aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CriticalAntiDepBreaker.cpp
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2011-02-08 17:39:46 +0000
committerAndrew Trick <atrick@apple.com>2011-02-08 17:39:46 +0000
commitbc4bd92d52be2f6707a8c311873ded27a8f2481f (patch)
treee615ff541b39a385d31c52a92d9ae25e36af2fde /lib/CodeGen/CriticalAntiDepBreaker.cpp
parent75396a998887220074b90f176e29054a35b6c0ed (diff)
downloadexternal_llvm-bc4bd92d52be2f6707a8c311873ded27a8f2481f.zip
external_llvm-bc4bd92d52be2f6707a8c311873ded27a8f2481f.tar.gz
external_llvm-bc4bd92d52be2f6707a8c311873ded27a8f2481f.tar.bz2
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
Diffstat (limited to 'lib/CodeGen/CriticalAntiDepBreaker.cpp')
-rw-r--r--lib/CodeGen/CriticalAntiDepBreaker.cpp54
1 files changed, 46 insertions, 8 deletions
diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp
index 7b2ce36..f79598d 100644
--- a/lib/CodeGen/CriticalAntiDepBreaker.cpp
+++ b/lib/CodeGen/CriticalAntiDepBreaker.cpp
@@ -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))