X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FRegisterScavenging.cpp;h=e8329781ac3d7cca5c4b43ec9ac73c9b1db5d439;hb=56867520990a4fea1353d55f71bb74a0126554e6;hp=aeed72cef52e955f6f97d5044d6faabaf00de54f;hpb=749c6f6b5ed301c84aac562e414486549d7b98eb;p=oota-llvm.git diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index aeed72cef52..e8329781ac3 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// // // This file implements the machine register scavenger. It can provide -// information such as unused register at any point in a machine basic block. -// It also provides a mechanism to make registers availbale by evicting them -// to spill slots. +// information, such as unused registers, at any point in a machine basic block. +// It also provides a mechanism to make registers available by evicting them to +// spill slots. // //===----------------------------------------------------------------------===// @@ -19,31 +19,88 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Target/MRegisterInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" using namespace llvm; +/// RedefinesSuperRegPart - Return true if the specified register is redefining +/// part of a super-register. +static bool RedefinesSuperRegPart(const MachineInstr *MI, unsigned SubReg, + const TargetRegisterInfo *TRI) { + bool SeenSuperUse = false; + bool SeenSuperDef = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isRegister()) + continue; + if (TRI->isSuperRegister(SubReg, MO.getReg())) { + if (MO.isUse()) + SeenSuperUse = true; + else if (MO.isImplicit()) + SeenSuperDef = true; + } + } + + return SeenSuperDef && SeenSuperUse; +} + +static bool RedefinesSuperRegPart(const MachineInstr *MI, + const MachineOperand &MO, + const TargetRegisterInfo *TRI) { + assert(MO.isRegister() && MO.isDef() && "Not a register def!"); + return RedefinesSuperRegPart(MI, MO.getReg(), TRI); +} + +/// setUsed - Set the register and its sub-registers as being used. +void RegScavenger::setUsed(unsigned Reg, bool ImpDef) { + RegsAvailable.reset(Reg); + ImplicitDefed[Reg] = ImpDef; + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + RegsAvailable.reset(SubReg); + ImplicitDefed[SubReg] = ImpDef; + } +} + +/// setUnused - Set the register and its sub-registers as being unused. +void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) { + RegsAvailable.set(Reg); + ImplicitDefed.reset(Reg); + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + if (!RedefinesSuperRegPart(MI, Reg, TRI)) { + RegsAvailable.set(SubReg); + ImplicitDefed.reset(SubReg); + } +} + void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { const MachineFunction &MF = *mbb->getParent(); const TargetMachine &TM = MF.getTarget(); TII = TM.getInstrInfo(); - RegInfo = TM.getRegisterInfo(); + TRI = TM.getRegisterInfo(); + MRI = &MF.getRegInfo(); - assert((NumPhysRegs == 0 || NumPhysRegs == RegInfo->getNumRegs()) && + assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) && "Target changed?"); if (!MBB) { - NumPhysRegs = RegInfo->getNumRegs(); + NumPhysRegs = TRI->getNumRegs(); RegsAvailable.resize(NumPhysRegs); + ImplicitDefed.resize(NumPhysRegs); // Create reserved registers bitvector. - ReservedRegs = RegInfo->getReservedRegs(MF); + ReservedRegs = TRI->getReservedRegs(MF); // Create callee-saved registers bitvector. CalleeSavedRegs.resize(NumPhysRegs); - const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); + const unsigned *CSRegs = TRI->getCalleeSavedRegs(); if (CSRegs != NULL) for (unsigned i = 0; CSRegs[i]; ++i) CalleeSavedRegs.set(CSRegs[i]); @@ -73,14 +130,48 @@ void RegScavenger::restoreScavengedReg() { return; TII->loadRegFromStackSlot(*MBB, MBBI, ScavengedReg, - ScavengingFrameIndex, ScavengedRC); + ScavengingFrameIndex, ScavengedRC); MachineBasicBlock::iterator II = prior(MBBI); - RegInfo->eliminateFrameIndex(II, 0, this); + TRI->eliminateFrameIndex(II, 0, this); setUsed(ScavengedReg); ScavengedReg = 0; ScavengedRC = NULL; } +/// isLiveInButUnusedBefore - Return true if register is livein the MBB not +/// not used before it reaches the MI that defines register. +static bool isLiveInButUnusedBefore(unsigned Reg, MachineInstr *MI, + MachineBasicBlock *MBB, + const TargetRegisterInfo *TRI, + MachineRegisterInfo* MRI) { + // First check if register is livein. + bool isLiveIn = false; + for (MachineBasicBlock::const_livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) + if (Reg == *I || TRI->isSuperRegister(Reg, *I)) { + isLiveIn = true; + break; + } + if (!isLiveIn) + return false; + + // Is there any use of it before the specified MI? + SmallPtrSet UsesInMBB; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (UseMI->getParent() == MBB) + UsesInMBB.insert(UseMI); + } + if (UsesInMBB.empty()) + return true; + + for (MachineBasicBlock::iterator I = MBB->begin(), E = MI; I != E; ++I) + if (UsesInMBB.count(&*I)) + return false; + return true; +} + void RegScavenger::forward() { // Move ptr forward. if (!Tracking) { @@ -105,9 +196,10 @@ void RegScavenger::forward() { const MachineOperand &MO = MI->getOperand(i); if (!MO.isRegister() || !MO.isUse()) continue; + unsigned Reg = MO.getReg(); - if (Reg == 0) - continue; + if (Reg == 0) continue; + if (!isUsed(Reg)) { // Register has been scavenged. Restore it! if (Reg != ScavengedReg) @@ -115,32 +207,55 @@ void RegScavenger::forward() { else restoreScavengedReg(); } - if (MO.isKill() && !isReserved(Reg)) + + if (MO.isKill() && !isReserved(Reg)) { ChangedRegs.set(Reg); + + // Mark sub-registers as changed if they aren't defined in the same + // instruction. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + ChangedRegs.set(SubReg); + } } + // Change states of all registers after all the uses are processed to guard // against multiple uses. setUnused(ChangedRegs); // Process defs. + bool IsImpDef = MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); + if (!MO.isRegister() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + // If it's dead upon def, then it is now free. if (MO.isDead()) { - setUnused(Reg); + setUnused(Reg, MI); continue; } + // Skip two-address destination operand. if (TID.findTiedToSrcOperand(i) != -1) { assert(isUsed(Reg) && "Using an undefined register!"); continue; } - assert((isUnused(Reg) || isReserved(Reg)) && + + // Skip is this is merely redefining part of a super-register. + if (RedefinesSuperRegPart(MI, MO, TRI)) + continue; + + // Implicit def is allowed to "re-define" any register. Similarly, + // implicitly defined registers can be clobbered. + assert((isReserved(Reg) || isUnused(Reg) || + IsImpDef || isImplicitlyDefined(Reg) || + isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) && "Re-defining a live register!"); - setUsed(Reg); + setUsed(Reg, IsImpDef); } } @@ -163,7 +278,7 @@ void RegScavenger::backward() { unsigned Reg = MO.getReg(); assert(isUsed(Reg)); if (!isReserved(Reg)) - setUnused(Reg); + setUnused(Reg, MI); } // Process uses. @@ -177,6 +292,11 @@ void RegScavenger::backward() { continue; assert(isUnused(Reg) || isReserved(Reg)); ChangedRegs.set(Reg); + + // Set the sub-registers as "used". + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + ChangedRegs.set(SubReg); } setUsed(ChangedRegs); } @@ -231,12 +351,13 @@ unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass, /// calcDistanceToUse - Calculate the distance to the first use of the /// specified register. static unsigned calcDistanceToUse(MachineBasicBlock *MBB, - MachineBasicBlock::iterator I, unsigned Reg) { + MachineBasicBlock::iterator I, unsigned Reg, + const TargetRegisterInfo *TRI) { unsigned Dist = 0; I = next(I); while (I != MBB->end()) { Dist++; - if (I->findRegisterUseOperandIdx(Reg) != -1) + if (I->readsRegister(Reg, TRI)) return Dist; I = next(I); } @@ -261,12 +382,12 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, Candidates.reset(MO.getReg()); } - // Find the register whose use is furtherest aaway. + // Find the register whose use is furthest away. unsigned SReg = 0; unsigned MaxDist = 0; int Reg = Candidates.find_first(); while (Reg != -1) { - unsigned Dist = calcDistanceToUse(MBB, I, Reg); + unsigned Dist = calcDistanceToUse(MBB, I, Reg, TRI); if (Dist >= MaxDist) { MaxDist = Dist; SReg = Reg; @@ -277,14 +398,14 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, if (ScavengedReg != 0) { // First restore previously scavenged register. TII->loadRegFromStackSlot(*MBB, I, ScavengedReg, - ScavengingFrameIndex, ScavengedRC); + ScavengingFrameIndex, ScavengedRC); MachineBasicBlock::iterator II = prior(I); - RegInfo->eliminateFrameIndex(II, SPAdj, this); + TRI->eliminateFrameIndex(II, SPAdj, this); } TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC); MachineBasicBlock::iterator II = prior(I); - RegInfo->eliminateFrameIndex(II, SPAdj, this); + TRI->eliminateFrameIndex(II, SPAdj, this); ScavengedReg = SReg; ScavengedRC = RC;