Machine CSE work in progress. It's doing some CSE now. But implicit def of physical registers are getting in the way.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97664 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2010-03-03 21:20:05 +00:00
parent 1423c70b8f
commit 16b48b8a05

View File

@ -25,6 +25,9 @@
using namespace llvm; using namespace llvm;
STATISTIC(NumCoalesces, "Number of copies coalesced");
STATISTIC(NumCSEs, "Number of common subexpression eliminated");
namespace llvm { namespace llvm {
template<> struct DenseMapInfo<MachineInstr*> { template<> struct DenseMapInfo<MachineInstr*> {
static inline MachineInstr *getEmptyKey() { static inline MachineInstr *getEmptyKey() {
@ -93,8 +96,6 @@ namespace {
const TargetInstrInfo *TII; const TargetInstrInfo *TII;
MachineRegisterInfo *MRI; MachineRegisterInfo *MRI;
MachineDominatorTree *DT; MachineDominatorTree *DT;
ScopedHashTable<MachineInstr*, unsigned> VNT;
unsigned CurrVN;
public: public:
static char ID; // Pass identification static char ID; // Pass identification
MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {} MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
@ -109,6 +110,10 @@ namespace {
} }
private: private:
unsigned CurrVN;
ScopedHashTable<MachineInstr*, unsigned> VNT;
SmallVector<MachineInstr*, 64> Exps;
bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB); bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
bool ProcessBlock(MachineDomTreeNode *Node); bool ProcessBlock(MachineDomTreeNode *Node);
}; };
@ -125,22 +130,28 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
bool Changed = false; bool Changed = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i); MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.isUse()) { if (!MO.isReg() || !MO.isUse())
continue;
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg)) if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
continue; continue;
if (!MRI->hasOneUse(Reg))
// Only coalesce single use copies. This ensure the copy will be
// deleted.
continue;
MachineInstr *DefMI = MRI->getVRegDef(Reg); MachineInstr *DefMI = MRI->getVRegDef(Reg);
if (DefMI->getParent() == MBB) { if (DefMI->getParent() != MBB)
continue;
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
TargetRegisterInfo::isVirtualRegister(SrcReg) && TargetRegisterInfo::isVirtualRegister(SrcReg) &&
!SrcSubIdx && !DstSubIdx) { !SrcSubIdx && !DstSubIdx) {
MO.setReg(SrcReg); MO.setReg(SrcReg);
DefMI->eraseFromParent();
++NumCoalesces;
Changed = true; Changed = true;
} }
} }
}
}
return Changed; return Changed;
} }
@ -153,6 +164,8 @@ static bool hasLivePhysRegDefUse(MachineInstr *MI) {
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (!Reg) if (!Reg)
continue; continue;
// FIXME: This is obviously overly conservative. On x86 lots of instructions
// will def EFLAGS and they are not marked dead at this point.
if (TargetRegisterInfo::isPhysicalRegister(Reg) && if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
!(MO.isDef() && MO.isDead())) !(MO.isDef() && MO.isDead()))
return true; return true;
@ -165,16 +178,17 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT); ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
MachineBasicBlock *MBB = Node->getBlock(); MachineBasicBlock *MBB = Node->getBlock();
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) {
++I) {
MachineInstr *MI = &*I; MachineInstr *MI = &*I;
++I;
bool SawStore = false; bool SawStore = false;
if (!MI->isSafeToMove(TII, 0, SawStore)) if (!MI->isSafeToMove(TII, 0, SawStore))
continue; continue;
// Ignore copies or instructions that read / write physical registers // Ignore copies or instructions that read / write physical registers
// (except for dead defs of physical registers). // (except for dead defs of physical registers).
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx)) if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) ||
MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg())
continue; continue;
if (hasLivePhysRegDefUse(MI)) if (hasLivePhysRegDefUse(MI))
continue; continue;
@ -186,10 +200,33 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
FoundCSE = VNT.count(MI); FoundCSE = VNT.count(MI);
} }
if (FoundCSE) if (!FoundCSE) {
DEBUG(dbgs() << "Found a common subexpression: " << *MI); VNT.insert(MI, CurrVN++);
else Exps.push_back(MI);
VNT.insert(MI, ++CurrVN); continue;
}
// Found a common subexpression, eliminate it.
unsigned CSVN = VNT.lookup(MI);
MachineInstr *CSMI = Exps[CSVN];
DEBUG(dbgs() << "Examining: " << *MI);
DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI);
unsigned NumDefs = MI->getDesc().getNumDefs();
for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isDef())
continue;
unsigned OldReg = MO.getReg();
unsigned NewReg = CSMI->getOperand(i).getReg();
assert(OldReg != NewReg &&
TargetRegisterInfo::isVirtualRegister(OldReg) &&
TargetRegisterInfo::isVirtualRegister(NewReg) &&
"Do not CSE physical register defs!");
MRI->replaceRegWith(OldReg, NewReg);
--NumDefs;
}
MI->eraseFromParent();
++NumCSEs;
} }
// Recursively call ProcessBlock with childred. // Recursively call ProcessBlock with childred.