39#define DEBUG_TYPE "post-RA-sched"
43 : MF(MFi), MRI(MF.getRegInfo()), TII(MF.getSubtarget().getInstrInfo()),
44 TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI),
45 Classes(TRI->getNumRegs(), nullptr), KillIndices(TRI->getNumRegs(), 0),
46 DefIndices(TRI->getNumRegs(), 0), KeepRegs(TRI->getNumRegs(),
false) {}
51 const unsigned BBSize = BB->
size();
52 for (
unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {
58 DefIndices[i] = BBSize;
68 for (
const auto &LI : Succ->liveins()) {
72 KillIndices[Reg.id()] = BBSize;
73 DefIndices[Reg.id()] = ~0u;
82 for (
const MCPhysReg *
I = MF.getRegInfo().getCalleeSavedRegs(); *
I;
85 if (!IsReturnBlock && !Pristine.
test(Reg))
90 KillIndices[Reg.id()] = BBSize;
91 DefIndices[Reg.id()] = ~0u;
102 unsigned InsertPosIndex) {
110 if (
MI.isDebugInstr() ||
MI.isKill())
112 assert(
Count < InsertPosIndex &&
"Instruction index out of expected range!");
114 for (
unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {
115 if (KillIndices[Reg] != ~0u) {
120 KillIndices[Reg] =
Count;
121 }
else if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >=
Count) {
130 DefIndices[Reg] = InsertPosIndex;
134 PrescanInstruction(
MI);
142 unsigned NextDepth = 0;
145 const SUnit *PredSU =
P.getSUnit();
146 unsigned PredLatency =
P.getLatency();
147 unsigned PredTotalLatency = PredSU->
getDepth() + PredLatency;
150 if (NextDepth < PredTotalLatency ||
151 (NextDepth == PredTotalLatency &&
P.getKind() ==
SDep::Anti)) {
152 NextDepth = PredTotalLatency;
159void CriticalAntiDepBreaker::PrescanInstruction(
MachineInstr &
MI) {
177 MI.isCall() ||
MI.hasExtraSrcRegAllocReq() || TII->isPredicated(
MI);
181 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
182 MachineOperand &MO =
MI.getOperand(i);
183 if (!MO.
isReg())
continue;
187 const TargetRegisterClass *NewRC =
nullptr;
189 if (i <
MI.getDesc().getNumOperands())
190 NewRC = TII->getRegClass(
MI.getDesc(), i, TRI);
194 if (!Classes[
Reg.
id()] && NewRC)
195 Classes[
Reg.
id()] = NewRC;
196 else if (!NewRC || Classes[
Reg.
id()] != NewRC)
197 Classes[
Reg.
id()] =
reinterpret_cast<TargetRegisterClass *
>(-1);
200 for (MCRegAliasIterator AI(
Reg, TRI,
false); AI.isValid(); ++AI) {
204 unsigned AliasReg = (*AI).id();
205 if (Classes[AliasReg]) {
206 Classes[AliasReg] =
reinterpret_cast<TargetRegisterClass *
>(-1);
207 Classes[
Reg.
id()] =
reinterpret_cast<TargetRegisterClass *
>(-1);
212 if (Classes[
Reg.
id()] !=
reinterpret_cast<TargetRegisterClass *
>(-1))
213 RegRefs.emplace(
Reg, &MO);
215 if (MO.
isUse() && Special) {
216 if (!KeepRegs.test(
Reg.
id())) {
223 for (
unsigned I = 0,
E =
MI.getNumOperands();
I !=
E; ++
I) {
224 const MachineOperand &MO =
MI.getOperand(
I);
225 if (!MO.
isReg())
continue;
239 if (
MI.isRegTiedToUseOperand(
I) &&
240 Classes[
Reg.
id()] ==
reinterpret_cast<TargetRegisterClass *
>(-1)) {
245 KeepRegs.set(SuperReg);
255 assert(!
MI.isKill() &&
"Attempting to scan a kill instruction");
257 if (!TII->isPredicated(
MI)) {
260 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
261 MachineOperand &MO =
MI.getOperand(i);
264 auto ClobbersPhysRegAndSubRegs = [&](
unsigned PhysReg) {
265 return all_of(TRI->subregs_inclusive(PhysReg),
266 [&](
MCPhysReg SR) { return MO.clobbersPhysReg(SR); });
269 for (
unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {
270 if (ClobbersPhysRegAndSubRegs(i)) {
271 DefIndices[i] =
Count;
272 KillIndices[i] = ~0
u;
274 Classes[i] =
nullptr;
280 if (!MO.
isReg())
continue;
284 if (!MO.
isDef())
continue;
287 if (
MI.isRegTiedToUseOperand(i))
296 for (
MCPhysReg SubregReg : TRI->subregs_inclusive(
Reg)) {
297 DefIndices[SubregReg] =
Count;
298 KillIndices[SubregReg] = ~0
u;
299 Classes[SubregReg] =
nullptr;
300 RegRefs.erase(SubregReg);
302 KeepRegs.reset(SubregReg);
306 Classes[SR] =
reinterpret_cast<TargetRegisterClass *
>(-1);
309 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
310 MachineOperand &MO =
MI.getOperand(i);
311 if (!MO.
isReg())
continue;
315 if (!MO.
isUse())
continue;
317 const TargetRegisterClass *NewRC =
nullptr;
318 if (i <
MI.getDesc().getNumOperands())
319 NewRC = TII->getRegClass(
MI.getDesc(), i, TRI);
323 if (!Classes[
Reg.
id()] && NewRC)
324 Classes[
Reg.
id()] = NewRC;
325 else if (!NewRC || Classes[
Reg.
id()] != NewRC)
326 Classes[
Reg.
id()] =
reinterpret_cast<TargetRegisterClass *
>(-1);
328 RegRefs.emplace(
Reg, &MO);
332 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI) {
333 MCRegister AliasReg = *AI;
334 if (KillIndices[AliasReg.
id()] == ~0u) {
335 KillIndices[AliasReg.
id()] =
Count;
336 DefIndices[AliasReg.
id()] = ~0
u;
353bool CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
354 RegRefIter RegRefEnd,
356 for (RegRefIter
I = RegRefBegin;
I != RegRefEnd; ++
I ) {
357 MachineOperand *RefOper =
I->second;
367 for (
const MachineOperand &CheckOper :
MI->operands()) {
368 if (CheckOper.isRegMask() && CheckOper.clobbersPhysReg(NewReg))
371 if (!CheckOper.isReg() || !CheckOper.isDef() ||
372 CheckOper.getReg() != NewReg)
377 if (RefOper->
isDef())
382 if (CheckOper.isEarlyClobber())
387 if (
MI->isInlineAsm())
394MCRegister CriticalAntiDepBreaker::findSuitableFreeRegister(
395 RegRefIter RegRefBegin, RegRefIter RegRefEnd,
MCRegister AntiDepReg,
399 for (MCRegister NewReg : Order) {
401 if (NewReg == AntiDepReg)
continue;
405 if (NewReg == LastNewReg)
continue;
409 if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg))
continue;
412 assert(((KillIndices[AntiDepReg.
id()] == ~0u) !=
413 (DefIndices[AntiDepReg.
id()] == ~0u)) &&
414 "Kill and Def maps aren't consistent for AntiDepReg!");
415 assert(((KillIndices[NewReg.
id()] == ~0u) !=
416 (DefIndices[NewReg.
id()] == ~0u)) &&
417 "Kill and Def maps aren't consistent for NewReg!");
418 if (KillIndices[NewReg.
id()] != ~0u ||
419 Classes[NewReg.
id()] ==
reinterpret_cast<TargetRegisterClass *
>(-1) ||
420 KillIndices[AntiDepReg.
id()] > DefIndices[NewReg.
id()])
423 bool Forbidden =
false;
425 if (TRI->regsOverlap(NewReg, R)) {
429 if (Forbidden)
continue;
441 unsigned InsertPosIndex,
445 if (SUnits.empty())
return 0;
454 const SUnit *Max =
nullptr;
455 for (
const SUnit &SU : SUnits) {
456 MISUnitMap[SU.getInstr()] = &SU;
457 if (!Max || SU.getDepth() + SU.Latency > Max->getDepth() + Max->Latency)
460 assert(Max &&
"Failed to find bottom of the critical path");
465 << (Max->getDepth() + Max->Latency) <<
"\n");
467 for (
unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {
468 if (KillIndices[Reg] == ~0u)
477 const SUnit *CriticalPathSU = Max;
521 std::vector<MCRegister> LastNewReg(TRI->getNumRegs(),
MCRegister());
527 unsigned Count = InsertPosIndex - 1;
537 if (
MI.isDebugInstr() ||
MI.isKill())
554 if (&
MI == CriticalPathMI) {
556 const SUnit *NextSU = Edge->getSUnit();
560 AntiDepReg = Edge->getReg().asMCReg();
561 assert(AntiDepReg &&
"Anti-dependence on reg0?");
562 if (!MRI.isAllocatable(AntiDepReg))
565 else if (KeepRegs.test(AntiDepReg.
id()))
579 if (
P.getSUnit() == NextSU
580 ? (
P.getKind() !=
SDep::Anti ||
P.getReg() != AntiDepReg)
582 P.getReg() == AntiDepReg)) {
588 CriticalPathSU = NextSU;
589 CriticalPathMI = CriticalPathSU->
getInstr();
592 CriticalPathSU =
nullptr;
593 CriticalPathMI =
nullptr;
597 PrescanInstruction(
MI);
604 if (
MI.isCall() ||
MI.hasExtraDefRegAllocReq() || TII->isPredicated(
MI))
608 else if (AntiDepReg) {
614 if (!MO.
isReg())
continue;
618 if (MO.
isUse() && TRI->regsOverlap(AntiDepReg, Reg)) {
622 if (MO.
isDef() && Reg != AntiDepReg)
630 AntiDepReg ? Classes[AntiDepReg.
id()] :
nullptr;
631 assert((!AntiDepReg || RC !=
nullptr) &&
632 "Register should be live if it's causing an anti-dependence!");
641 std::pair<std::multimap<MCRegister, MachineOperand *>::iterator,
642 std::multimap<MCRegister, MachineOperand *>::iterator>
643 Range = RegRefs.equal_range(AntiDepReg);
644 if (
MCRegister NewReg = findSuitableFreeRegister(
646 LastNewReg[AntiDepReg.
id()], RC, ForbidRegs)) {
648 <<
printReg(AntiDepReg, TRI) <<
" with "
649 << RegRefs.count(AntiDepReg) <<
" references"
650 <<
" using " <<
printReg(NewReg, TRI) <<
"!\n");
654 for (std::multimap<MCRegister, MachineOperand *>::iterator
658 Q->second->setReg(NewReg);
662 const SUnit *SU = MISUnitMap[Q->second->getParent()];
671 Classes[NewReg.
id()] = Classes[AntiDepReg.
id()];
672 DefIndices[NewReg.
id()] = DefIndices[AntiDepReg.
id()];
673 KillIndices[NewReg.
id()] = KillIndices[AntiDepReg.
id()];
674 assert(((KillIndices[NewReg.
id()] == ~0u) !=
675 (DefIndices[NewReg.
id()] == ~0u)) &&
676 "Kill and Def maps aren't consistent for NewReg!");
678 Classes[AntiDepReg.
id()] =
nullptr;
679 DefIndices[AntiDepReg.
id()] = KillIndices[AntiDepReg.
id()];
680 KillIndices[AntiDepReg.
id()] = ~0u;
681 assert(((KillIndices[AntiDepReg.
id()] == ~0u) !=
682 (DefIndices[AntiDepReg.
id()] == ~0u)) &&
683 "Kill and Def maps aren't consistent for AntiDepReg!");
685 RegRefs.erase(AntiDepReg);
686 LastNewReg[AntiDepReg.
id()] = NewReg;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const SUnit * CriticalPathStep(const SUnit *SU)
CriticalPathStep - Return the next SUnit after SU on the bottom-up critical path.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Promote Memory to Register
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file defines the SmallVector class.
This class works in conjunction with the post-RA scheduler to rename registers to break register anti...
void UpdateDbgValues(const DbgValueVector &DbgValues, MachineInstr *ParentMI, MCRegister OldReg, MCRegister NewReg)
Update all DBG_VALUE instructions that may be affected by the dependency breaker's update of ParentMI...
std::vector< std::pair< MachineInstr *, MachineInstr * > > DbgValueVector
bool test(unsigned Idx) const
void clear()
clear - Removes all bits from the bitvector.
~CriticalAntiDepBreaker() override
unsigned BreakAntiDependencies(const std::vector< SUnit > &SUnits, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned InsertPosIndex, DbgValueVector &DbgValues) override
Identifiy anti-dependencies along the critical path of the ScheduleDAG and break them by renaming reg...
void FinishBlock() override
Finish anti-dep breaking for a basic block.
void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex) override
Update liveness information to account for the current instruction, which will not be scheduled.
void StartBlock(MachineBasicBlock *BB) override
Initialize anti-dep breaking for a new basic block.
CriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
MCRegAliasIterator enumerates all registers aliasing Reg.
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr unsigned id() const
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
Scheduling unit. This is a node in the scheduling DAG.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
ArrayRef(const T &OneElt) -> ArrayRef< T >
AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
@ Keep
No function return thunk.