Skip to content

Commit

Permalink
[CriticalAntiDepBreaker] Use Register and MCRegister. NFC
Browse files Browse the repository at this point in the history
  • Loading branch information
topperc committed Mar 7, 2025
1 parent fc4bce3 commit 6b09402
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 82 deletions.
144 changes: 73 additions & 71 deletions llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
for (const MachineBasicBlock *Succ : BB->successors())
for (const auto &LI : Succ->liveins()) {
for (MCRegAliasIterator AI(LI.PhysReg, TRI, true); AI.isValid(); ++AI) {
unsigned Reg = (*AI).id();
Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
KillIndices[Reg] = BBSize;
MCRegister Reg = *AI;
Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);
KillIndices[Reg.id()] = BBSize;
DefIndices[Reg] = ~0u;
}
}
Expand All @@ -85,10 +85,10 @@ void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
if (!IsReturnBlock && !Pristine.test(Reg))
continue;
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) {
unsigned Reg = (*AI).id();
Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
KillIndices[Reg] = BBSize;
DefIndices[Reg] = ~0u;
MCRegister Reg = *AI;
Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);
KillIndices[Reg.id()] = BBSize;
DefIndices[Reg.id()] = ~0u;
}
}
}
Expand Down Expand Up @@ -182,7 +182,8 @@ void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr &MI) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg()) continue;
Register Reg = MO.getReg();
if (Reg == 0) continue;
if (!Reg)
continue;
const TargetRegisterClass *NewRC = nullptr;

if (i < MI.getDesc().getNumOperands())
Expand Down Expand Up @@ -278,7 +279,8 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {

if (!MO.isReg()) continue;
Register Reg = MO.getReg();
if (Reg == 0) continue;
if (!Reg)
continue;
if (!MO.isDef()) continue;

// Ignore two-addr defs.
Expand Down Expand Up @@ -308,7 +310,8 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg()) continue;
Register Reg = MO.getReg();
if (Reg == 0) continue;
if (!Reg)
continue;
if (!MO.isUse()) continue;

const TargetRegisterClass *NewRC = nullptr;
Expand All @@ -327,10 +330,10 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {
// It wasn't previously live but now it is, this is a kill.
// Repeat for all aliases.
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
unsigned AliasReg = (*AI).id();
if (KillIndices[AliasReg] == ~0u) {
KillIndices[AliasReg] = Count;
DefIndices[AliasReg] = ~0u;
MCRegister AliasReg = *AI;
if (KillIndices[AliasReg.id()] == ~0u) {
KillIndices[AliasReg.id()] = Count;
DefIndices[AliasReg.id()] = ~0u;
}
}
}
Expand All @@ -347,10 +350,9 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {
// RegRefs because the def is inserted by PrescanInstruction and not erased
// during ScanInstruction. So checking for an instruction with definitions of
// both NewReg and AntiDepReg covers it.
bool
CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg) {
bool CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
MCRegister NewReg) {
for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) {
MachineOperand *RefOper = I->second;

Expand Down Expand Up @@ -389,15 +391,12 @@ CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
return false;
}

unsigned CriticalAntiDepBreaker::
findSuitableFreeRegister(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned AntiDepReg,
unsigned LastNewReg,
const TargetRegisterClass *RC,
SmallVectorImpl<unsigned> &Forbid) {
MCRegister CriticalAntiDepBreaker::findSuitableFreeRegister(
RegRefIter RegRefBegin, RegRefIter RegRefEnd, MCRegister AntiDepReg,
MCRegister LastNewReg, const TargetRegisterClass *RC,
const SmallVectorImpl<Register> &Forbid) {
ArrayRef<MCPhysReg> Order = RegClassInfo.getOrder(RC);
for (unsigned NewReg : Order) {
for (MCRegister NewReg : Order) {
// Don't replace a register with itself.
if (NewReg == AntiDepReg) continue;
// Don't replace a register with one that was recently used to repair
Expand All @@ -410,17 +409,18 @@ findSuitableFreeRegister(RegRefIter RegRefBegin,
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))
&& "Kill and Def maps aren't consistent for AntiDepReg!");
assert(((KillIndices[AntiDepReg.id()] == ~0u) !=
(DefIndices[AntiDepReg.id()] == ~0u)) &&
"Kill and Def maps aren't consistent for AntiDepReg!");
assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u))
&& "Kill and Def maps aren't consistent for NewReg!");
if (KillIndices[NewReg] != ~0u ||
Classes[NewReg] == reinterpret_cast<TargetRegisterClass *>(-1) ||
KillIndices[AntiDepReg] > DefIndices[NewReg])
KillIndices[AntiDepReg.id()] > DefIndices[NewReg])
continue;
// If NewReg overlaps any of the forbidden registers, we can't use it.
bool Forbidden = false;
for (unsigned R : Forbid)
for (Register R : Forbid)
if (TRI->regsOverlap(NewReg, R)) {
Forbidden = true;
break;
Expand All @@ -430,7 +430,7 @@ findSuitableFreeRegister(RegRefIter RegRefBegin,
}

// No registers are free and available!
return 0;
return MCRegister();
}

unsigned CriticalAntiDepBreaker::
Expand Down Expand Up @@ -517,7 +517,7 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,
// fix that remaining critical edge too. This is a little more involved,
// because unlike the most recent register, less recent registers should
// still be considered, though only if no other registers are available.
std::vector<unsigned> LastNewReg(TRI->getNumRegs(), 0);
std::vector<MCRegister> LastNewReg(TRI->getNumRegs(), MCRegister());

// Attempt to break anti-dependence edges on the critical path. Walk the
// instructions from the bottom up, tracking information about liveness
Expand Down Expand Up @@ -549,22 +549,22 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,
// anti-dependencies. The current code here only knows how to break one
// edge per instruction. Note that we'd have to be able to break all of
// the anti-dependencies in an instruction in order to be effective.
unsigned AntiDepReg = 0;
MCRegister AntiDepReg;
if (&MI == CriticalPathMI) {
if (const SDep *Edge = CriticalPathStep(CriticalPathSU)) {
const SUnit *NextSU = Edge->getSUnit();

// Only consider anti-dependence edges.
if (Edge->getKind() == SDep::Anti) {
AntiDepReg = Edge->getReg();
assert(AntiDepReg != 0 && "Anti-dependence on reg0?");
AntiDepReg = Edge->getReg().asMCReg();
assert(AntiDepReg && "Anti-dependence on reg0?");
if (!MRI.isAllocatable(AntiDepReg))
// Don't break anti-dependencies on non-allocatable registers.
AntiDepReg = 0;
else if (KeepRegs.test(AntiDepReg))
AntiDepReg = MCRegister();
else if (KeepRegs.test(AntiDepReg.id()))
// Don't break anti-dependencies if a use down below requires
// this exact register.
AntiDepReg = 0;
AntiDepReg = MCRegister();
else {
// If the SUnit has other dependencies on the SUnit that it
// anti-depends on, don't bother breaking the anti-dependency
Expand All @@ -579,7 +579,7 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,
? (P.getKind() != SDep::Anti || P.getReg() != AntiDepReg)
: (P.getKind() == SDep::Data &&
P.getReg() == AntiDepReg)) {
AntiDepReg = 0;
AntiDepReg = MCRegister();
break;
}
}
Expand All @@ -595,15 +595,15 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,

PrescanInstruction(MI);

SmallVector<unsigned, 2> ForbidRegs;
SmallVector<Register, 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).
if (MI.isCall() || MI.hasExtraDefRegAllocReq() || TII->isPredicated(MI))
// If this instruction's defs have special allocation requirement, don't
// break this anti-dependency.
AntiDepReg = 0;
AntiDepReg = MCRegister();
else if (AntiDepReg) {
// If this instruction has a use of AntiDepReg, breaking it
// is invalid. If the instruction defines other registers,
Expand All @@ -612,9 +612,10 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg()) continue;
Register Reg = MO.getReg();
if (Reg == 0) continue;
if (!Reg)
continue;
if (MO.isUse() && TRI->regsOverlap(AntiDepReg, Reg)) {
AntiDepReg = 0;
AntiDepReg = MCRegister();
break;
}
if (MO.isDef() && Reg != AntiDepReg)
Expand All @@ -624,34 +625,35 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,

// Determine AntiDepReg's register class, if it is live and is
// consistently used within a single class.
const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg]
: nullptr;
assert((AntiDepReg == 0 || RC != nullptr) &&
const TargetRegisterClass *RC =
AntiDepReg ? Classes[AntiDepReg.id()] : nullptr;
assert((!AntiDepReg || RC != nullptr) &&
"Register should be live if it's causing an anti-dependence!");
if (RC == reinterpret_cast<TargetRegisterClass *>(-1))
AntiDepReg = 0;
AntiDepReg = MCRegister();

// Look for a suitable register to use to break the anti-dependence.
//
// TODO: Instead of picking the first free register, consider which might
// be the best.
if (AntiDepReg != 0) {
std::pair<std::multimap<unsigned, MachineOperand *>::iterator,
std::multimap<unsigned, MachineOperand *>::iterator>
Range = RegRefs.equal_range(AntiDepReg);
if (unsigned NewReg = findSuitableFreeRegister(Range.first, Range.second,
AntiDepReg,
LastNewReg[AntiDepReg],
RC, ForbidRegs)) {
if (AntiDepReg) {
std::pair<std::multimap<MCRegister, MachineOperand *>::iterator,
std::multimap<MCRegister, MachineOperand *>::iterator>
Range = RegRefs.equal_range(AntiDepReg);
if (MCRegister NewReg = findSuitableFreeRegister(
Range.first, Range.second, AntiDepReg, LastNewReg[AntiDepReg], RC,
ForbidRegs)) {
LLVM_DEBUG(dbgs() << "Breaking anti-dependence edge on "
<< printReg(AntiDepReg, TRI) << " with "
<< RegRefs.count(AntiDepReg) << " references"
<< " using " << printReg(NewReg, TRI) << "!\n");

// Update the references to the old register to refer to the new
// register.
for (std::multimap<unsigned, MachineOperand *>::iterator
Q = Range.first, QE = Range.second; Q != QE; ++Q) {
for (std::multimap<MCRegister, MachineOperand *>::iterator
Q = Range.first,
QE = Range.second;
Q != QE; ++Q) {
Q->second->setReg(NewReg);
// If the SU for the instruction being updated has debug information
// related to the anti-dependency register, make sure to update that
Expand All @@ -665,22 +667,22 @@ BreakAntiDependencies(const std::vector<SUnit> &SUnits,
// We just went back in time and modified history; the
// liveness information for the anti-dependence reg is now
// inconsistent. Set the state as if it were dead.
Classes[NewReg] = Classes[AntiDepReg];
DefIndices[NewReg] = DefIndices[AntiDepReg];
KillIndices[NewReg] = KillIndices[AntiDepReg];
assert(((KillIndices[NewReg] == ~0u) !=
(DefIndices[NewReg] == ~0u)) &&
"Kill and Def maps aren't consistent for NewReg!");

Classes[AntiDepReg] = nullptr;
DefIndices[AntiDepReg] = KillIndices[AntiDepReg];
KillIndices[AntiDepReg] = ~0u;
assert(((KillIndices[AntiDepReg] == ~0u) !=
(DefIndices[AntiDepReg] == ~0u)) &&
"Kill and Def maps aren't consistent for AntiDepReg!");
Classes[NewReg.id()] = Classes[AntiDepReg.id()];
DefIndices[NewReg.id()] = DefIndices[AntiDepReg.id()];
KillIndices[NewReg.id()] = KillIndices[AntiDepReg.id()];
assert(((KillIndices[NewReg.id()] == ~0u) !=
(DefIndices[NewReg.id()] == ~0u)) &&
"Kill and Def maps aren't consistent for NewReg!");

Classes[AntiDepReg.id()] = nullptr;
DefIndices[AntiDepReg.id()] = KillIndices[AntiDepReg.id()];
KillIndices[AntiDepReg.id()] = ~0u;
assert(((KillIndices[AntiDepReg.id()] == ~0u) !=
(DefIndices[AntiDepReg.id()] == ~0u)) &&
"Kill and Def maps aren't consistent for AntiDepReg!");

RegRefs.erase(AntiDepReg);
LastNewReg[AntiDepReg] = NewReg;
LastNewReg[AntiDepReg.id()] = NewReg;
++Broken;
}
}
Expand Down
20 changes: 9 additions & 11 deletions llvm/lib/CodeGen/CriticalAntiDepBreaker.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ class LLVM_LIBRARY_VISIBILITY CriticalAntiDepBreaker : public AntiDepBreaker {
std::vector<const TargetRegisterClass *> Classes;

/// Map registers to all their references within a live range.
std::multimap<unsigned, MachineOperand *> RegRefs;
std::multimap<MCRegister, MachineOperand *> RegRefs;

using RegRefIter =
std::multimap<unsigned, MachineOperand *>::const_iterator;
std::multimap<MCRegister, MachineOperand *>::const_iterator;

/// The index of the most recent kill (proceeding bottom-up),
/// or ~0u if the register is not live.
Expand Down Expand Up @@ -96,15 +96,13 @@ class LLVM_LIBRARY_VISIBILITY CriticalAntiDepBreaker : public AntiDepBreaker {
private:
void PrescanInstruction(MachineInstr &MI);
void ScanInstruction(MachineInstr &MI, unsigned Count);
bool isNewRegClobberedByRefs(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned NewReg);
unsigned findSuitableFreeRegister(RegRefIter RegRefBegin,
RegRefIter RegRefEnd,
unsigned AntiDepReg,
unsigned LastNewReg,
const TargetRegisterClass *RC,
SmallVectorImpl<unsigned> &Forbid);
bool isNewRegClobberedByRefs(RegRefIter RegRefBegin, RegRefIter RegRefEnd,
MCRegister NewReg);
MCRegister
findSuitableFreeRegister(RegRefIter RegRefBegin, RegRefIter RegRefEnd,
MCRegister AntiDepReg, MCRegister LastNewReg,
const TargetRegisterClass *RC,
const SmallVectorImpl<Register> &Forbid);
};

} // end namespace llvm
Expand Down

0 comments on commit 6b09402

Please sign in to comment.