40#define DEBUG_TYPE "post-RA-sched"
45 cl::desc(
"Debug control for aggressive anti-dep breaker"),
50 cl::desc(
"Debug control for aggressive anti-dep breaker"),
55 : NumTargetRegs(TargetRegs), GroupNodes(TargetRegs, 0),
56 GroupNodeIndices(TargetRegs, 0), KillIndices(TargetRegs, 0),
57 DefIndices(TargetRegs, 0) {
58 const unsigned BBSize = BB->
size();
59 for (
unsigned i = 0; i < NumTargetRegs; ++i) {
62 GroupNodeIndices[i] = i;
65 DefIndices[i] = BBSize;
70 unsigned Node = GroupNodeIndices[Reg.id()];
78 unsigned Group, std::vector<MCRegister> &Regs,
79 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
81 for (
unsigned Reg = 0; Reg != NumTargetRegs; ++Reg) {
82 if ((
GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0))
88 assert(GroupNodes[0] == 0 &&
"GroupNode 0 not parent!");
89 assert(GroupNodeIndices[0] == 0 &&
"Reg 0 not in Group 0!");
96 unsigned Parent = (Group1 == 0) ? Group1 : Group2;
97 unsigned Other = (Parent == Group1) ? Group2 : Group1;
98 GroupNodes.at(
Other) = Parent;
106 unsigned idx = GroupNodes.size();
107 GroupNodes.push_back(idx);
108 GroupNodeIndices[Reg.id()] = idx;
115 return ((KillIndices[Reg.id()] != ~0u) && (DefIndices[Reg.id()] == ~0u));
121 : MF(MFi), MRI(MF.getRegInfo()), TII(MF.getSubtarget().getInstrInfo()),
122 TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI) {
126 BitVector CPSet = TRI->getAllocatableSet(MF, RC);
127 if (CriticalPathSet.none())
128 CriticalPathSet = CPSet;
130 CriticalPathSet |= CPSet;
135 : CriticalPathSet.set_bits())
dbgs()
148 std::vector<unsigned> &KillIndices = State->GetKillIndices();
149 std::vector<unsigned> &DefIndices = State->GetDefIndices();
162 for (
unsigned R = 1, E = TRI->getNumRegs(); R != E; ++R) {
164 if (!
all_of(TRI->regunits(Reg), [&](MCRegUnit Unit) {
165 return LiveOutUnits.test(static_cast<unsigned>(Unit));
168 State->UnionGroups(Reg, 0);
169 KillIndices[Reg.id()] = BB->
size();
170 DefIndices[Reg.id()] = ~0u;
180 unsigned InsertPosIndex) {
181 assert(
Count < InsertPosIndex &&
"Instruction index out of expected range!");
183 std::set<MCRegister> PassthruRegs;
184 GetPassthruRegs(
MI, PassthruRegs);
185 PrescanInstruction(
MI,
Count, PassthruRegs);
192 std::vector<unsigned> &DefIndices = State->GetDefIndices();
193 for (
unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {
200 if (State->IsLive(Reg)) {
202 <<
" " <<
printReg(Reg, TRI) <<
"=g" << State->GetGroup(Reg)
203 <<
"->g0(region live-out)");
204 State->UnionGroups(Reg, 0);
205 }
else if ((DefIndices[Reg] < InsertPosIndex)
206 && (DefIndices[Reg] >=
Count)) {
207 DefIndices[Reg] =
Count;
224 Op =
MI.findRegisterUseOperand(Reg,
nullptr,
true);
226 Op =
MI.findRegisterDefOperand(Reg,
nullptr);
228 return(
Op &&
Op->isImplicit());
231void AggressiveAntiDepBreaker::GetPassthruRegs(
233 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
235 if (!MO.
isReg())
continue;
236 if ((MO.
isDef() &&
MI.isRegTiedToUseOperand(i)) ||
237 IsImplicitDefUse(
MI, MO)) {
240 PassthruRegs.insert(SubReg);
252 Edges.push_back(&
Pred);
261 unsigned NextDepth = 0;
266 unsigned PredLatency =
Pred.getLatency();
267 unsigned PredTotalLatency = PredSU->
getDepth() + PredLatency;
270 if (NextDepth < PredTotalLatency ||
271 (NextDepth == PredTotalLatency &&
Pred.getKind() ==
SDep::Anti)) {
272 NextDepth = PredTotalLatency;
278 return (
Next) ?
Next->getSUnit() :
nullptr;
281void AggressiveAntiDepBreaker::HandleLastUse(
MCRegister Reg,
unsigned KillIdx,
284 const char *footer) {
285 std::vector<unsigned> &KillIndices = State->GetKillIndices();
286 std::vector<unsigned> &DefIndices = State->GetDefIndices();
287 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
288 &RegRefs = State->GetRegRefs();
294 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI)
295 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI)) {
300 if (!State->IsLive(
Reg)) {
301 KillIndices[
Reg.
id()] = KillIdx;
302 DefIndices[
Reg.
id()] = ~0
u;
304 State->LeaveGroup(
Reg);
315 if (!State->IsLive(SubregReg)) {
316 KillIndices[SubregReg] = KillIdx;
317 DefIndices[SubregReg] = ~0
u;
318 RegRefs.erase(SubregReg);
319 State->LeaveGroup(SubregReg);
325 << State->GetGroup(SubregReg) << tag);
333void AggressiveAntiDepBreaker::PrescanInstruction(
335 const std::set<MCRegister> &PassthruRegs) {
336 std::vector<unsigned> &DefIndices = State->GetDefIndices();
337 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
338 &RegRefs = State->GetRegRefs();
345 for (
const MachineOperand &MO :
MI.all_defs()) {
354 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
355 MachineOperand &MO =
MI.getOperand(i);
362 << State->GetGroup(
Reg));
369 if (
MI.isCall() ||
MI.hasExtraDefRegAllocReq() || TII->isPredicated(
MI) ||
372 State->UnionGroups(
Reg, 0);
377 for (MCRegAliasIterator AI(
Reg, TRI,
false); AI.isValid(); ++AI) {
378 MCRegister AliasReg = *AI;
379 if (State->IsLive(AliasReg)) {
380 State->UnionGroups(
Reg, AliasReg);
388 if (i <
MI.getDesc().getNumOperands())
389 RC = TII->getRegClass(
MI.getDesc(), i);
390 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
398 for (
const MachineOperand &MO :
MI.all_defs()) {
403 if (
MI.isKill() || (PassthruRegs.count(
Reg) != 0))
407 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI) {
414 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI))
417 DefIndices[(*AI).id()] =
Count;
425 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
426 &RegRefs = State->GetRegRefs();
445 bool Special =
MI.isCall() ||
MI.hasExtraSrcRegAllocReq() ||
446 TII->isPredicated(
MI) ||
MI.isInlineAsm();
450 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
451 MachineOperand &MO =
MI.getOperand(i);
458 << State->GetGroup(
Reg));
467 State->UnionGroups(
Reg, 0);
472 if (i <
MI.getDesc().getNumOperands())
473 RC = TII->getRegClass(
MI.getDesc(), i);
474 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
486 for (
const MachineOperand &MO :
MI.operands()) {
487 if (!MO.
isReg())
continue;
494 State->UnionGroups(FirstReg,
Reg);
506 BitVector BV(TRI->getNumRegs(),
false);
512 for (
const auto &Q :
make_range(State->GetRegRefs().equal_range(
Reg))) {
516 BitVector RCBV = TRI->getAllocatableSet(MF, RC);
530bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
531 MCRegister SuperReg,
unsigned AntiDepGroupIndex,
532 RenameOrderType &RenameOrder, std::map<MCRegister, MCRegister> &RenameMap) {
533 std::vector<unsigned> &KillIndices = State->GetKillIndices();
534 std::vector<unsigned> &DefIndices = State->GetDefIndices();
535 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
536 &RegRefs = State->GetRegRefs();
541 std::vector<MCRegister> Regs;
542 State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs);
543 assert(!Regs.empty() &&
"Empty register group!");
549 LLVM_DEBUG(
dbgs() <<
"\tRename Candidates for Group g" << AntiDepGroupIndex
551 std::map<MCRegister, BitVector> RenameRegisterMap;
552 for (MCRegister
Reg : Regs) {
554 if (RegRefs.count(
Reg) > 0) {
557 BitVector &BV = RenameRegisterMap[
Reg];
559 BV = GetRenameRegisters(
Reg);
571 for (MCRegister
Reg : Regs) {
572 if (
Reg == SuperReg)
continue;
573 bool IsSub = TRI->isSubRegister(SuperReg,
Reg);
584 static int renamecnt = 0;
588 dbgs() <<
"*** Performing rename " <<
printReg(SuperReg, TRI)
589 <<
" for debug ***\n";
611 RenameOrder.insert(RenameOrderType::value_type(SuperRC, Order.
size()));
613 unsigned OrigR = RenameOrder[SuperRC];
614 unsigned EndR = ((OrigR == Order.
size()) ? 0 : OrigR);
617 if (R == 0)
R = Order.
size();
619 const MCRegister NewSuperReg = Order[
R];
621 if (!MRI.isAllocatable(NewSuperReg))
continue;
623 if (NewSuperReg == SuperReg)
continue;
631 for (MCRegister
Reg : Regs) {
633 if (
Reg == SuperReg) {
634 NewReg = NewSuperReg;
636 unsigned NewSubRegIdx = TRI->getSubRegIndex(SuperReg,
Reg);
637 if (NewSubRegIdx != 0)
638 NewReg = TRI->getSubReg(NewSuperReg, NewSubRegIdx);
644 if (!RenameRegisterMap[
Reg].
test(NewReg.
id())) {
653 if (State->IsLive(NewReg) ||
654 (KillIndices[
Reg.
id()] > DefIndices[NewReg.
id()])) {
659 for (MCRegAliasIterator AI(NewReg, TRI,
false); AI.isValid(); ++AI) {
660 MCRegister AliasReg = *AI;
661 if (State->IsLive(AliasReg) ||
662 (KillIndices[
Reg.
id()] > DefIndices[AliasReg.
id()])) {
664 <<
"(alias " <<
printReg(AliasReg, TRI) <<
" live)");
691 if (!Q.second.Operand->isDef() || !Q.second.Operand->isEarlyClobber())
702 RenameMap.insert(std::make_pair(
Reg, NewReg));
707 RenameOrder.erase(SuperRC);
708 RenameOrder.insert(RenameOrderType::value_type(SuperRC, R));
725 const std::vector<SUnit> &SUnits,
728 unsigned InsertPosIndex,
730 std::vector<unsigned> &KillIndices = State->GetKillIndices();
731 std::vector<unsigned> &DefIndices = State->GetDefIndices();
732 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
733 &RegRefs = State->GetRegRefs();
737 if (SUnits.empty())
return 0;
740 RenameOrderType RenameOrder;
743 std::map<MachineInstr *, const SUnit *> MISUnitMap;
744 for (
const SUnit &SU : SUnits)
745 MISUnitMap.insert(std::make_pair(SU.getInstr(), &SU));
750 const SUnit *CriticalPathSU =
nullptr;
752 if (CriticalPathSet.any()) {
753 for (
const SUnit &SU : SUnits) {
754 if (!CriticalPathSU ||
755 ((SU.getDepth() + SU.Latency) >
757 CriticalPathSU = &SU;
760 assert(CriticalPathSU &&
"Failed to find SUnit critical path");
761 CriticalPathMI = CriticalPathSU->
getInstr();
765 LLVM_DEBUG(
dbgs() <<
"\n===== Aggressive anti-dependency breaking\n");
767 for (
unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {
768 if (!State->IsLive(Reg))
778 unsigned Count = InsertPosIndex - 1;
783 if (
MI.isDebugOrPseudoInstr())
789 std::set<MCRegister> PassthruRegs;
790 GetPassthruRegs(
MI, PassthruRegs);
793 PrescanInstruction(
MI,
Count, PassthruRegs);
797 std::vector<const SDep *> Edges;
798 const SUnit *PathSU = MISUnitMap[&
MI];
804 if (&
MI == CriticalPathMI) {
806 CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->
getInstr() :
nullptr;
807 }
else if (CriticalPathSet.any()) {
808 ExcludeRegs = &CriticalPathSet;
815 for (
const SDep *Edge : Edges) {
816 SUnit *NextSU = Edge->getSUnit();
821 MCRegister AntiDepReg = Edge->getReg().asMCReg();
823 assert(AntiDepReg &&
"Anti-dependence on reg0?");
825 if (!MRI.isAllocatable(AntiDepReg)) {
829 }
else if (ExcludeRegs && ExcludeRegs->
test(AntiDepReg.
id())) {
834 }
else if (PassthruRegs.count(AntiDepReg) != 0) {
843 MI.findRegisterDefOperand(AntiDepReg,
nullptr);
844 assert(AntiDepOp &&
"Can't find index for defined register operand");
860 if (Pred.getSUnit() == NextSU ? (Pred.getKind() !=
SDep::Anti ||
861 Pred.getReg() != AntiDepReg)
863 Pred.getReg() == AntiDepReg)) {
869 if ((Pred.getSUnit() == NextSU) && (Pred.getKind() !=
SDep::Anti) &&
874 }
else if ((Pred.getSUnit() != NextSU) &&
876 (Pred.getReg() == AntiDepReg)) {
890 const unsigned GroupIndex = State->GetGroup(AntiDepReg);
891 if (GroupIndex == 0) {
899 std::map<MCRegister, MCRegister> RenameMap;
900 if (FindSuitableFreeRegisters(AntiDepReg, GroupIndex, RenameOrder,
903 <<
printReg(AntiDepReg, TRI) <<
":");
906 for (
const auto &
P : RenameMap) {
912 << RegRefs.count(CurrReg) <<
" refs)");
916 for (
const auto &Q :
make_range(RegRefs.equal_range(CurrReg))) {
917 Q.second.Operand->setReg(NewReg);
921 const SUnit *SU = MISUnitMap[Q.second.Operand->getParent()];
930 State->UnionGroups(NewReg, 0);
931 RegRefs.erase(NewReg);
932 DefIndices[NewReg.
id()] = DefIndices[CurrReg.
id()];
933 KillIndices[NewReg.
id()] = KillIndices[CurrReg.
id()];
935 State->UnionGroups(CurrReg, 0);
936 RegRefs.erase(CurrReg);
937 DefIndices[CurrReg.
id()] = KillIndices[CurrReg.
id()];
938 KillIndices[CurrReg.
id()] = ~0u;
939 assert(((KillIndices[CurrReg.
id()] == ~0u) !=
940 (DefIndices[CurrReg.
id()] == ~0u)) &&
941 "Kill and Def maps aren't consistent for AntiDepReg!");
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void AntiDepEdges(const SUnit *SU, std::vector< const SDep * > &Edges)
AntiDepEdges - Return in Edges the anti- and output- dependencies in SU that we want to consider for ...
static const SUnit * CriticalPathStep(const SUnit *SU)
CriticalPathStep - Return the next SUnit after SU on the bottom-up critical path.
static cl::opt< int > DebugDiv("agg-antidep-debugdiv", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
static cl::opt< int > DebugMod("agg-antidep-debugmod", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file defines the SmallSet class.
void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex) override
Update liveness information to account for the current instruction, which will not be scheduled.
void FinishBlock() override
Finish anti-dep breaking for a basic block.
~AggressiveAntiDepBreaker() 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 StartBlock(MachineBasicBlock *BB) override
Initialize anti-dep breaking for a new basic block.
AggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
Contains all the state necessary for anti-dep breaking.
AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB)
void GetGroupRegs(unsigned Group, std::vector< MCRegister > &Regs, std::multimap< MCRegister, AggressiveAntiDepState::RegisterReference > *RegRefs)
unsigned LeaveGroup(MCRegister Reg)
bool IsLive(MCRegister Reg)
Return true if Reg is live.
unsigned GetGroup(MCRegister Reg)
unsigned UnionGroups(MCRegister Reg1, MCRegister Reg2)
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
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
iterator_range< const_set_bits_iterator > set_bits() const
bool empty() const
Returns whether there are no bits in this bitvector.
A set of register units used to track register liveness.
const BitVector & getBitVector() const
Return the internal bitvector representation of the set.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
Wrapper class representing physical registers. Should be passed by value.
constexpr unsigned id() const
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr unsigned id() const
@ Output
A register output-dependence (aka WAW).
@ 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 short Latency
Node latency.
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallVectorImpl< const TargetRegisterClass * > RegClassVector
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
initializer< Ty > init(const Ty &Val)
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 AntiDepBreaker * createAggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
@ End
Run the machine verifier once, at the end of the pipeline.
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.
MCRegisterClass TargetRegisterClass