Re-commit r130862 with a minor change to avoid an iterator running off the edge in some cases.

Original message:

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 .

llvm-svn: 130877
This commit is contained in:
Eli Friedman 2011-05-04 22:10:36 +00:00
parent c7e4fa7c19
commit 0fe4608af2
3 changed files with 74 additions and 30 deletions

View File

@ -33,6 +33,8 @@ STATISTIC(NumCoalesces, "Number of copies coalesced");
STATISTIC(NumCSEs, "Number of common subexpression eliminated"); STATISTIC(NumCSEs, "Number of common subexpression eliminated");
STATISTIC(NumPhysCSEs, STATISTIC(NumPhysCSEs,
"Number of physreg referencing common subexpr eliminated"); "Number of physreg referencing common subexpr eliminated");
STATISTIC(NumCrossBlockPhysCSEs,
"Number of physreg common subexprs cross-block eliminated");
STATISTIC(NumCommutes, "Number of copies coalesced after commuting"); STATISTIC(NumCommutes, "Number of copies coalesced after commuting");
namespace { namespace {
@ -82,7 +84,8 @@ namespace {
MachineBasicBlock::const_iterator E) const ; MachineBasicBlock::const_iterator E) const ;
bool hasLivePhysRegDefUses(const MachineInstr *MI, bool hasLivePhysRegDefUses(const MachineInstr *MI,
const MachineBasicBlock *MBB, const MachineBasicBlock *MBB,
SmallSet<unsigned,8> &PhysRefs) const; SmallSet<unsigned,8> &PhysRefs,
SmallVector<unsigned,8> &PhysDefs) const;
bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
SmallSet<unsigned,8> &PhysRefs) const; SmallSet<unsigned,8> &PhysRefs) const;
bool isCSECandidate(MachineInstr *MI); bool isCSECandidate(MachineInstr *MI);
@ -189,7 +192,8 @@ MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
/// instruction does not uses a physical register. /// instruction does not uses a physical register.
bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI, bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
const MachineBasicBlock *MBB, const MachineBasicBlock *MBB,
SmallSet<unsigned,8> &PhysRefs) const { SmallSet<unsigned,8> &PhysRefs,
SmallVector<unsigned,8> &PhysDefs) const{
MachineBasicBlock::const_iterator I = MI; I = llvm::next(I); MachineBasicBlock::const_iterator I = MI; I = llvm::next(I);
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i); const MachineOperand &MO = MI->getOperand(i);
@ -206,6 +210,7 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
if (MO.isDef() && if (MO.isDef() &&
(MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end()))) (MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end())))
continue; continue;
PhysDefs.push_back(Reg);
PhysRefs.insert(Reg); PhysRefs.insert(Reg);
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias)
PhysRefs.insert(*Alias); PhysRefs.insert(*Alias);
@ -216,20 +221,20 @@ bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
SmallSet<unsigned,8> &PhysRefs) const { SmallSet<unsigned,8> &PhysRefs) const {
// For now conservatively returns false if the common subexpression is // Look backward from MI to find CSMI.
// 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;
unsigned LookAheadLeft = LookAheadLimit; unsigned LookAheadLeft = LookAheadLimit;
MachineBasicBlock *CurBB = MI->getParent();
MachineBasicBlock::const_reverse_iterator I(MI);
MachineBasicBlock::const_reverse_iterator E(CurBB->rend());
while (LookAheadLeft) { while (LookAheadLeft) {
while (LookAheadLeft && I != E) {
// Skip over dbg_value's. // Skip over dbg_value's.
while (I != E && I->isDebugValue()) while (I != E && I->isDebugValue())
++I; ++I;
if (I == E) if (I == E) break;
if (&*I == CSMI)
return true; return true;
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
@ -246,6 +251,14 @@ bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
--LookAheadLeft; --LookAheadLeft;
++I; ++I;
} }
// Go back another BB; for now, only go back at most one BB.
MachineBasicBlock *CSBB = CSMI->getParent();
if (!CSBB->isSuccessor(CurBB) || CurBB->pred_size() != 1)
return false;
CurBB = CSBB;
I = CSBB->rbegin();
E = CSBB->rend();
}
return false; return false;
} }
@ -395,7 +408,8 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
// used, then it's not safe to replace it with a common subexpression. // used, then it's not safe to replace it with a common subexpression.
// It's also not safe if the instruction uses physical registers. // It's also not safe if the instruction uses physical registers.
SmallSet<unsigned,8> PhysRefs; SmallSet<unsigned,8> PhysRefs;
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs)) { SmallVector<unsigned,8> DirectPhysRefs;
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs, DirectPhysRefs)) {
FoundCSE = false; FoundCSE = false;
// ... Unless the CS is local and it also defines the physical register // ... Unless the CS is local and it also defines the physical register
@ -448,6 +462,14 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
MRI->clearKillFlags(CSEPairs[i].second); MRI->clearKillFlags(CSEPairs[i].second);
} }
MI->eraseFromParent(); MI->eraseFromParent();
if (!DirectPhysRefs.empty() && CSMI->getParent() != MBB) {
assert(CSMI->getParent()->isSuccessor(MBB));
++NumCrossBlockPhysCSEs;
SmallVector<unsigned,8>::iterator PI = DirectPhysRefs.begin(),
PE = DirectPhysRefs.end();
for (; PI != PE; ++PI)
MBB->addLiveIn(*PI);
}
++NumCSEs; ++NumCSEs;
if (!PhysRefs.empty()) if (!PhysRefs.empty())
++NumPhysCSEs; ++NumPhysCSEs;

View File

@ -21,8 +21,8 @@ bb7: ; preds = %bb3
bb9: ; preds = %bb7 bb9: ; preds = %bb7
; CHECK: cmp r0, #0 ; CHECK: cmp r0, #0
; CHECK: cmp r0, #0 ; CHECK-NOT: cmp
; CHECK-NEXT: cbnz ; CHECK: cbnz
%0 = tail call double @floor(double %b) nounwind readnone ; <double> [#uses=0] %0 = tail call double @floor(double %b) nounwind readnone ; <double> [#uses=0]
br label %bb11 br label %bb11

View File

@ -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
}