Fix PostRA antidependence breaker.

Avoid using the same register for two def operands or and earlyclobber
def and use operand. This fixes PR8986 and improves on the prior fix
for rdar://problem/8959122.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125089 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2011-02-08 17:39:46 +00:00
parent 75396a9988
commit bc4bd92d52
2 changed files with 49 additions and 11 deletions

View File

@ -325,17 +325,55 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr *MI,
}
}
// Check all machine instructions that define the antidependent register.
// Return true if any of these instructions define the new register.
// Check all machine operands that reference the antidependent register and must
// be replaced by NewReg. Return true if any of their parent instructions may
// clobber the new register.
//
// Note: AntiDepReg may be referenced by a two-address instruction such that
// it's use operand is tied to a def operand. We guard against the case in which
// the two-address instruction also defines NewReg, as may happen with
// pre/postincrement loads. In this case, both the use and def operands are in
// RegRefs because the def is inserted by PrescanInstruction and not erased
// during ScanInstruction. So checking for an instructions with definitions of
// both NewReg and AntiDepReg covers it.
bool
CriticalAntiDepBreaker::isNewRegModifiedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg)
CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg)
{
for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) {
MachineOperand *MO = I->second;
if (MO->getParent()->modifiesRegister(NewReg, TRI))
MachineOperand *RefOper = I->second;
// Don't allow the instruction defining AntiDepReg to earlyclobber its
// operands, in case they may be assigned to NewReg. In this case antidep
// breaking must fail, but it's too rare to bother optimizing.
if (RefOper->isDef() && RefOper->isEarlyClobber())
return true;
// Handle cases in which this instructions defines NewReg.
MachineInstr *MI = RefOper->getParent();
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &CheckOper = MI->getOperand(i);
if (!CheckOper.isReg() || !CheckOper.isDef() ||
CheckOper.getReg() != NewReg)
continue;
// Don't allow the instruction to define NewReg and AntiDepReg.
// When AntiDepReg is renamed it will be an illegal op.
if (RefOper->isDef())
return true;
// Don't allow an instruction using AntiDepReg to be earlyclobbered by
// NewReg
if (CheckOper.isEarlyClobber())
return true;
// Don't allow inline asm to define NewReg at all. Who know what it's
// doing with it.
if (MI->isInlineAsm())
return true;
}
}
return false;
}
@ -361,7 +399,7 @@ CriticalAntiDepBreaker::findSuitableFreeRegister(RegRefIter RegRefBegin,
// If any instructions that define AntiDepReg also define the NewReg, it's
// not suitable. For example, Instruction with multiple definitions can
// result in this condition.
if (isNewRegModifiedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue;
if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue;
// If NewReg is dead and NewReg's most recent def is not before
// AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg.
assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u))

View File

@ -92,9 +92,9 @@ class TargetRegisterInfo;
private:
void PrescanInstruction(MachineInstr *MI);
void ScanInstruction(MachineInstr *MI, unsigned Count);
bool isNewRegModifiedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg);
bool isNewRegClobberedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg);
unsigned findSuitableFreeRegister(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned AntiDepReg,