mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
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:
parent
75396a9988
commit
bc4bd92d52
@ -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))
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user