From bc4bd92d52be2f6707a8c311873ded27a8f2481f Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 8 Feb 2011 17:39:46 +0000 Subject: [PATCH] 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 --- lib/CodeGen/CriticalAntiDepBreaker.cpp | 54 ++++++++++++++++++++++---- lib/CodeGen/CriticalAntiDepBreaker.h | 6 +-- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp index 7b2ce362417..f79598de1d9 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)) diff --git a/lib/CodeGen/CriticalAntiDepBreaker.h b/lib/CodeGen/CriticalAntiDepBreaker.h index df21ef28340..6adc45add6d 100644 --- a/lib/CodeGen/CriticalAntiDepBreaker.h +++ b/lib/CodeGen/CriticalAntiDepBreaker.h @@ -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,