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()
149 std::vector<unsigned> &KillIndices = State->GetKillIndices();
150 std::vector<unsigned> &DefIndices = State->GetDefIndices();
154 for (
const auto &LI : Succ->liveins()) {
157 State->UnionGroups(Reg, 0);
158 KillIndices[Reg.id()] = BB->
size();
159 DefIndices[Reg.id()] = ~0u;
168 for (
const MCPhysReg *
I = MF.getRegInfo().getCalleeSavedRegs(); *
I;
171 if (!IsReturnBlock && !Pristine.
test(Reg))
175 State->UnionGroups(AliasReg, 0);
176 KillIndices[AliasReg.
id()] = BB->
size();
177 DefIndices[AliasReg.
id()] = ~0u;
188 unsigned InsertPosIndex) {
189 assert(
Count < InsertPosIndex &&
"Instruction index out of expected range!");
191 std::set<MCRegister> PassthruRegs;
192 GetPassthruRegs(
MI, PassthruRegs);
193 PrescanInstruction(
MI,
Count, PassthruRegs);
200 std::vector<unsigned> &DefIndices = State->GetDefIndices();
201 for (
unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {
208 if (State->IsLive(Reg)) {
210 <<
" " <<
printReg(Reg, TRI) <<
"=g" << State->GetGroup(Reg)
211 <<
"->g0(region live-out)");
212 State->UnionGroups(Reg, 0);
213 }
else if ((DefIndices[Reg] < InsertPosIndex)
214 && (DefIndices[Reg] >=
Count)) {
215 DefIndices[Reg] =
Count;
232 Op =
MI.findRegisterUseOperand(Reg,
nullptr,
true);
234 Op =
MI.findRegisterDefOperand(Reg,
nullptr);
236 return(
Op &&
Op->isImplicit());
239void AggressiveAntiDepBreaker::GetPassthruRegs(
241 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
243 if (!MO.
isReg())
continue;
244 if ((MO.
isDef() &&
MI.isRegTiedToUseOperand(i)) ||
245 IsImplicitDefUse(
MI, MO)) {
248 PassthruRegs.insert(
SubReg);
259 if (RegSet.
insert(Pred.getReg()).second)
260 Edges.push_back(&Pred);
269 unsigned NextDepth = 0;
273 const SUnit *PredSU = Pred.getSUnit();
274 unsigned PredLatency = Pred.getLatency();
275 unsigned PredTotalLatency = PredSU->
getDepth() + PredLatency;
278 if (NextDepth < PredTotalLatency ||
279 (NextDepth == PredTotalLatency && Pred.getKind() ==
SDep::Anti)) {
280 NextDepth = PredTotalLatency;
286 return (
Next) ?
Next->getSUnit() :
nullptr;
289void AggressiveAntiDepBreaker::HandleLastUse(
MCRegister Reg,
unsigned KillIdx,
292 const char *footer) {
293 std::vector<unsigned> &KillIndices = State->GetKillIndices();
294 std::vector<unsigned> &DefIndices = State->GetDefIndices();
295 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
296 &RegRefs = State->GetRegRefs();
302 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI)
303 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI)) {
308 if (!State->IsLive(
Reg)) {
309 KillIndices[
Reg.
id()] = KillIdx;
310 DefIndices[
Reg.
id()] = ~0
u;
312 State->LeaveGroup(
Reg);
323 if (!State->IsLive(SubregReg)) {
324 KillIndices[SubregReg] = KillIdx;
325 DefIndices[SubregReg] = ~0
u;
326 RegRefs.erase(SubregReg);
327 State->LeaveGroup(SubregReg);
333 << State->GetGroup(SubregReg) << tag);
341void AggressiveAntiDepBreaker::PrescanInstruction(
343 const std::set<MCRegister> &PassthruRegs) {
344 std::vector<unsigned> &DefIndices = State->GetDefIndices();
345 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
346 &RegRefs = State->GetRegRefs();
353 for (
const MachineOperand &MO :
MI.all_defs()) {
362 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
363 MachineOperand &MO =
MI.getOperand(i);
370 << State->GetGroup(
Reg));
377 if (
MI.isCall() ||
MI.hasExtraDefRegAllocReq() || TII->isPredicated(
MI) ||
380 State->UnionGroups(
Reg, 0);
385 for (MCRegAliasIterator AI(
Reg, TRI,
false); AI.isValid(); ++AI) {
386 MCRegister AliasReg = *AI;
387 if (State->IsLive(AliasReg)) {
388 State->UnionGroups(
Reg, AliasReg);
395 const TargetRegisterClass *RC =
nullptr;
396 if (i <
MI.getDesc().getNumOperands())
397 RC = TII->getRegClass(
MI.getDesc(), i);
398 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
406 for (
const MachineOperand &MO :
MI.all_defs()) {
411 if (
MI.isKill() || (PassthruRegs.count(
Reg) != 0))
415 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI) {
422 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI))
425 DefIndices[(*AI).id()] =
Count;
433 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
434 &RegRefs = State->GetRegRefs();
453 bool Special =
MI.isCall() ||
MI.hasExtraSrcRegAllocReq() ||
454 TII->isPredicated(
MI) ||
MI.isInlineAsm();
458 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
459 MachineOperand &MO =
MI.getOperand(i);
466 << State->GetGroup(
Reg));
475 State->UnionGroups(
Reg, 0);
479 const TargetRegisterClass *RC =
nullptr;
480 if (i <
MI.getDesc().getNumOperands())
481 RC = TII->getRegClass(
MI.getDesc(), i);
482 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
494 for (
const MachineOperand &MO :
MI.operands()) {
495 if (!MO.
isReg())
continue;
502 State->UnionGroups(FirstReg,
Reg);
514 BitVector BV(TRI->getNumRegs(),
false);
520 for (
const auto &Q :
make_range(State->GetRegRefs().equal_range(
Reg))) {
521 const TargetRegisterClass *RC = Q.second.RC;
524 BitVector RCBV = TRI->getAllocatableSet(MF, RC);
538bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
539 MCRegister SuperReg,
unsigned AntiDepGroupIndex,
540 RenameOrderType &RenameOrder, std::map<MCRegister, MCRegister> &RenameMap) {
541 std::vector<unsigned> &KillIndices = State->GetKillIndices();
542 std::vector<unsigned> &DefIndices = State->GetDefIndices();
543 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
544 &RegRefs = State->GetRegRefs();
549 std::vector<MCRegister> Regs;
550 State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs);
551 assert(!Regs.empty() &&
"Empty register group!");
557 LLVM_DEBUG(
dbgs() <<
"\tRename Candidates for Group g" << AntiDepGroupIndex
559 std::map<MCRegister, BitVector> RenameRegisterMap;
560 for (MCRegister
Reg : Regs) {
562 if (RegRefs.count(
Reg) > 0) {
565 BitVector &BV = RenameRegisterMap[
Reg];
567 BV = GetRenameRegisters(
Reg);
579 for (MCRegister
Reg : Regs) {
580 if (
Reg == SuperReg)
continue;
581 bool IsSub = TRI->isSubRegister(SuperReg,
Reg);
592 static int renamecnt = 0;
596 dbgs() <<
"*** Performing rename " <<
printReg(SuperReg, TRI)
597 <<
" for debug ***\n";
609 const TargetRegisterClass *SuperRC =
610 TRI->getMinimalPhysRegClass(SuperReg, MVT::Other);
620 RenameOrder.insert(RenameOrderType::value_type(SuperRC, Order.
size()));
622 unsigned OrigR = RenameOrder[SuperRC];
623 unsigned EndR = ((OrigR == Order.
size()) ? 0 : OrigR);
626 if (R == 0)
R = Order.
size();
628 const MCRegister NewSuperReg = Order[
R];
630 if (!MRI.isAllocatable(NewSuperReg))
continue;
632 if (NewSuperReg == SuperReg)
continue;
640 for (MCRegister
Reg : Regs) {
642 if (
Reg == SuperReg) {
643 NewReg = NewSuperReg;
645 unsigned NewSubRegIdx = TRI->getSubRegIndex(SuperReg,
Reg);
646 if (NewSubRegIdx != 0)
647 NewReg = TRI->getSubReg(NewSuperReg, NewSubRegIdx);
653 if (!RenameRegisterMap[
Reg].
test(NewReg.
id())) {
662 if (State->IsLive(NewReg) ||
663 (KillIndices[
Reg.
id()] > DefIndices[NewReg.
id()])) {
668 for (MCRegAliasIterator AI(NewReg, TRI,
false); AI.isValid(); ++AI) {
669 MCRegister AliasReg = *AI;
670 if (State->IsLive(AliasReg) ||
671 (KillIndices[
Reg.
id()] > DefIndices[AliasReg.
id()])) {
673 <<
"(alias " <<
printReg(AliasReg, TRI) <<
" live)");
700 if (!Q.second.Operand->isDef() || !Q.second.Operand->isEarlyClobber())
711 RenameMap.insert(std::make_pair(
Reg, NewReg));
716 RenameOrder.erase(SuperRC);
717 RenameOrder.insert(RenameOrderType::value_type(SuperRC, R));
734 const std::vector<SUnit> &SUnits,
737 unsigned InsertPosIndex,
739 std::vector<unsigned> &KillIndices = State->GetKillIndices();
740 std::vector<unsigned> &DefIndices = State->GetDefIndices();
741 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
742 &RegRefs = State->GetRegRefs();
746 if (SUnits.empty())
return 0;
749 RenameOrderType RenameOrder;
752 std::map<MachineInstr *, const SUnit *> MISUnitMap;
753 for (
const SUnit &SU : SUnits)
754 MISUnitMap.insert(std::make_pair(SU.getInstr(), &SU));
759 const SUnit *CriticalPathSU =
nullptr;
761 if (CriticalPathSet.any()) {
762 for (
const SUnit &SU : SUnits) {
763 if (!CriticalPathSU ||
764 ((SU.getDepth() + SU.Latency) >
766 CriticalPathSU = &SU;
769 assert(CriticalPathSU &&
"Failed to find SUnit critical path");
770 CriticalPathMI = CriticalPathSU->
getInstr();
774 LLVM_DEBUG(
dbgs() <<
"\n===== Aggressive anti-dependency breaking\n");
776 for (
unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {
777 if (!State->IsLive(Reg))
789 unsigned Count = InsertPosIndex - 1;
794 if (
MI.isDebugInstr())
800 std::set<MCRegister> PassthruRegs;
801 GetPassthruRegs(
MI, PassthruRegs);
804 PrescanInstruction(
MI,
Count, PassthruRegs);
808 std::vector<const SDep *> Edges;
809 const SUnit *PathSU = MISUnitMap[&
MI];
815 if (&
MI == CriticalPathMI) {
817 CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->
getInstr() :
nullptr;
818 }
else if (CriticalPathSet.any()) {
819 ExcludeRegs = &CriticalPathSet;
826 for (
const SDep *Edge : Edges) {
827 SUnit *NextSU = Edge->getSUnit();
832 MCRegister AntiDepReg = Edge->getReg().asMCReg();
834 assert(AntiDepReg &&
"Anti-dependence on reg0?");
836 if (!MRI.isAllocatable(AntiDepReg)) {
840 }
else if (ExcludeRegs && ExcludeRegs->
test(AntiDepReg.
id())) {
845 }
else if (PassthruRegs.count(AntiDepReg) != 0) {
854 MI.findRegisterDefOperand(AntiDepReg,
nullptr);
855 assert(AntiDepOp &&
"Can't find index for defined register operand");
871 if (Pred.getSUnit() == NextSU ? (Pred.getKind() !=
SDep::Anti ||
872 Pred.getReg() != AntiDepReg)
874 Pred.getReg() == AntiDepReg)) {
880 if ((Pred.getSUnit() == NextSU) && (Pred.getKind() !=
SDep::Anti) &&
885 }
else if ((Pred.getSUnit() != NextSU) &&
887 (Pred.getReg() == AntiDepReg)) {
901 const unsigned GroupIndex = State->GetGroup(AntiDepReg);
902 if (GroupIndex == 0) {
910 std::map<MCRegister, MCRegister> RenameMap;
911 if (FindSuitableFreeRegisters(AntiDepReg, GroupIndex, RenameOrder,
914 <<
printReg(AntiDepReg, TRI) <<
":");
917 for (
const auto &
P : RenameMap) {
923 << RegRefs.count(CurrReg) <<
" refs)");
927 for (
const auto &Q :
make_range(RegRefs.equal_range(CurrReg))) {
928 Q.second.Operand->setReg(NewReg);
932 const SUnit *SU = MISUnitMap[Q.second.Operand->getParent()];
941 State->UnionGroups(NewReg, 0);
942 RegRefs.erase(NewReg);
943 DefIndices[NewReg.
id()] = DefIndices[CurrReg.
id()];
944 KillIndices[NewReg.
id()] = KillIndices[CurrReg.
id()];
946 State->UnionGroups(CurrReg, 0);
947 RegRefs.erase(CurrReg);
948 DefIndices[CurrReg.
id()] = KillIndices[CurrReg.
id()];
949 KillIndices[CurrReg.
id()] = ~0u;
950 assert(((KillIndices[CurrReg.
id()] == ~0u) !=
951 (DefIndices[CurrReg.
id()] == ~0u)) &&
952 "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
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
bool test(unsigned Idx) const
iterator_range< const_set_bits_iterator > set_bits() const
bool empty() const
empty - Tests whether there are no bits in this bitvector.
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.
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.
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.
FunctionAddr VTableAddr Count
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.