From: Eli Friedman Date: Wed, 4 May 2011 19:54:24 +0000 (+0000) Subject: Teach MachineCSE how to do simple cross-block CSE involving physregs. This allows... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=49cec1d818d0c7d801e786c458896a60eb424524;p=oota-llvm.git Teach MachineCSE how to do simple cross-block CSE involving physregs. This allows, for example, eliminating duplicate cmpl's on x86. Part of rdar://problem/8259436 . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130862 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp index f97ccf65790..ff7062da30e 100644 --- a/lib/CodeGen/MachineCSE.cpp +++ b/lib/CodeGen/MachineCSE.cpp @@ -82,7 +82,8 @@ namespace { MachineBasicBlock::const_iterator E) const ; bool hasLivePhysRegDefUses(const MachineInstr *MI, const MachineBasicBlock *MBB, - SmallSet &PhysRefs) const; + SmallSet &PhysRefs, + SmallVector &PhysDefs) const; bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, SmallSet &PhysRefs) const; bool isCSECandidate(MachineInstr *MI); @@ -189,7 +190,8 @@ MachineCSE::isPhysDefTriviallyDead(unsigned Reg, /// instruction does not uses a physical register. bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI, const MachineBasicBlock *MBB, - SmallSet &PhysRefs) const { + SmallSet &PhysRefs, + SmallVector &PhysDefs) const{ MachineBasicBlock::const_iterator I = MI; I = llvm::next(I); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); @@ -206,6 +208,7 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI, if (MO.isDef() && (MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end()))) continue; + PhysDefs.push_back(Reg); PhysRefs.insert(Reg); for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) PhysRefs.insert(*Alias); @@ -216,35 +219,40 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI, bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, SmallSet &PhysRefs) const { - // For now conservatively returns false if the common subexpression is - // not in the same basic block as the given instruction. - MachineBasicBlock *MBB = MI->getParent(); - if (CSMI->getParent() != MBB) - return false; - MachineBasicBlock::const_iterator I = CSMI; I = llvm::next(I); - MachineBasicBlock::const_iterator E = MI; + // Look backward from MI to find CSMI. unsigned LookAheadLeft = LookAheadLimit; + MachineBasicBlock::const_reverse_iterator I(MI); + MachineBasicBlock::const_reverse_iterator E(MI->getParent()->rend()); while (LookAheadLeft) { - // Skip over dbg_value's. - while (I != E && I->isDebugValue()) - ++I; + while (LookAheadLeft && I != E) { + // Skip over dbg_value's. + while (I != E && I->isDebugValue()) + ++I; - if (I == E) - return true; + if (&*I == CSMI) + return true; - for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = I->getOperand(i); - if (!MO.isReg() || !MO.isDef()) - continue; - unsigned MOReg = MO.getReg(); - if (TargetRegisterInfo::isVirtualRegister(MOReg)) - continue; - if (PhysRefs.count(MOReg)) - return false; - } + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned MOReg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + continue; + if (PhysRefs.count(MOReg)) + return false; + } - --LookAheadLeft; - ++I; + --LookAheadLeft; + ++I; + } + // Go back another BB; for now, only go back at most one BB. + MachineBasicBlock *CSBB = CSMI->getParent(); + MachineBasicBlock *BB = MI->getParent(); + if (!CSBB->isSuccessor(BB) || BB->pred_size() != 1) + return false; + I = CSBB->rbegin(); + E = CSBB->rend(); } return false; @@ -395,7 +403,8 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { // used, then it's not safe to replace it with a common subexpression. // It's also not safe if the instruction uses physical registers. SmallSet PhysRefs; - if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs)) { + SmallVector DirectPhysRefs; + if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs, DirectPhysRefs)) { FoundCSE = false; // ... Unless the CS is local and it also defines the physical register @@ -448,6 +457,13 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { MRI->clearKillFlags(CSEPairs[i].second); } MI->eraseFromParent(); + if (!DirectPhysRefs.empty() && CSMI->getParent() != MBB) { + assert(CSMI->getParent()->isSuccessor(MBB)); + SmallVector::iterator PI = DirectPhysRefs.begin(), + PE = DirectPhysRefs.end(); + for (; PI != PE; ++PI) + MBB->addLiveIn(*PI); + } ++NumCSEs; if (!PhysRefs.empty()) ++NumPhysCSEs; diff --git a/test/CodeGen/Thumb2/thumb2-cbnz.ll b/test/CodeGen/Thumb2/thumb2-cbnz.ll index 10a4985d173..0ca97647d54 100644 --- a/test/CodeGen/Thumb2/thumb2-cbnz.ll +++ b/test/CodeGen/Thumb2/thumb2-cbnz.ll @@ -21,8 +21,8 @@ bb7: ; preds = %bb3 bb9: ; preds = %bb7 ; CHECK: cmp r0, #0 -; CHECK: cmp r0, #0 -; CHECK-NEXT: cbnz +; CHECK-NOT: cmp +; CHECK: cbnz %0 = tail call double @floor(double %b) nounwind readnone ; [#uses=0] br label %bb11 diff --git a/test/CodeGen/X86/cmp-redundant.ll b/test/CodeGen/X86/cmp-redundant.ll new file mode 100644 index 00000000000..d30ea3edd68 --- /dev/null +++ b/test/CodeGen/X86/cmp-redundant.ll @@ -0,0 +1,22 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s + +define i32 @cmp(i32* %aa, i32* %bb) nounwind readnone ssp { +entry: + %a = load i32* %aa + %b = load i32* %bb + %cmp = icmp sgt i32 %a, %b + br i1 %cmp, label %return, label %if.end +; CHECK: cmp: +; CHECK: cmpl +; CHECK: jg +if.end: ; preds = %entry +; CHECK-NOT: cmpl +; CHECK: cmov + %cmp4 = icmp slt i32 %a, %b + %. = select i1 %cmp4, i32 2, i32 111 + br label %return + +return: ; preds = %if.end, %entry + %retval.0 = phi i32 [ 1, %entry ], [ %., %if.end ] + ret i32 %retval.0 +}