41#define DEBUG_TYPE "post-RA-sched"
46 cl::desc(
"Debug control for aggressive anti-dep breaker"),
51 cl::desc(
"Debug control for aggressive anti-dep breaker"),
56 : NumTargetRegs(TargetRegs), GroupNodes(TargetRegs, 0),
57 GroupNodeIndices(TargetRegs, 0), KillIndices(TargetRegs, 0),
58 DefIndices(TargetRegs, 0) {
59 const unsigned BBSize = BB->
size();
60 for (
unsigned i = 0; i < NumTargetRegs; ++i) {
63 GroupNodeIndices[i] = i;
66 DefIndices[i] = BBSize;
71 unsigned Node = GroupNodeIndices[Reg.id()];
79 unsigned Group, std::vector<MCRegister> &Regs,
80 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
82 for (
unsigned Reg = 0; Reg != NumTargetRegs; ++Reg) {
83 if ((
GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0))
89 assert(GroupNodes[0] == 0 &&
"GroupNode 0 not parent!");
90 assert(GroupNodeIndices[0] == 0 &&
"Reg 0 not in Group 0!");
97 unsigned Parent = (Group1 == 0) ? Group1 : Group2;
98 unsigned Other = (Parent == Group1) ? Group2 : Group1;
99 GroupNodes.at(
Other) = Parent;
107 unsigned idx = GroupNodes.size();
108 GroupNodes.push_back(idx);
109 GroupNodeIndices[Reg.id()] = idx;
116 return ((KillIndices[Reg.id()] != ~0u) && (DefIndices[Reg.id()] == ~0u));
122 : MF(MFi), MRI(MF.getRegInfo()), TII(MF.getSubtarget().getInstrInfo()),
123 TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI) {
127 BitVector CPSet = TRI->getAllocatableSet(MF, RC);
128 if (CriticalPathSet.none())
129 CriticalPathSet = CPSet;
131 CriticalPathSet |= CPSet;
136 : CriticalPathSet.set_bits())
dbgs()
150 std::vector<unsigned> &KillIndices = State->GetKillIndices();
151 std::vector<unsigned> &DefIndices = State->GetDefIndices();
155 for (
const auto &LI : Succ->liveins()) {
158 State->UnionGroups(Reg, 0);
159 KillIndices[Reg.id()] = BB->
size();
160 DefIndices[Reg.id()] = ~0u;
169 for (
const MCPhysReg *
I = MF.getRegInfo().getCalleeSavedRegs(); *
I;
172 if (!IsReturnBlock && !Pristine.
test(Reg))
176 State->UnionGroups(AliasReg, 0);
177 KillIndices[AliasReg.
id()] = BB->
size();
178 DefIndices[AliasReg.
id()] = ~0u;
189 unsigned InsertPosIndex) {
190 assert(
Count < InsertPosIndex &&
"Instruction index out of expected range!");
192 std::set<MCRegister> PassthruRegs;
193 GetPassthruRegs(
MI, PassthruRegs);
194 PrescanInstruction(
MI,
Count, PassthruRegs);
201 std::vector<unsigned> &DefIndices = State->GetDefIndices();
202 for (
unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {
209 if (State->IsLive(Reg)) {
211 <<
" " <<
printReg(Reg, TRI) <<
"=g" << State->GetGroup(Reg)
212 <<
"->g0(region live-out)");
213 State->UnionGroups(Reg, 0);
214 }
else if ((DefIndices[Reg] < InsertPosIndex)
215 && (DefIndices[Reg] >=
Count)) {
216 DefIndices[Reg] =
Count;
233 Op =
MI.findRegisterUseOperand(Reg,
nullptr,
true);
235 Op =
MI.findRegisterDefOperand(Reg,
nullptr);
237 return(
Op &&
Op->isImplicit());
240void AggressiveAntiDepBreaker::GetPassthruRegs(
242 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
244 if (!MO.
isReg())
continue;
245 if ((MO.
isDef() &&
MI.isRegTiedToUseOperand(i)) ||
246 IsImplicitDefUse(
MI, MO)) {
249 PassthruRegs.insert(
SubReg);
260 if (RegSet.
insert(Pred.getReg()).second)
261 Edges.push_back(&Pred);
270 unsigned NextDepth = 0;
274 const SUnit *PredSU = Pred.getSUnit();
275 unsigned PredLatency = Pred.getLatency();
276 unsigned PredTotalLatency = PredSU->
getDepth() + PredLatency;
279 if (NextDepth < PredTotalLatency ||
280 (NextDepth == PredTotalLatency && Pred.getKind() ==
SDep::Anti)) {
281 NextDepth = PredTotalLatency;
287 return (
Next) ?
Next->getSUnit() :
nullptr;
290void AggressiveAntiDepBreaker::HandleLastUse(
MCRegister Reg,
unsigned KillIdx,
293 const char *footer) {
294 std::vector<unsigned> &KillIndices = State->GetKillIndices();
295 std::vector<unsigned> &DefIndices = State->GetDefIndices();
296 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
297 &RegRefs = State->GetRegRefs();
303 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI)
304 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI)) {
309 if (!State->IsLive(
Reg)) {
310 KillIndices[
Reg.
id()] = KillIdx;
311 DefIndices[
Reg.
id()] = ~0
u;
313 State->LeaveGroup(
Reg);
324 if (!State->IsLive(SubregReg)) {
325 KillIndices[SubregReg] = KillIdx;
326 DefIndices[SubregReg] = ~0
u;
327 RegRefs.erase(SubregReg);
328 State->LeaveGroup(SubregReg);
334 << State->GetGroup(SubregReg) << tag);
342void AggressiveAntiDepBreaker::PrescanInstruction(
344 const std::set<MCRegister> &PassthruRegs) {
345 std::vector<unsigned> &DefIndices = State->GetDefIndices();
346 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
347 &RegRefs = State->GetRegRefs();
354 for (
const MachineOperand &MO :
MI.all_defs()) {
363 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
364 MachineOperand &MO =
MI.getOperand(i);
371 << State->GetGroup(
Reg));
378 if (
MI.isCall() ||
MI.hasExtraDefRegAllocReq() || TII->isPredicated(
MI) ||
381 State->UnionGroups(
Reg, 0);
386 for (MCRegAliasIterator AI(
Reg, TRI,
false); AI.isValid(); ++AI) {
387 MCRegister AliasReg = *AI;
388 if (State->IsLive(AliasReg)) {
389 State->UnionGroups(
Reg, AliasReg);
396 const TargetRegisterClass *RC =
nullptr;
397 if (i <
MI.getDesc().getNumOperands())
398 RC = TII->getRegClass(
MI.getDesc(), i, TRI);
399 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
407 for (
const MachineOperand &MO :
MI.all_defs()) {
412 if (
MI.isKill() || (PassthruRegs.count(
Reg) != 0))
416 for (MCRegAliasIterator AI(
Reg, TRI,
true); AI.isValid(); ++AI) {
423 if (TRI->isSuperRegister(
Reg, *AI) && State->IsLive(*AI))
426 DefIndices[(*AI).id()] =
Count;
434 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
435 &RegRefs = State->GetRegRefs();
454 bool Special =
MI.isCall() ||
MI.hasExtraSrcRegAllocReq() ||
455 TII->isPredicated(
MI) ||
MI.isInlineAsm();
459 for (
unsigned i = 0, e =
MI.getNumOperands(); i != e; ++i) {
460 MachineOperand &MO =
MI.getOperand(i);
467 << State->GetGroup(
Reg));
476 State->UnionGroups(
Reg, 0);
480 const TargetRegisterClass *RC =
nullptr;
481 if (i <
MI.getDesc().getNumOperands())
482 RC = TII->getRegClass(
MI.getDesc(), i, TRI);
483 AggressiveAntiDepState::RegisterReference RR = { &MO, RC };
495 for (
const MachineOperand &MO :
MI.operands()) {
496 if (!MO.
isReg())
continue;
503 State->UnionGroups(FirstReg,
Reg);
515 BitVector BV(TRI->getNumRegs(),
false);
521 for (
const auto &Q :
make_range(State->GetRegRefs().equal_range(
Reg))) {
522 const TargetRegisterClass *RC = Q.second.RC;
525 BitVector RCBV = TRI->getAllocatableSet(MF, RC);
539bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
540 MCRegister SuperReg,
unsigned AntiDepGroupIndex,
541 RenameOrderType &RenameOrder, std::map<MCRegister, MCRegister> &RenameMap) {
542 std::vector<unsigned> &KillIndices = State->GetKillIndices();
543 std::vector<unsigned> &DefIndices = State->GetDefIndices();
544 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
545 &RegRefs = State->GetRegRefs();
550 std::vector<MCRegister> Regs;
551 State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs);
552 assert(!Regs.empty() &&
"Empty register group!");
558 LLVM_DEBUG(
dbgs() <<
"\tRename Candidates for Group g" << AntiDepGroupIndex
560 std::map<MCRegister, BitVector> RenameRegisterMap;
561 for (MCRegister
Reg : Regs) {
563 if (RegRefs.count(
Reg) > 0) {
566 BitVector &BV = RenameRegisterMap[
Reg];
568 BV = GetRenameRegisters(
Reg);
580 for (MCRegister
Reg : Regs) {
581 if (
Reg == SuperReg)
continue;
582 bool IsSub = TRI->isSubRegister(SuperReg,
Reg);
593 static int renamecnt = 0;
597 dbgs() <<
"*** Performing rename " <<
printReg(SuperReg, TRI)
598 <<
" for debug ***\n";
610 const TargetRegisterClass *SuperRC =
611 TRI->getMinimalPhysRegClass(SuperReg, MVT::Other);
621 RenameOrder.insert(RenameOrderType::value_type(SuperRC, Order.
size()));
623 unsigned OrigR = RenameOrder[SuperRC];
624 unsigned EndR = ((OrigR == Order.
size()) ? 0 : OrigR);
627 if (R == 0)
R = Order.
size();
629 const MCRegister NewSuperReg = Order[
R];
631 if (!MRI.isAllocatable(NewSuperReg))
continue;
633 if (NewSuperReg == SuperReg)
continue;
641 for (MCRegister
Reg : Regs) {
643 if (
Reg == SuperReg) {
644 NewReg = NewSuperReg;
646 unsigned NewSubRegIdx = TRI->getSubRegIndex(SuperReg,
Reg);
647 if (NewSubRegIdx != 0)
648 NewReg = TRI->getSubReg(NewSuperReg, NewSubRegIdx);
654 if (!RenameRegisterMap[
Reg].
test(NewReg.
id())) {
663 if (State->IsLive(NewReg) ||
664 (KillIndices[
Reg.
id()] > DefIndices[NewReg.
id()])) {
669 for (MCRegAliasIterator AI(NewReg, TRI,
false); AI.isValid(); ++AI) {
670 MCRegister AliasReg = *AI;
671 if (State->IsLive(AliasReg) ||
672 (KillIndices[
Reg.
id()] > DefIndices[AliasReg.
id()])) {
674 <<
"(alias " <<
printReg(AliasReg, TRI) <<
" live)");
701 if (!Q.second.Operand->isDef() || !Q.second.Operand->isEarlyClobber())
712 RenameMap.insert(std::make_pair(
Reg, NewReg));
717 RenameOrder.erase(SuperRC);
718 RenameOrder.insert(RenameOrderType::value_type(SuperRC, R));
735 const std::vector<SUnit> &SUnits,
738 unsigned InsertPosIndex,
740 std::vector<unsigned> &KillIndices = State->GetKillIndices();
741 std::vector<unsigned> &DefIndices = State->GetDefIndices();
742 std::multimap<MCRegister, AggressiveAntiDepState::RegisterReference>
743 &RegRefs = State->GetRegRefs();
747 if (SUnits.empty())
return 0;
750 RenameOrderType RenameOrder;
753 std::map<MachineInstr *, const SUnit *> MISUnitMap;
754 for (
const SUnit &SU : SUnits)
755 MISUnitMap.insert(std::make_pair(SU.getInstr(), &SU));
760 const SUnit *CriticalPathSU =
nullptr;
762 if (CriticalPathSet.any()) {
763 for (
const SUnit &SU : SUnits) {
764 if (!CriticalPathSU ||
765 ((SU.getDepth() + SU.Latency) >
767 CriticalPathSU = &SU;
770 assert(CriticalPathSU &&
"Failed to find SUnit critical path");
771 CriticalPathMI = CriticalPathSU->
getInstr();
775 LLVM_DEBUG(
dbgs() <<
"\n===== Aggressive anti-dependency breaking\n");
777 for (
unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {
778 if (!State->IsLive(Reg))
790 unsigned Count = InsertPosIndex - 1;
795 if (
MI.isDebugInstr())
801 std::set<MCRegister> PassthruRegs;
802 GetPassthruRegs(
MI, PassthruRegs);
805 PrescanInstruction(
MI,
Count, PassthruRegs);
809 std::vector<const SDep *> Edges;
810 const SUnit *PathSU = MISUnitMap[&
MI];
816 if (&
MI == CriticalPathMI) {
818 CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->
getInstr() :
nullptr;
819 }
else if (CriticalPathSet.any()) {
820 ExcludeRegs = &CriticalPathSet;
827 for (
const SDep *Edge : Edges) {
828 SUnit *NextSU = Edge->getSUnit();
833 MCRegister AntiDepReg = Edge->getReg().asMCReg();
835 assert(AntiDepReg &&
"Anti-dependence on reg0?");
837 if (!MRI.isAllocatable(AntiDepReg)) {
841 }
else if (ExcludeRegs && ExcludeRegs->
test(AntiDepReg.
id())) {
846 }
else if (PassthruRegs.count(AntiDepReg) != 0) {
855 MI.findRegisterDefOperand(AntiDepReg,
nullptr);
856 assert(AntiDepOp &&
"Can't find index for defined register operand");
872 if (Pred.getSUnit() == NextSU ? (Pred.getKind() !=
SDep::Anti ||
873 Pred.getReg() != AntiDepReg)
875 Pred.getReg() == AntiDepReg)) {
881 if ((Pred.getSUnit() == NextSU) && (Pred.getKind() !=
SDep::Anti) &&
886 }
else if ((Pred.getSUnit() != NextSU) &&
888 (Pred.getReg() == AntiDepReg)) {
902 const unsigned GroupIndex = State->GetGroup(AntiDepReg);
903 if (GroupIndex == 0) {
911 std::map<MCRegister, MCRegister> RenameMap;
912 if (FindSuitableFreeRegisters(AntiDepReg, GroupIndex, RenameOrder,
915 <<
printReg(AntiDepReg, TRI) <<
":");
918 for (
const auto &
P : RenameMap) {
924 << RegRefs.count(CurrReg) <<
" refs)");
928 for (
const auto &Q :
make_range(RegRefs.equal_range(CurrReg))) {
929 Q.second.Operand->setReg(NewReg);
933 const SUnit *SU = MISUnitMap[Q.second.Operand->getParent()];
942 State->UnionGroups(NewReg, 0);
943 RegRefs.erase(NewReg);
944 DefIndices[NewReg.
id()] = DefIndices[CurrReg.
id()];
945 KillIndices[NewReg.
id()] = KillIndices[CurrReg.
id()];
947 State->UnionGroups(CurrReg, 0);
948 RegRefs.erase(CurrReg);
949 DefIndices[CurrReg.
id()] = KillIndices[CurrReg.
id()];
950 KillIndices[CurrReg.
id()] = ~0u;
951 assert(((KillIndices[CurrReg.
id()] == ~0u) !=
952 (DefIndices[CurrReg.
id()] == ~0u)) &&
953 "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.