80#define DEBUG_TYPE "machine-cp"
82STATISTIC(NumDeletes,
"Number of dead copies deleted");
83STATISTIC(NumCopyForwards,
"Number of copy uses forwarded");
84STATISTIC(NumCopyBackwardPropagated,
"Number of copy defs backward propagated");
85STATISTIC(SpillageChainsLength,
"Length of spillage chains");
86STATISTIC(NumSpillageChains,
"Number of spillage chains");
88 "Controls which register COPYs are forwarded");
100 "MachineCopyPropagation should be run after register allocation!");
108 return asPhysMCReg(DSP.
Source);
110std::pair<MCRegister, MCRegister> getDstSrcMCRegs(
const DestSourcePair &DSP) {
111 return {getDstMCReg(DSP), getSrcMCReg(DSP)};
118 return TII.isCopyInstr(
MI);
128 MachineInstr *MI =
nullptr;
129 MachineInstr *LastSeenUseInCopy =
nullptr;
130 SmallPtrSet<MachineInstr *, 4> SrcUsers;
135 DenseMap<MCRegUnit, CopyInfo> Copies;
140 DenseMap<const uint32_t *, BitVector> RegMaskToPreservedRegUnits;
144 BitVector &getPreservedRegUnits(
const MachineOperand &RegMaskOp,
145 const TargetRegisterInfo &
TRI) {
146 const uint32_t *RegMask = RegMaskOp.
getRegMask();
147 auto [It,
Inserted] = RegMaskToPreservedRegUnits.try_emplace(RegMask);
150 BitVector &PreservedRegUnits = It->second;
152 PreservedRegUnits.
resize(
TRI.getNumRegUnits());
153 for (
unsigned SafeReg = 0,
E =
TRI.getNumRegs(); SafeReg <
E; ++SafeReg)
155 for (MCRegUnit SafeUnit :
TRI.regunits(SafeReg))
156 PreservedRegUnits.
set(
static_cast<unsigned>(SafeUnit));
158 return PreservedRegUnits;
164 const TargetRegisterInfo &
TRI) {
165 for (MCRegister
Reg : Regs) {
167 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
168 auto CI = Copies.find(Unit);
169 if (CI != Copies.end())
170 CI->second.Avail =
false;
176 void invalidateRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
177 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
182 SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;
183 auto InvalidateCopy = [&](MachineInstr *
MI) {
184 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
185 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
186 auto DstUnits =
TRI.regunits(Dst);
187 auto SrcUnits =
TRI.regunits(Src);
192 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
193 auto I = Copies.find(Unit);
194 if (
I != Copies.end()) {
195 if (MachineInstr *
MI =
I->second.MI)
197 if (MachineInstr *
MI =
I->second.LastSeenUseInCopy)
201 for (MCRegUnit Unit : RegUnitsToInvalidate)
206 void clobberRegUnit(MCRegUnit Unit,
const TargetRegisterInfo &
TRI,
207 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
208 auto I = Copies.find(Unit);
209 if (
I != Copies.end()) {
212 markRegsUnavailable(
I->second.DefRegs,
TRI);
215 if (MachineInstr *
MI =
I->second.MI) {
216 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
217 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
219 markRegsUnavailable(Dst,
TRI);
233 for (MCRegUnit SrcUnit :
TRI.regunits(Src)) {
234 auto SrcCopy = Copies.find(SrcUnit);
235 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {
239 for (
auto Itr = SrcCopy->second.DefRegs.begin();
240 Itr != SrcCopy->second.DefRegs.end(); Itr++) {
242 SrcCopy->second.DefRegs.erase(Itr);
248 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {
249 Copies.erase(SrcCopy);
263 void clobberRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
264 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
265 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
266 clobberRegUnit(Unit,
TRI,
TII, UseCopyInstr);
273 bool trackSrcUsers(MCRegister
Reg, MachineInstr &
MI,
274 const TargetRegisterInfo &
TRI,
const TargetInstrInfo &
TII,
276 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
277 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
281 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
282 MCRegister Src = getSrcMCReg(CopyOperands);
288 auto I = Copies.find(RU);
289 if (
I == Copies.end())
292 I->second.SrcUsers.insert(&
MI);
297 SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister
Reg,
298 const TargetRegisterInfo &
TRI) {
299 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
300 auto I = Copies.find(RU);
301 if (
I == Copies.end())
303 return I->second.SrcUsers;
307 void trackCopy(MachineInstr *
MI,
const TargetRegisterInfo &
TRI,
308 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
309 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
310 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
313 for (MCRegUnit Unit :
TRI.regunits(Dst))
314 Copies[
Unit] = {
MI,
nullptr, {}, {},
true};
318 for (MCRegUnit Unit :
TRI.regunits(Src)) {
321 Copy.DefRegs.push_back(Dst);
322 Copy.LastSeenUseInCopy =
MI;
326 bool hasAnyCopies() {
327 return !Copies.empty();
330 MachineInstr *findCopyForUnit(MCRegUnit RegUnit,
331 const TargetRegisterInfo &
TRI,
332 bool MustBeAvailable =
false) {
333 auto CI = Copies.find(RegUnit);
334 if (CI == Copies.end())
336 if (MustBeAvailable && !CI->second.Avail)
338 return CI->second.MI;
341 MachineInstr *findCopyDefViaUnit(MCRegUnit RegUnit,
342 const TargetRegisterInfo &
TRI) {
343 auto CI = Copies.find(RegUnit);
344 if (CI == Copies.end())
346 if (CI->second.DefRegs.size() != 1)
348 MCRegUnit RU = *
TRI.regunits(CI->second.DefRegs[0]).begin();
349 return findCopyForUnit(RU,
TRI,
true);
352 MachineInstr *findAvailBackwardCopy(MachineInstr &
I, MCRegister
Reg,
353 const TargetRegisterInfo &
TRI,
354 const TargetInstrInfo &
TII,
356 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
357 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
362 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
363 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
364 if (!
TRI.isSubRegisterEq(AvailSrc,
Reg))
367 for (
const MachineInstr &
MI :
369 for (
const MachineOperand &MO :
MI.operands())
372 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
378 MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister
Reg,
379 const TargetRegisterInfo &
TRI,
380 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
383 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
384 MachineInstr *AvailCopy =
385 findCopyForUnit(RU,
TRI,
true);
390 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
391 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
392 if (!
TRI.isSubRegisterEq(AvailDst,
Reg))
397 for (
const MachineInstr &
MI :
399 for (
const MachineOperand &MO :
MI.operands())
401 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
408 MachineInstr *findLastSeenDefInCopy(
const MachineInstr &Current,
410 const TargetRegisterInfo &
TRI,
411 const TargetInstrInfo &
TII,
413 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
414 auto CI = Copies.find(RU);
415 if (CI == Copies.end() || !CI->second.Avail)
418 MachineInstr *DefCopy = CI->second.MI;
419 DestSourcePair CopyOperands = *isCopyInstr(*DefCopy,
TII, UseCopyInstr);
420 MCRegister Dst = getDstMCReg(CopyOperands);
421 if (!
TRI.isSubRegisterEq(Dst,
Reg))
427 void clobberNonPreservedRegs(
const BitVector &PreservedRegUnits,
428 const TargetRegisterInfo &
TRI,
429 const TargetInstrInfo &
TII) {
431 for (
auto &[Unit,
_] : Copies)
432 if (!PreservedRegUnits.
test(
static_cast<unsigned>(Unit)))
435 for (MCRegUnit Unit : UnitsToClobber) {
440 auto RegUnitInfo = Copies.find(Unit);
441 if (RegUnitInfo == Copies.end())
444 for (MCRegister DstReg : RegUnitInfo->second.DefRegs) {
445 for (MCRegUnit DstUnit :
TRI.regunits(DstReg)) {
446 if (!PreservedRegUnits.
test(
static_cast<unsigned>(DstUnit))) {
447 if (
auto CI = Copies.find(DstUnit); CI != Copies.end()) {
448 CI->second.Avail =
false;
453 Copies.erase(RegUnitInfo);
458 MachineInstr *findLastSeenUseInCopy(MCRegister
Reg,
459 const TargetRegisterInfo &
TRI) {
460 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
461 auto CI = Copies.find(RU);
462 if (CI == Copies.end())
464 return CI->second.LastSeenUseInCopy;
472class MachineCopyPropagation {
473 const TargetRegisterInfo *TRI =
nullptr;
474 const TargetInstrInfo *TII =
nullptr;
475 const MachineRegisterInfo *MRI =
nullptr;
481 MachineCopyPropagation(
bool CopyInstr =
false)
484 bool run(MachineFunction &MF);
487 typedef enum { DebugUse =
false, RegularUse =
true } DebugType;
490 void readSuccessorLiveIns(
const MachineBasicBlock &
MBB);
491 void forwardCopyPropagateBlock(MachineBasicBlock &
MBB);
492 void backwardCopyPropagateBlock(MachineBasicBlock &
MBB);
493 void eliminateSpillageCopies(MachineBasicBlock &
MBB);
494 bool eraseIfRedundant(MachineInstr &Copy, MCRegister Dst, MCRegister Src);
495 void forwardUses(MachineInstr &
MI);
496 void propagateDefs(MachineInstr &
MI);
497 bool isForwardableRegClassCopy(
const MachineInstr &Copy,
498 const MachineInstr &UseI,
unsigned UseIdx);
499 bool isBackwardPropagatableRegClassCopy(
const MachineInstr &Copy,
500 const MachineInstr &UseI,
502 bool isBackwardPropagatableCopy(
const MachineInstr &Copy,
503 const DestSourcePair &CopyOperands);
506 bool isNeverRedundant(MCRegister CopyOperand) {
510 return MRI->isReserved(CopyOperand);
514 bool isNeverRedundant(
const MachineInstr &Copy) {
518 bool hasImplicitOverlap(
const MachineInstr &
MI,
const MachineOperand &Use);
519 bool hasOverlappingMultipleDef(
const MachineInstr &
MI,
520 const MachineOperand &MODef, MCRegister Def);
521 bool canUpdateSrcUsers(
const MachineInstr &Copy,
522 const MachineOperand &CopySrc);
525 SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
528 DenseMap<MachineInstr *, SmallPtrSet<MachineInstr *, 2>> CopyDbgUsers;
532 bool Changed =
false;
541 MachineCopyPropagationLegacy(
bool UseCopyInstr =
false)
542 : MachineFunctionPass(ID), UseCopyInstr(UseCopyInstr) {}
544 void getAnalysisUsage(AnalysisUsage &AU)
const override {
549 bool runOnMachineFunction(MachineFunction &MF)
override;
551 MachineFunctionProperties getRequiredProperties()
const override {
552 return MachineFunctionProperties().setNoVRegs();
558char MachineCopyPropagationLegacy::ID = 0;
563 "Machine Copy Propagation Pass",
false,
false)
570 for (MCRegUnit Unit :
TRI->regunits(
Reg)) {
571 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
572 if (DT == RegularUse) {
573 LLVM_DEBUG(dbgs() <<
"MCP: Copy is used - not dead: "; Copy->dump());
574 MaybeDeadCopies.remove(Copy);
576 CopyDbgUsers[Copy].insert(&Reader);
582void MachineCopyPropagation::readSuccessorLiveIns(
584 if (MaybeDeadCopies.empty())
589 for (
const auto &LI : Succ->liveins()) {
590 for (MCRegUnitMaskIterator
U(LI.PhysReg,
TRI);
U.isValid(); ++U) {
592 if ((Mask & LI.LaneMask).any()) {
593 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *
TRI))
594 MaybeDeadCopies.remove(Copy);
612 auto [PreviousDst, PreviousSrc] = getDstSrcMCRegs(CopyOperands);
613 if (Src == PreviousSrc && Dst == PreviousDst)
615 if (!
TRI->isSubRegister(PreviousSrc, Src))
617 unsigned SubIdx =
TRI->getSubRegIndex(PreviousSrc, Src);
618 return SubIdx ==
TRI->getSubRegIndex(PreviousDst, Dst);
624bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
625 MCRegister Dst, MCRegister Src) {
626 if (isNeverRedundant(Copy) || isNeverRedundant(Src) || isNeverRedundant(Dst))
630 MachineInstr *PrevCopy =
631 Tracker.findAvailCopy(Copy, Dst, *
TRI, *
TII, UseCopyInstr);
635 DestSourcePair PrevCopyOperands = *isCopyInstr(*PrevCopy, *
TII, UseCopyInstr);
646 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
648 MCRegister CopyDst = getDstMCReg(CopyOperands);
649 assert(CopyDst == Src || CopyDst == Dst);
650 for (MachineInstr &
MI :
652 MI.clearRegisterKills(CopyDst,
TRI);
660 Copy.eraseFromParent();
666bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
667 const MachineInstr &Copy,
const MachineInstr &UseI,
unsigned UseIdx) {
668 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
669 MCRegister Dst = getDstMCReg(CopyOperands);
671 if (
const TargetRegisterClass *URC =
673 return URC->contains(Dst);
680bool MachineCopyPropagation::isBackwardPropagatableCopy(
681 const MachineInstr &Copy,
const DestSourcePair &CopyOperands) {
682 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
687 if (isNeverRedundant(Copy) || isNeverRedundant(Dst) || isNeverRedundant(Src))
696bool MachineCopyPropagation::isForwardableRegClassCopy(
const MachineInstr &Copy,
697 const MachineInstr &UseI,
699 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
700 MCRegister CopySrc = getSrcMCReg(CopyOperands);
704 if (
const TargetRegisterClass *URC =
706 return URC->contains(CopySrc);
708 std::optional<DestSourcePair> UseICopyOperands =
709 isCopyInstr(UseI, *
TII, UseCopyInstr);
710 if (!UseICopyOperands)
733 MCRegister UseDst = getDstMCReg(*UseICopyOperands);
735 bool IsCrossClass =
false;
736 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
737 if (RC->contains(CopySrc) && RC->contains(UseDst)) {
739 if (
TRI->getCrossCopyRegClass(RC) != RC) {
751 MCRegister CopyDst = getDstMCReg(CopyOperands);
752 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
753 if (RC->contains(CopySrc) && RC->contains(CopyDst) &&
754 TRI->getCrossCopyRegClass(RC) != RC)
768bool MachineCopyPropagation::hasImplicitOverlap(
const MachineInstr &
MI,
769 const MachineOperand &Use) {
770 for (
const MachineOperand &MIUse :
MI.uses())
771 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
772 MIUse.isUse() &&
TRI->regsOverlap(
Use.getReg(), MIUse.getReg()))
782bool MachineCopyPropagation::hasOverlappingMultipleDef(
783 const MachineInstr &
MI,
const MachineOperand &MODef, MCRegister Def) {
784 for (
const MachineOperand &MIDef :
MI.all_defs()) {
785 if ((&MIDef != &MODef) && MIDef.isReg() &&
786 TRI->regsOverlap(Def, MIDef.getReg()))
795bool MachineCopyPropagation::canUpdateSrcUsers(
const MachineInstr &Copy,
796 const MachineOperand &CopySrc) {
797 assert(CopySrc.
isReg() &&
"Expected a register operand");
798 for (
auto *SrcUser : Tracker.getSrcUsers(CopySrc.
getReg(), *
TRI)) {
799 if (hasImplicitOverlap(*SrcUser, CopySrc))
802 for (MachineOperand &MO : SrcUser->uses()) {
803 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.
getReg())
805 if (MO.isTied() || !MO.isRenamable() ||
806 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
816void MachineCopyPropagation::forwardUses(MachineInstr &
MI) {
817 if (!Tracker.hasAnyCopies())
823 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx < OpEnd;
825 MachineOperand &MOUse =
MI.getOperand(
OpIdx);
845 *
TRI, *
TII, UseCopyInstr);
849 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
850 auto [CopyDst, CopySrc] = getDstSrcMCRegs(CopyOperands);
851 const MachineOperand &CopySrcOperand = *CopyOperands.
Source;
853 MCRegister ForwardedReg = CopySrc;
856 if (MOUse.
getReg() != CopyDst) {
857 unsigned SubRegIdx =
TRI->getSubRegIndex(CopyDst, MOUse.
getReg());
859 "MI source is not a sub-register of Copy destination");
860 ForwardedReg =
TRI->getSubReg(CopySrc, SubRegIdx);
861 if (!ForwardedReg ||
TRI->isArtificial(ForwardedReg)) {
862 LLVM_DEBUG(
dbgs() <<
"MCP: Copy source does not have sub-register "
863 <<
TRI->getSubRegIndexName(SubRegIdx) <<
'\n');
872 if (!isForwardableRegClassCopy(*Copy,
MI,
OpIdx))
875 if (hasImplicitOverlap(
MI, MOUse))
881 if (isCopyInstr(
MI, *
TII, UseCopyInstr) &&
882 MI.modifiesRegister(CopySrc,
TRI) &&
883 !
MI.definesRegister(CopySrc,
nullptr)) {
889 LLVM_DEBUG(
dbgs() <<
"MCP: Skipping forwarding due to debug counter:\n "
896 <<
"\n in " <<
MI <<
" from " << *Copy);
898 MOUse.
setReg(ForwardedReg);
907 for (MachineInstr &KMI :
909 KMI.clearRegisterKills(CopySrc,
TRI);
916void MachineCopyPropagation::forwardCopyPropagateBlock(MachineBasicBlock &
MBB) {
922 std::optional<DestSourcePair> CopyOperands =
923 isCopyInstr(
MI, *
TII, UseCopyInstr);
925 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
926 if (!
TRI->regsOverlap(Dst, Src)) {
942 if (eraseIfRedundant(
MI, Dst, Src) || eraseIfRedundant(
MI, Src, Dst))
948 for (
const MachineOperand &MO :
MI.operands())
949 if (MO.isReg() && MO.isEarlyClobber()) {
956 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
963 if (
TII->simplifyInstruction(
MI)) {
968 CopyOperands = isCopyInstr(
MI, *
TII, UseCopyInstr);
970 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
971 if (!
TRI->regsOverlap(Dst, Src)) {
974 if (!isNeverRedundant(
MI) && !isNeverRedundant(Dst))
975 MaybeDeadCopies.insert(&
MI);
980 const MachineOperand *RegMask =
nullptr;
981 for (
const MachineOperand &MO :
MI.operands()) {
991 "MachineCopyPropagation should be run after register allocation!");
993 if (MO.isDef() && !MO.isEarlyClobber()) {
999 }
else if (MO.readsReg()) {
1008 BitVector &PreservedRegUnits =
1009 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
1012 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
1013 MaybeDeadCopies.begin();
1014 DI != MaybeDeadCopies.end();) {
1015 MachineInstr *MaybeDead = *DI;
1016 std::optional<DestSourcePair> CopyOperands =
1017 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1018 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
1019 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(
Reg));
1028 bool MIRefedinCopyInfo =
false;
1029 for (MCRegUnit RegUnit :
TRI->regunits(
Reg)) {
1030 if (!PreservedRegUnits.
test(
static_cast<unsigned>(RegUnit)))
1031 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1033 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1034 MIRefedinCopyInfo =
true;
1041 DI = MaybeDeadCopies.erase(DI);
1044 if (MIRefedinCopyInfo)
1047 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1057 for (MCRegister
Reg : Defs)
1058 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1061 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1062 if (!
TRI->regsOverlap(Dst, Src)) {
1063 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1073 readSuccessorLiveIns(
MBB);
1079 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1080 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1083 DestSourcePair CopyOperands =
1084 *isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1086 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1087 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(Dst));
1090 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1101 MaybeDeadCopies.clear();
1102 CopyDbgUsers.clear();
1106void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1107 if (!Tracker.hasAnyCopies())
1110 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1112 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1128 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1133 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1134 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1136 if (MODef.
getReg() != Src)
1139 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1142 if (hasImplicitOverlap(
MI, MODef))
1145 if (hasOverlappingMultipleDef(
MI, MODef, Dst))
1148 if (!canUpdateSrcUsers(*Copy, *CopyOperands.
Source))
1153 <<
MI <<
" from " << *Copy);
1158 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1159 for (MachineOperand &MO : SrcUser->uses()) {
1160 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1168 MaybeDeadCopies.insert(Copy);
1170 ++NumCopyBackwardPropagated;
1174void MachineCopyPropagation::backwardCopyPropagateBlock(
1175 MachineBasicBlock &
MBB) {
1181 std::optional<DestSourcePair> CopyOperands =
1182 isCopyInstr(
MI, *
TII, UseCopyInstr);
1183 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1184 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1186 if (!
TRI->regsOverlap(Dst, Src)) {
1189 if (isBackwardPropagatableCopy(
MI, *CopyOperands)) {
1190 Tracker.invalidateRegister(Src, *
TRI, *
TII, UseCopyInstr);
1191 Tracker.invalidateRegister(Dst, *
TRI, *
TII, UseCopyInstr);
1192 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1199 for (
const MachineOperand &MO :
MI.operands())
1200 if (MO.isReg() && MO.isEarlyClobber()) {
1204 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1208 for (
const MachineOperand &MO :
MI.operands()) {
1216 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1219 if (MO.readsReg()) {
1224 for (MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1225 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1226 CopyDbgUsers[
Copy].insert(&
MI);
1229 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1232 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1239 for (
auto *Copy : MaybeDeadCopies) {
1240 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1241 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1242 const auto &DbgUsers = CopyDbgUsers[
Copy];
1247 Copy->eraseFromParent();
1251 MaybeDeadCopies.clear();
1252 CopyDbgUsers.clear();
1260 auto &SC = SpillChain[Leader];
1261 auto &RC = ReloadChain[Leader];
1262 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1306void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &
MBB) {
1309 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1314 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1317 DenseSet<const MachineInstr *> CopySourceInvalid;
1319 auto TryFoldSpillageCopies =
1320 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1321 const SmallVectorImpl<MachineInstr *> &RC) {
1322 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1337 for (
const MachineInstr *Spill :
drop_begin(SC))
1338 if (CopySourceInvalid.
count(Spill))
1341 for (
const MachineInstr *Reload :
drop_end(RC))
1342 if (CopySourceInvalid.
count(Reload))
1346 return TRI->getCommonMinimalPhysRegClass(Dst, Src);
1349 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1350 const MachineOperand *
New) {
1351 for (MachineOperand &MO :
MI->operands()) {
1353 MO.setReg(
New->getReg());
1357 DestSourcePair InnerMostSpillCopy =
1358 *isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1359 DestSourcePair OuterMostSpillCopy =
1360 *isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1361 DestSourcePair InnerMostReloadCopy =
1362 *isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1363 DestSourcePair OuterMostReloadCopy =
1364 *isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1365 if (!CheckCopyConstraint(getSrcMCReg(OuterMostSpillCopy),
1366 getSrcMCReg(InnerMostSpillCopy)) ||
1367 !CheckCopyConstraint(getDstMCReg(InnerMostReloadCopy),
1368 getDstMCReg(OuterMostReloadCopy)))
1371 SpillageChainsLength += SC.
size() + RC.size();
1372 NumSpillageChains += 1;
1374 OuterMostSpillCopy.
Source);
1375 UpdateReg(RC[0], InnerMostReloadCopy.
Source,
1378 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1379 SC[
I]->eraseFromParent();
1380 RC[
I]->eraseFromParent();
1385 auto GetFoldableCopy =
1386 [
this](
const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
1387 if (MaybeCopy.getNumImplicitOperands() > 0)
1388 return std::nullopt;
1389 std::optional<DestSourcePair> CopyOperands =
1390 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1392 return std::nullopt;
1393 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1394 if (Src && Dst && !
TRI->regsOverlap(Src, Dst) &&
1395 CopyOperands->Source->isRenamable() &&
1396 CopyOperands->Destination->isRenamable())
1397 return CopyOperands;
1399 return std::nullopt;
1402 auto IsSpillReloadPair = [&](
const MachineInstr &
Spill,
1403 const MachineInstr &Reload) {
1404 std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
1405 if (!FoldableSpillCopy)
1407 std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
1408 if (!FoldableReloadCopy)
1410 return FoldableSpillCopy->Source->getReg() ==
1411 FoldableReloadCopy->Destination->getReg() &&
1412 FoldableSpillCopy->Destination->getReg() ==
1413 FoldableReloadCopy->Source->getReg();
1416 auto IsChainedCopy = [&](
const MachineInstr &Prev,
1417 const MachineInstr &Current) {
1418 std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
1419 if (!FoldablePrevCopy)
1421 std::optional<DestSourcePair> FoldableCurrentCopy =
1422 GetFoldableCopy(Current);
1423 if (!FoldableCurrentCopy)
1425 return FoldablePrevCopy->Source->getReg() ==
1426 FoldableCurrentCopy->Destination->getReg();
1430 std::optional<DestSourcePair> CopyOperands =
1431 isCopyInstr(
MI, *
TII, UseCopyInstr);
1434 SmallSet<Register, 8> RegsToClobber;
1435 if (!CopyOperands) {
1436 for (
const MachineOperand &MO :
MI.operands()) {
1437 if (MO.isRegMask()) {
1438 BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *
TRI);
1439 Tracker.clobberNonPreservedRegs(PreservedRegUnits, *
TRI, *
TII);
1447 MachineInstr *LastUseCopy =
1454 CopySourceInvalid.
insert(LastUseCopy);
1468 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1475 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1477 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1479 MachineInstr *MaybeSpill =
1480 Tracker.findLastSeenDefInCopy(
MI, Src, *
TRI, *
TII, UseCopyInstr);
1481 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1482 if (!MaybeSpillIsChained && MaybeSpill &&
1483 IsSpillReloadPair(*MaybeSpill,
MI)) {
1518 MachineInstr *MaybePrevReload = Tracker.findLastSeenUseInCopy(Dst, *
TRI);
1519 auto Leader = ChainLeader.
find(MaybePrevReload);
1520 MachineInstr *
L =
nullptr;
1521 if (Leader == ChainLeader.
end() ||
1522 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1525 "SpillChain should not have contained newly found chain");
1527 assert(MaybePrevReload &&
1528 "Found a valid leader through nullptr should not happend");
1531 "Existing chain's length should be larger than zero");
1534 "Newly found paired spill-reload should not belong to any chain "
1536 ChainLeader.
insert({MaybeSpill,
L});
1538 SpillChain[
L].push_back(MaybeSpill);
1539 ReloadChain[
L].push_back(&
MI);
1542 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1559 Tracker.clobberRegister(Src, *
TRI, *
TII, UseCopyInstr);
1563 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1566 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1567 auto &SC =
I->second;
1569 "Reload chain of the same leader should exist");
1570 auto &RC = ReloadChain[
I->first];
1571 TryFoldSpillageCopies(SC, RC);
1574 MaybeDeadCopies.clear();
1575 CopyDbgUsers.clear();
1579bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1583 return MachineCopyPropagation(UseCopyInstr).run(MF);
1590 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1598 bool IsSpillageCopyElimEnabled =
false;
1601 IsSpillageCopyElimEnabled =
1605 IsSpillageCopyElimEnabled =
true;
1608 IsSpillageCopyElimEnabled =
false;
1619 if (IsSpillageCopyElimEnabled)
1620 eliminateSpillageCopies(
MBB);
1621 backwardCopyPropagateBlock(
MBB);
1622 forwardCopyPropagateBlock(
MBB);
1628MachineFunctionPass *
1630 return new MachineCopyPropagationLegacy(UseCopyInstr);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
const HexagonInstrInfo * TII
static cl::opt< cl::boolOrDefault > EnableSpillageCopyElimination("enable-spill-copy-elim", cl::Hidden)
static void printSpillReloadChain(DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &SpillChain, DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &ReloadChain, MachineInstr *Leader)
static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src, MCRegister Dst, const TargetRegisterInfo *TRI, const TargetInstrInfo *TII, bool UseCopyInstr)
Return true if PreviousCopy did copy register Src to register Dst.
static cl::opt< bool > MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false), cl::Hidden)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
bool test(unsigned Idx) const
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Represents analyses that only rely on functions' control flow.
static bool shouldExecute(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Wrapper class representing physical registers. Should be passed by value.
An RAII based helper class to modify MachineFunctionProperties when running pass.
iterator_range< succ_iterator > successors()
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI const TargetRegisterClass * getRegClassConstraint(unsigned OpIdx, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const
Compute the static register class constraint for operand OpIdx.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
LLVM_ABI void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
LLVM_ABI bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
void updateDbgUsersToReg(MCRegister OldReg, MCRegister NewReg, ArrayRef< MachineInstr * > Users) const
updateDbgUsersToReg - Update a collection of debug instructions to refer to the designated register.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
void insert_range(Range &&R)
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool enableSpillageCopyElimination() const
Enable spillage copy elimination in MachineCopyPropagation pass.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
reverse_self_iterator getReverseIterator()
self_iterator getIterator()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI MachineFunctionPass * createMachineCopyPropagationPass(bool UseCopyInstr)
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.
LLVM_ABI char & MachineCopyPropagationID
MachineCopyPropagation - This pass performs copy propagation on machine instructions.
const MachineOperand * Source
const MachineOperand * Destination