Only check for PHI uses inside the current loop.

Hoisting a value that is used by a PHI in the loop will introduce a
copy because the live range is extended to cross the PHI.

The same applies to PHIs in exit blocks.

Also use this opportunity to make HasLoopPHIUse() non-recursive.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154454 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2012-04-11 00:00:26 +00:00
parent 89cdaf46ec
commit 8b560b8c48

View File

@ -80,6 +80,14 @@ namespace {
MachineLoop *CurLoop; // The current loop we are working on. MachineLoop *CurLoop; // The current loop we are working on.
MachineBasicBlock *CurPreheader; // The preheader for CurLoop. MachineBasicBlock *CurPreheader; // The preheader for CurLoop.
// Exit blocks for CurLoop.
SmallVector<MachineBasicBlock*, 8> ExitBlocks;
bool isExitBlock(const MachineBasicBlock *MBB) const {
return std::find(ExitBlocks.begin(), ExitBlocks.end(), MBB) !=
ExitBlocks.end();
}
// Track 'estimated' register pressure. // Track 'estimated' register pressure.
SmallSet<unsigned, 32> RegSeen; SmallSet<unsigned, 32> RegSeen;
SmallVector<unsigned, 8> RegPressure; SmallVector<unsigned, 8> RegPressure;
@ -182,9 +190,9 @@ namespace {
/// ///
bool IsLoopInvariantInst(MachineInstr &I); bool IsLoopInvariantInst(MachineInstr &I);
/// HasAnyPHIUse - Return true if the specified register is used by any /// HasLoopPHIUse - Return true if the specified instruction is used by any
/// phi node. /// phi node in the current loop.
bool HasAnyPHIUse(unsigned Reg) const; bool HasLoopPHIUse(const MachineInstr *MI) const;
/// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop, return true if the target considered /// and an use in the current loop, return true if the target considered
@ -348,6 +356,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
while (!Worklist.empty()) { while (!Worklist.empty()) {
CurLoop = Worklist.pop_back_val(); CurLoop = Worklist.pop_back_val();
CurPreheader = 0; CurPreheader = 0;
ExitBlocks.clear();
// If this is done before regalloc, only visit outer-most preheader-sporting // If this is done before regalloc, only visit outer-most preheader-sporting
// loops. // loops.
@ -356,6 +365,8 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
continue; continue;
} }
CurLoop->getExitBlocks(ExitBlocks);
if (!PreRegAlloc) if (!PreRegAlloc)
HoistRegionPostRA(); HoistRegionPostRA();
else { else {
@ -955,22 +966,40 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) {
} }
/// HasAnyPHIUse - Return true if the specified register is used by any /// HasLoopPHIUse - Return true if the specified instruction is used by a
/// phi node. /// phi node and hoisting it could cause a copy to be inserted.
bool MachineLICM::HasAnyPHIUse(unsigned Reg) const { bool MachineLICM::HasLoopPHIUse(const MachineInstr *MI) const {
SmallVector<const MachineInstr*, 8> Work(1, MI);
do {
MI = Work.pop_back_val();
for (ConstMIOperands MO(MI); MO.isValid(); ++MO) {
if (!MO->isReg() || !MO->isDef())
continue;
unsigned Reg = MO->getReg();
if (!TargetRegisterInfo::isVirtualRegister(Reg))
continue;
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg),
UE = MRI->use_end(); UI != UE; ++UI) { UE = MRI->use_end(); UI != UE; ++UI) {
MachineInstr *UseMI = &*UI; MachineInstr *UseMI = &*UI;
if (UseMI->isPHI()) // A PHI may cause a copy to be inserted.
if (UseMI->isPHI()) {
// A PHI inside the loop causes a copy because the live range of Reg is
// extended across the PHI.
if (CurLoop->contains(UseMI))
return true; return true;
// Look pass copies as well. // A PHI in an exit block can cause a copy to be inserted if the PHI
if (UseMI->isCopy()) { // has multiple predecessors in the loop with different values.
unsigned Def = UseMI->getOperand(0).getReg(); // For now, approximate by rejecting all exit blocks.
if (TargetRegisterInfo::isVirtualRegister(Def) && if (isExitBlock(UseMI->getParent()))
HasAnyPHIUse(Def))
return true; return true;
continue;
}
// Look past copies as well.
if (UseMI->isCopy() && CurLoop->contains(UseMI))
Work.push_back(UseMI);
} }
} }
} while (!Work.empty());
return false; return false;
} }
@ -1182,15 +1211,10 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) {
return false; return false;
} }
// If result(s) of this instruction is used by PHIs outside of the loop, then // If result(s) of this instruction is used by PHIs inside the loop, then
// don't hoist it if the instruction because it will introduce an extra copy. // don't hoist it because it will introduce an extra copy.
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { if (HasLoopPHIUse(&MI))
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.isDef())
continue;
if (HasAnyPHIUse(MO.getReg()))
return false; return false;
}
return true; return true;
} }