aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h16
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp69
-rw-r--r--test/CodeGen/Blackfin/2009-08-11-RegScavenger-CSR.ll17
3 files changed, 66 insertions, 36 deletions
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 2b86e5f..97a4834 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<MachineInstr*, unsigned> 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 93c0eb0..f012ff8 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<MachineInstr*, unsigned> 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<MachineInstr*, unsigned>::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 0000000..ae08f0f
--- /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) ; <i8> [#uses=1]
+ %b = call i16 @llvm.cttz.i16(i16 %B) ; <i16> [#uses=1]
+ %d = call i64 @llvm.cttz.i64(i64 %D) ; <i64> [#uses=1]
+ store i8 %a, i8* %AP
+ store i16 %b, i16* %BP
+ store i64 %d, i64* %DP
+ ret void
+}