diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 2b86e5fda7d..97a4834e93a 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -19,7 +19,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" namespace llvm { @@ -69,14 +68,6 @@ class RegScavenger { /// available, unset means the register is currently being used. BitVector RegsAvailable; - /// CurrDist - Distance from MBB entry to the current instruction MBBI. - /// - unsigned CurrDist; - - /// DistanceMap - Keep track the distance of a MI from the start of the - /// current basic block. - DenseMap DistanceMap; - public: RegScavenger() : MBB(NULL), NumPhysRegs(0), Tracking(false), @@ -112,6 +103,9 @@ public: bool isUsed(unsigned Reg) const { return !RegsAvailable[Reg]; } bool isUnused(unsigned Reg) const { return RegsAvailable[Reg]; } + /// isAliasUsed - Is Reg or an alias currently in use? + bool isAliasUsed(unsigned Reg) const; + /// getRegsUsed - return all registers currently in use in used. void getRegsUsed(BitVector &used, bool includeReserved); @@ -156,10 +150,6 @@ private: /// emergency spill slot. Mark it used. void restoreScavengedReg(); - MachineInstr *findFirstUse(MachineBasicBlock *MBB, - MachineBasicBlock::iterator I, unsigned Reg, - unsigned &Dist); - /// Add Reg and all its sub-registers to BV. void addRegWithSubRegs(BitVector &BV, unsigned Reg); diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 93c0eb00944..f012ff882e8 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -25,6 +25,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" @@ -48,12 +49,19 @@ void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) { RegsAvailable.set(SubReg); } +bool RegScavenger::isAliasUsed(unsigned Reg) const { + if (isUsed(Reg)) + return true; + for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R) + if (isUsed(*R)) + return true; + return false; +} + void RegScavenger::initRegState() { ScavengedReg = 0; ScavengedRC = NULL; ScavengeRestore = NULL; - CurrDist = 0; - DistanceMap.clear(); // All registers started out unused. RegsAvailable.set(); @@ -176,7 +184,6 @@ void RegScavenger::forward() { } MachineInstr *MI = MBBI; - DistanceMap.insert(std::make_pair(MI, CurrDist++)); if (MI == ScavengeRestore) { ScavengedReg = 0; @@ -286,12 +293,25 @@ unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RegClass, return (Reg == -1) ? 0 : Reg; } +/// DistanceMap - Keep track the distance of an MI from the current position. +typedef DenseMap DistanceMap; + +/// Build a distance map for instructions from I to E. +static void buildDistanceMap(DistanceMap &DM, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E) { + DM.clear(); + for (unsigned d = 0; I != E; ++I, ++d) + DM.insert(DistanceMap::value_type(I, d)); +} + /// findFirstUse - Calculate the distance to the first use of the -/// specified register. -MachineInstr* -RegScavenger::findFirstUse(MachineBasicBlock *MBB, - MachineBasicBlock::iterator I, unsigned Reg, - unsigned &Dist) { +/// specified register in the range covered by DM. +static MachineInstr *findFirstUse(const MachineBasicBlock *MBB, + const DistanceMap &DM, + unsigned Reg, + unsigned &Dist) { + const MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo(); MachineInstr *UseMI = 0; Dist = ~0U; for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(Reg), @@ -299,19 +319,10 @@ RegScavenger::findFirstUse(MachineBasicBlock *MBB, MachineInstr *UDMI = &*RI; if (UDMI->getParent() != MBB) continue; - DenseMap::iterator DI = DistanceMap.find(UDMI); - if (DI == DistanceMap.end()) { - // If it's not in map, it's below current MI, let's initialize the - // map. - I = next(I); - unsigned Dist = CurrDist + 1; - while (I != MBB->end()) { - DistanceMap.insert(std::make_pair(I, Dist++)); - I = next(I); - } - } - DI = DistanceMap.find(UDMI); - if (DI->second > CurrDist && DI->second < Dist) { + DistanceMap::const_iterator DI = DM.find(UDMI); + if (DI == DM.end()) + continue; + if (DI->second < Dist) { Dist = DI->second; UseMI = UDMI; } @@ -338,6 +349,10 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, Candidates.reset(MO.getReg()); } + // Prepare to call findFirstUse() a number of times. + DistanceMap DM; + buildDistanceMap(DM, I, MBB->end()); + // Find the register whose use is furthest away. unsigned SReg = 0; unsigned MaxDist = 0; @@ -345,15 +360,23 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, int Reg = Candidates.find_first(); while (Reg != -1) { unsigned Dist; - MachineInstr *UseMI = findFirstUse(MBB, I, Reg, Dist); + MachineInstr *UseMI = findFirstUse(MBB, DM, Reg, Dist); for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { unsigned AsDist; - MachineInstr *AsUseMI = findFirstUse(MBB, I, *AS, AsDist); + MachineInstr *AsUseMI = findFirstUse(MBB, DM, *AS, AsDist); if (AsDist < Dist) { Dist = AsDist; UseMI = AsUseMI; } } + + // If we found an unused register that is defined by a later instruction, + // there is no reason to spill it. We have probably found a callee-saved + // register that has been saved in the prologue, but happens to be unused at + // this point. + if (!isAliasUsed(Reg) && UseMI != NULL) + return Reg; + if (Dist >= MaxDist) { MaxDist = Dist; MaxUseMI = UseMI; diff --git a/test/CodeGen/Blackfin/2009-08-11-RegScavenger-CSR.ll b/test/CodeGen/Blackfin/2009-08-11-RegScavenger-CSR.ll new file mode 100644 index 00000000000..ae08f0f1d09 --- /dev/null +++ b/test/CodeGen/Blackfin/2009-08-11-RegScavenger-CSR.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | llc -march=bfin -verify-machineinstrs + +declare i64 @llvm.cttz.i64(i64) nounwind readnone + +declare i16 @llvm.cttz.i16(i16) nounwind readnone + +declare i8 @llvm.cttz.i8(i8) nounwind readnone + +define void @cttztest(i8 %A, i16 %B, i32 %C, i64 %D, i8* %AP, i16* %BP, i32* %CP, i64* %DP) { + %a = call i8 @llvm.cttz.i8(i8 %A) ; [#uses=1] + %b = call i16 @llvm.cttz.i16(i16 %B) ; [#uses=1] + %d = call i64 @llvm.cttz.i64(i64 %D) ; [#uses=1] + store i8 %a, i8* %AP + store i16 %b, i16* %BP + store i64 %d, i64* %DP + ret void +}