mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-12 13:38:21 +00:00
This patch addresses bug 15031.
The common code in the post-RA scheduler to break anti-dependencies on the critical path contained a flaw. In the reported case, an anti-dependency between the overlapping registers %X4 and %R4 exists: %X29<def> = OR8 %X4, %X4 %R4<def>, %X3<def,dead,tied3> = LBZU 1, %X3<kill,tied1> The unpatched code breaks the dependency by replacing %R4 and its uses with %R3, the first register on the available list. However, %R3 and %X3 overlap, so this creates two overlapping definitions on the same instruction. The fix is straightforward, preventing selection of a register that overlaps any other defined register on the same instruction. The test case is reduced from the bug report, and verifies that we no longer produce "lbzu 3, 1(3)" when breaking this anti-dependency. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173706 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -371,12 +371,13 @@ CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned
|
||||
CriticalAntiDepBreaker::findSuitableFreeRegister(RegRefIter RegRefBegin,
|
||||
RegRefIter RegRefEnd,
|
||||
unsigned AntiDepReg,
|
||||
unsigned LastNewReg,
|
||||
const TargetRegisterClass *RC)
|
||||
unsigned CriticalAntiDepBreaker::
|
||||
findSuitableFreeRegister(RegRefIter RegRefBegin,
|
||||
RegRefIter RegRefEnd,
|
||||
unsigned AntiDepReg,
|
||||
unsigned LastNewReg,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVector<unsigned, 2> &Forbid)
|
||||
{
|
||||
ArrayRef<MCPhysReg> Order = RegClassInfo.getOrder(RC);
|
||||
for (unsigned i = 0; i != Order.size(); ++i) {
|
||||
@ -401,6 +402,15 @@ CriticalAntiDepBreaker::findSuitableFreeRegister(RegRefIter RegRefBegin,
|
||||
Classes[NewReg] == reinterpret_cast<TargetRegisterClass *>(-1) ||
|
||||
KillIndices[AntiDepReg] > DefIndices[NewReg])
|
||||
continue;
|
||||
// If NewReg overlaps any of the forbidden registers, we can't use it.
|
||||
bool Forbidden = false;
|
||||
for (SmallVector<unsigned, 2>::iterator it = Forbid.begin(),
|
||||
ite = Forbid.end(); it != ite; ++it)
|
||||
if (TRI->regsOverlap(NewReg, *it)) {
|
||||
Forbidden = true;
|
||||
break;
|
||||
}
|
||||
if (Forbidden) continue;
|
||||
return NewReg;
|
||||
}
|
||||
|
||||
@ -564,6 +574,8 @@ BreakAntiDependencies(const std::vector<SUnit>& SUnits,
|
||||
|
||||
PrescanInstruction(MI);
|
||||
|
||||
SmallVector<unsigned, 2> ForbidRegs;
|
||||
|
||||
// If MI's defs have a special allocation requirement, don't allow
|
||||
// any def registers to be changed. Also assume all registers
|
||||
// defined in a call must not be changed (ABI).
|
||||
@ -574,7 +586,9 @@ BreakAntiDependencies(const std::vector<SUnit>& SUnits,
|
||||
AntiDepReg = 0;
|
||||
else if (AntiDepReg) {
|
||||
// If this instruction has a use of AntiDepReg, breaking it
|
||||
// is invalid.
|
||||
// is invalid. If the instruction defines other registers,
|
||||
// save a list of them so that we don't pick a new register
|
||||
// that overlaps any of them.
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI->getOperand(i);
|
||||
if (!MO.isReg()) continue;
|
||||
@ -584,6 +598,8 @@ BreakAntiDependencies(const std::vector<SUnit>& SUnits,
|
||||
AntiDepReg = 0;
|
||||
break;
|
||||
}
|
||||
if (MO.isDef() && Reg != AntiDepReg)
|
||||
ForbidRegs.push_back(Reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,7 +622,7 @@ BreakAntiDependencies(const std::vector<SUnit>& SUnits,
|
||||
if (unsigned NewReg = findSuitableFreeRegister(Range.first, Range.second,
|
||||
AntiDepReg,
|
||||
LastNewReg[AntiDepReg],
|
||||
RC)) {
|
||||
RC, ForbidRegs)) {
|
||||
DEBUG(dbgs() << "Breaking anti-dependence edge on "
|
||||
<< TRI->getName(AntiDepReg)
|
||||
<< " with " << RegRefs.count(AntiDepReg) << " references"
|
||||
|
Reference in New Issue
Block a user