diff options
author | Evan Cheng <evan.cheng@apple.com> | 2010-03-04 01:33:55 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2010-03-04 01:33:55 +0000 |
commit | b3958e80324884e3d1c1e198a50f212bae0c3b77 (patch) | |
tree | c3cb03465fd875167d172b27d7383e6a9405eacf /lib/CodeGen/MachineCSE.cpp | |
parent | 6b4ae7172529503bd28333f488857c0d4fdc3e39 (diff) | |
download | llvm-b3958e80324884e3d1c1e198a50f212bae0c3b77.tar.gz llvm-b3958e80324884e3d1c1e198a50f212bae0c3b77.tar.bz2 llvm-b3958e80324884e3d1c1e198a50f212bae0c3b77.tar.xz |
Look ahead a bit to determine if a physical register def that is not marked dead is really alive. This is necessary to catch a lot of common cse opportunities for targets like x86.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97706 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/MachineCSE.cpp')
-rw-r--r-- | lib/CodeGen/MachineCSE.cpp | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp index d542cc9969..90704e354f 100644 --- a/lib/CodeGen/MachineCSE.cpp +++ b/lib/CodeGen/MachineCSE.cpp @@ -31,6 +31,7 @@ STATISTIC(NumCSEs, "Number of common subexpression eliminated"); namespace { class MachineCSE : public MachineFunctionPass { const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; MachineRegisterInfo *MRI; MachineDominatorTree *DT; public: @@ -51,6 +52,10 @@ namespace { ScopedHashTable<MachineInstr*, unsigned, MachineInstrExpressionTrait> VNT; SmallVector<MachineInstr*, 64> Exps; + bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB); + bool isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E); bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB); bool ProcessBlock(MachineDomTreeNode *Node); }; @@ -93,7 +98,39 @@ bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI, return Changed; } -static bool hasLivePhysRegDefUse(MachineInstr *MI) { +bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E) { + unsigned LookAheadLeft = 5; + while (LookAheadLeft--) { + if (I == E) + // Reached end of block, register is obviously dead. + return true; + + if (I->isDebugValue()) + continue; + bool SeenDef = false; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + if (!TRI->regsOverlap(MO.getReg(), Reg)) + continue; + if (MO.isUse()) + return false; + SeenDef = true; + } + if (SeenDef) + // See a def of Reg (or an alias) before encountering any use, it's + // trivially dead. + return true; + ++I; + } + return false; +} + +bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){ + unsigned PhysDef = 0; for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg()) @@ -101,10 +138,26 @@ static bool hasLivePhysRegDefUse(MachineInstr *MI) { unsigned Reg = MO.getReg(); if (!Reg) 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) && - !(MO.isDef() && MO.isDead())) + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) + // Can't touch anything to read a physical register. + return true; + if (MO.isDead()) + // If the def is dead, it's ok. + continue; + // Ok, this is a physical register def that's not marked "dead". That's + // common since this pass is run before livevariables. We can scan + // forward a few instructions and check if it is obviously dead. + if (PhysDef) + // Multiple physical register defs. These are rare, forget about it. + return true; + PhysDef = Reg; + } + } + + if (PhysDef) { + MachineBasicBlock::iterator I = MI; I = llvm::next(I); + if (!isPhysDefTriviallyDead(PhysDef, I, MBB->end())) return true; } return false; @@ -135,10 +188,11 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { if (PerformTrivialCoalescing(MI, MBB)) FoundCSE = VNT.count(MI); } + // FIXME: commute commutable instructions? // If the instruction defines a physical register and the value *may* be // used, then it's not safe to replace it with a common subexpression. - if (FoundCSE && hasLivePhysRegDefUse(MI)) + if (FoundCSE && hasLivePhysRegDefUse(MI, MBB)) FoundCSE = false; if (!FoundCSE) { @@ -180,6 +234,7 @@ bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); MRI = &MF.getRegInfo(); DT = &getAnalysis<MachineDominatorTree>(); return ProcessBlock(DT->getRootNode()); |