81#define DEBUG_TYPE "machine-cp"
83STATISTIC(NumDeletes,
"Number of dead copies deleted");
84STATISTIC(NumCopyForwards,
"Number of copy uses forwarded");
85STATISTIC(NumCopyBackwardPropagated,
"Number of copy defs backward propagated");
86STATISTIC(SpillageChainsLength,
"Length of spillage chains");
87STATISTIC(NumSpillageChains,
"Number of spillage chains");
89 "Controls which register COPYs are forwarded");
101 "MachineCopyPropagation should be run after register allocation!");
109 return asPhysMCReg(DSP.
Source);
111std::pair<MCRegister, MCRegister> getDstSrcMCRegs(
const DestSourcePair &DSP) {
112 return {getDstMCReg(DSP), getSrcMCReg(DSP)};
119 return TII.isCopyInstr(
MI);
129 MachineInstr *MI =
nullptr;
130 MachineInstr *LastSeenUseInCopy =
nullptr;
131 SmallPtrSet<MachineInstr *, 4> SrcUsers;
136 DenseMap<MCRegUnit, CopyInfo> Copies;
141 DenseMap<const uint32_t *, BitVector> RegMaskToPreservedRegUnits;
145 BitVector &getPreservedRegUnits(
const MachineOperand &RegMaskOp,
146 const TargetRegisterInfo &
TRI) {
147 const uint32_t *RegMask = RegMaskOp.
getRegMask();
148 auto [It,
Inserted] = RegMaskToPreservedRegUnits.try_emplace(RegMask);
151 BitVector &PreservedRegUnits = It->second;
153 PreservedRegUnits.
resize(
TRI.getNumRegUnits());
154 for (
unsigned SafeReg = 0,
E =
TRI.getNumRegs(); SafeReg <
E; ++SafeReg)
156 for (MCRegUnit SafeUnit :
TRI.regunits(SafeReg))
157 PreservedRegUnits.
set(
static_cast<unsigned>(SafeUnit));
159 return PreservedRegUnits;
165 const TargetRegisterInfo &
TRI) {
166 for (MCRegister
Reg : Regs) {
168 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
169 auto CI = Copies.find(Unit);
170 if (CI != Copies.end())
171 CI->second.Avail =
false;
177 void invalidateRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
178 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
188 SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;
189 auto InvalidateCopy = [&](MachineInstr *
MI) {
190 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
191 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
192 auto DstUnits =
TRI.regunits(Dst);
193 auto SrcUnits =
TRI.regunits(Src);
198 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
199 auto I = Copies.find(Unit);
200 if (
I != Copies.end()) {
201 if (MachineInstr *
MI =
I->second.MI)
203 if (MachineInstr *
MI =
I->second.LastSeenUseInCopy)
207 for (MCRegUnit Unit : RegUnitsToInvalidate)
212 void clobberRegUnit(MCRegUnit Unit,
const TargetRegisterInfo &
TRI,
213 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
214 auto I = Copies.find(Unit);
215 if (
I != Copies.end()) {
218 markRegsUnavailable(
I->second.DefRegs,
TRI);
221 if (MachineInstr *
MI =
I->second.MI) {
222 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
223 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
225 markRegsUnavailable(Dst,
TRI);
239 for (MCRegUnit SrcUnit :
TRI.regunits(Src)) {
240 auto SrcCopy = Copies.find(SrcUnit);
241 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {
245 for (
auto Itr = SrcCopy->second.DefRegs.begin();
246 Itr != SrcCopy->second.DefRegs.end(); Itr++) {
248 SrcCopy->second.DefRegs.erase(Itr);
254 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {
255 Copies.erase(SrcCopy);
269 void clobberRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
270 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
276 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
277 clobberRegUnit(Unit,
TRI,
TII, UseCopyInstr);
284 bool trackSrcUsers(MCRegister
Reg, MachineInstr &
MI,
285 const TargetRegisterInfo &
TRI,
const TargetInstrInfo &
TII,
287 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
288 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
292 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
293 MCRegister Src = getSrcMCReg(CopyOperands);
299 auto I = Copies.find(RU);
300 if (
I == Copies.end())
303 I->second.SrcUsers.insert(&
MI);
308 SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister
Reg,
309 const TargetRegisterInfo &
TRI) {
310 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
311 auto I = Copies.find(RU);
312 if (
I == Copies.end())
314 return I->second.SrcUsers;
318 void trackCopy(MachineInstr *
MI,
const TargetRegisterInfo &
TRI,
319 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
320 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
321 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
324 for (MCRegUnit Unit :
TRI.regunits(Dst))
325 Copies[
Unit] = {
MI,
nullptr, {}, {},
true};
329 for (MCRegUnit Unit :
TRI.regunits(Src)) {
332 Copy.DefRegs.push_back(Dst);
333 Copy.LastSeenUseInCopy =
MI;
337 bool hasAnyCopies() {
338 return !Copies.empty();
341 MachineInstr *findCopyForUnit(MCRegUnit RegUnit,
342 const TargetRegisterInfo &
TRI,
343 bool MustBeAvailable =
false) {
344 auto CI = Copies.find(RegUnit);
345 if (CI == Copies.end())
347 if (MustBeAvailable && !CI->second.Avail)
349 return CI->second.MI;
352 MachineInstr *findCopyDefViaUnit(MCRegUnit RegUnit,
353 const TargetRegisterInfo &
TRI) {
354 auto CI = Copies.find(RegUnit);
355 if (CI == Copies.end())
357 if (CI->second.DefRegs.size() != 1)
359 MCRegUnit RU = *
TRI.regunits(CI->second.DefRegs[0]).begin();
360 return findCopyForUnit(RU,
TRI,
true);
363 MachineInstr *findAvailBackwardCopy(MachineInstr &
I, MCRegister
Reg,
364 const TargetRegisterInfo &
TRI,
365 const TargetInstrInfo &
TII,
367 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
368 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
373 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
374 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
375 if (!
TRI.isSubRegisterEq(AvailSrc,
Reg))
378 for (
const MachineInstr &
MI :
380 for (
const MachineOperand &MO :
MI.operands())
383 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
389 MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister
Reg,
390 const TargetRegisterInfo &
TRI,
391 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
394 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
395 MachineInstr *AvailCopy =
396 findCopyForUnit(RU,
TRI,
true);
401 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
402 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
403 if (!
TRI.isSubRegisterEq(AvailDst,
Reg))
408 for (
const MachineInstr &
MI :
410 for (
const MachineOperand &MO :
MI.operands())
412 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
419 MachineInstr *findLastSeenDefInCopy(
const MachineInstr &Current,
421 const TargetRegisterInfo &
TRI,
422 const TargetInstrInfo &
TII,
424 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
425 auto CI = Copies.find(RU);
426 if (CI == Copies.end() || !CI->second.Avail)
429 MachineInstr *DefCopy = CI->second.MI;
430 DestSourcePair CopyOperands = *isCopyInstr(*DefCopy,
TII, UseCopyInstr);
431 MCRegister Dst = getDstMCReg(CopyOperands);
432 if (!
TRI.isSubRegisterEq(Dst,
Reg))
438 void clobberNonPreservedRegs(
const BitVector &PreservedRegUnits,
439 const TargetRegisterInfo &
TRI,
440 const TargetInstrInfo &
TII) {
442 for (
auto &[Unit,
_] : Copies)
443 if (!PreservedRegUnits.
test(
static_cast<unsigned>(Unit)))
446 for (MCRegUnit Unit : UnitsToClobber) {
451 auto RegUnitInfo = Copies.find(Unit);
452 if (RegUnitInfo == Copies.end())
455 for (MCRegister DstReg : RegUnitInfo->second.DefRegs) {
456 for (MCRegUnit DstUnit :
TRI.regunits(DstReg)) {
457 if (!PreservedRegUnits.
test(
static_cast<unsigned>(DstUnit))) {
458 if (
auto CI = Copies.find(DstUnit); CI != Copies.end()) {
459 CI->second.Avail =
false;
464 Copies.erase(RegUnitInfo);
469 MachineInstr *findLastSeenUseInCopy(MCRegister
Reg,
470 const TargetRegisterInfo &
TRI) {
471 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
472 auto CI = Copies.find(RU);
473 if (CI == Copies.end())
475 return CI->second.LastSeenUseInCopy;
483class MachineCopyPropagation {
484 const TargetRegisterInfo *TRI =
nullptr;
485 const TargetInstrInfo *TII =
nullptr;
486 const MachineRegisterInfo *MRI =
nullptr;
492 MachineCopyPropagation(
bool CopyInstr =
false)
495 bool run(MachineFunction &MF);
498 typedef enum { DebugUse =
false, RegularUse =
true } DebugType;
501 void readSuccessorLiveIns(
const MachineBasicBlock &
MBB);
502 void forwardCopyPropagateBlock(MachineBasicBlock &
MBB);
503 void backwardCopyPropagateBlock(MachineBasicBlock &
MBB);
504 void eliminateSpillageCopies(MachineBasicBlock &
MBB);
505 bool eraseIfRedundant(MachineInstr &Copy, MCRegister Dst, MCRegister Src);
506 void forwardUses(MachineInstr &
MI);
507 void propagateDefs(MachineInstr &
MI);
508 bool isForwardableRegClassCopy(
const MachineInstr &Copy,
509 const MachineInstr &UseI,
unsigned UseIdx);
510 bool isBackwardPropagatableRegClassCopy(
const MachineInstr &Copy,
511 const MachineInstr &UseI,
513 bool isBackwardPropagatableCopy(
const MachineInstr &Copy,
514 const DestSourcePair &CopyOperands);
517 bool isNeverRedundant(MCRegister CopyOperand) {
521 return MRI->isReserved(CopyOperand);
525 bool isNeverRedundant(
const MachineInstr &Copy) {
529 bool hasImplicitOverlap(
const MachineInstr &
MI,
const MachineOperand &Use);
530 bool hasOverlappingMultipleDef(
const MachineInstr &
MI,
531 const MachineOperand &MODef, MCRegister Def);
532 bool canUpdateSrcUsers(
const MachineInstr &Copy,
533 const MachineOperand &CopySrc);
536 SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
539 DenseMap<MachineInstr *, SmallPtrSet<MachineInstr *, 2>> CopyDbgUsers;
543 bool Changed =
false;
552 MachineCopyPropagationLegacy(
bool UseCopyInstr =
false)
553 : MachineFunctionPass(ID), UseCopyInstr(UseCopyInstr) {}
555 void getAnalysisUsage(AnalysisUsage &AU)
const override {
561 bool runOnMachineFunction(MachineFunction &MF)
override;
563 MachineFunctionProperties getRequiredProperties()
const override {
564 return MachineFunctionProperties().setNoVRegs();
570char MachineCopyPropagationLegacy::ID = 0;
575 "Machine Copy Propagation Pass",
false,
false)
582 for (MCRegUnit Unit :
TRI->regunits(
Reg)) {
583 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
584 if (DT == RegularUse) {
585 LLVM_DEBUG(dbgs() <<
"MCP: Copy is used - not dead: "; Copy->dump());
586 MaybeDeadCopies.remove(Copy);
588 CopyDbgUsers[Copy].insert(&Reader);
594void MachineCopyPropagation::readSuccessorLiveIns(
596 if (MaybeDeadCopies.empty())
601 for (
const auto &LI : Succ->liveins()) {
602 for (MCRegUnitMaskIterator
U(LI.PhysReg,
TRI);
U.isValid(); ++U) {
604 if ((Mask & LI.LaneMask).any()) {
605 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *
TRI))
606 MaybeDeadCopies.remove(Copy);
624 auto [PreviousDst, PreviousSrc] = getDstSrcMCRegs(CopyOperands);
625 if (Src == PreviousSrc && Dst == PreviousDst)
627 if (!
TRI->isSubRegister(PreviousSrc, Src))
629 unsigned SubIdx =
TRI->getSubRegIndex(PreviousSrc, Src);
630 return SubIdx ==
TRI->getSubRegIndex(PreviousDst, Dst);
636bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
637 MCRegister Dst, MCRegister Src) {
638 if (isNeverRedundant(Copy) || isNeverRedundant(Src) || isNeverRedundant(Dst))
642 MachineInstr *PrevCopy =
643 Tracker.findAvailCopy(Copy, Dst, *
TRI, *
TII, UseCopyInstr);
647 DestSourcePair PrevCopyOperands = *isCopyInstr(*PrevCopy, *
TII, UseCopyInstr);
658 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
660 MCRegister CopyDst = getDstMCReg(CopyOperands);
661 assert(CopyDst == Src || CopyDst == Dst);
662 for (MachineInstr &
MI :
664 MI.clearRegisterKills(CopyDst,
TRI);
672 Copy.eraseFromParent();
678bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
679 const MachineInstr &Copy,
const MachineInstr &UseI,
unsigned UseIdx) {
680 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
681 MCRegister Dst = getDstMCReg(CopyOperands);
685 return URC->contains(Dst);
692bool MachineCopyPropagation::isBackwardPropagatableCopy(
693 const MachineInstr &Copy,
const DestSourcePair &CopyOperands) {
694 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
699 if (isNeverRedundant(Copy) || isNeverRedundant(Dst) || isNeverRedundant(Src))
708bool MachineCopyPropagation::isForwardableRegClassCopy(
const MachineInstr &Copy,
709 const MachineInstr &UseI,
711 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
712 MCRegister CopySrc = getSrcMCReg(CopyOperands);
718 return URC->contains(CopySrc);
720 std::optional<DestSourcePair> UseICopyOperands =
721 isCopyInstr(UseI, *
TII, UseCopyInstr);
722 if (!UseICopyOperands)
745 MCRegister UseDst = getDstMCReg(*UseICopyOperands);
747 bool IsCrossClass =
false;
749 if (RC.contains(CopySrc) && RC.contains(UseDst)) {
751 if (
TRI->getCrossCopyRegClass(&RC) != &RC) {
763 MCRegister CopyDst = getDstMCReg(CopyOperands);
765 if (RC.contains(CopySrc) && RC.contains(CopyDst) &&
766 TRI->getCrossCopyRegClass(&RC) != &RC)
780bool MachineCopyPropagation::hasImplicitOverlap(
const MachineInstr &
MI,
781 const MachineOperand &Use) {
782 for (
const MachineOperand &MIUse :
MI.uses())
783 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
784 MIUse.isUse() &&
TRI->regsOverlap(
Use.getReg(), MIUse.getReg()))
794bool MachineCopyPropagation::hasOverlappingMultipleDef(
795 const MachineInstr &
MI,
const MachineOperand &MODef, MCRegister Def) {
796 for (
const MachineOperand &MIDef :
MI.all_defs()) {
797 if ((&MIDef != &MODef) && MIDef.isReg() &&
798 TRI->regsOverlap(Def, MIDef.getReg()))
807bool MachineCopyPropagation::canUpdateSrcUsers(
const MachineInstr &Copy,
808 const MachineOperand &CopySrc) {
809 assert(CopySrc.
isReg() &&
"Expected a register operand");
810 for (
auto *SrcUser : Tracker.getSrcUsers(CopySrc.
getReg(), *
TRI)) {
811 if (hasImplicitOverlap(*SrcUser, CopySrc))
814 for (MachineOperand &MO : SrcUser->uses()) {
815 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.
getReg())
817 if (MO.isTied() || !MO.isRenamable() ||
818 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
828void MachineCopyPropagation::forwardUses(MachineInstr &
MI) {
829 if (!Tracker.hasAnyCopies())
835 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx < OpEnd;
837 MachineOperand &MOUse =
MI.getOperand(
OpIdx);
857 *
TRI, *
TII, UseCopyInstr);
861 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
862 auto [CopyDst, CopySrc] = getDstSrcMCRegs(CopyOperands);
863 const MachineOperand &CopySrcOperand = *CopyOperands.
Source;
865 MCRegister ForwardedReg = CopySrc;
868 if (MOUse.
getReg() != CopyDst) {
869 unsigned SubRegIdx =
TRI->getSubRegIndex(CopyDst, MOUse.
getReg());
871 "MI source is not a sub-register of Copy destination");
872 ForwardedReg =
TRI->getSubReg(CopySrc, SubRegIdx);
873 if (!ForwardedReg ||
TRI->isArtificial(ForwardedReg)) {
874 LLVM_DEBUG(
dbgs() <<
"MCP: Copy source does not have sub-register "
875 <<
TRI->getSubRegIndexName(SubRegIdx) <<
'\n');
884 if (!isForwardableRegClassCopy(*Copy,
MI,
OpIdx))
887 if (hasImplicitOverlap(
MI, MOUse))
893 if (isCopyInstr(
MI, *
TII, UseCopyInstr) &&
894 MI.modifiesRegister(CopySrc,
TRI) &&
895 !
MI.definesRegister(CopySrc,
nullptr)) {
901 LLVM_DEBUG(
dbgs() <<
"MCP: Skipping forwarding due to debug counter:\n "
908 <<
"\n in " <<
MI <<
" from " << *Copy);
910 MOUse.
setReg(ForwardedReg);
919 for (MachineInstr &KMI :
921 KMI.clearRegisterKills(CopySrc,
TRI);
928void MachineCopyPropagation::forwardCopyPropagateBlock(MachineBasicBlock &
MBB) {
934 std::optional<DestSourcePair> CopyOperands =
935 isCopyInstr(
MI, *
TII, UseCopyInstr);
937 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
938 if (!
TRI->regsOverlap(Dst, Src)) {
954 if (eraseIfRedundant(
MI, Dst, Src) || eraseIfRedundant(
MI, Src, Dst))
960 for (
const MachineOperand &MO :
MI.operands())
961 if (MO.isReg() && MO.isEarlyClobber()) {
968 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
975 if (
TII->simplifyInstruction(
MI)) {
980 CopyOperands = isCopyInstr(
MI, *
TII, UseCopyInstr);
982 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
983 if (!
TRI->regsOverlap(Dst, Src)) {
986 if (!isNeverRedundant(
MI) && !isNeverRedundant(Dst))
987 MaybeDeadCopies.insert(&
MI);
992 const MachineOperand *RegMask =
nullptr;
993 for (
const MachineOperand &MO :
MI.operands()) {
1003 "MachineCopyPropagation should be run after register allocation!");
1005 if (MO.isDef() && !MO.isEarlyClobber()) {
1011 }
else if (MO.readsReg()) {
1020 BitVector &PreservedRegUnits =
1021 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
1024 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
1025 MaybeDeadCopies.begin();
1026 DI != MaybeDeadCopies.end();) {
1027 MachineInstr *MaybeDead = *DI;
1028 std::optional<DestSourcePair> CopyOperands =
1029 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1030 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
1031 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(
Reg));
1040 bool MIRefedinCopyInfo =
false;
1041 for (MCRegUnit RegUnit :
TRI->regunits(
Reg)) {
1042 if (!PreservedRegUnits.
test(
static_cast<unsigned>(RegUnit)))
1043 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1045 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1046 MIRefedinCopyInfo =
true;
1053 DI = MaybeDeadCopies.erase(DI);
1056 if (MIRefedinCopyInfo)
1059 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1069 for (MCRegister
Reg : Defs)
1070 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1073 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1074 if (!
TRI->regsOverlap(Dst, Src)) {
1075 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1085 readSuccessorLiveIns(
MBB);
1091 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1092 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1095 DestSourcePair CopyOperands =
1096 *isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1098 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1099 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(Dst));
1102 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1113 MaybeDeadCopies.clear();
1114 CopyDbgUsers.clear();
1118void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1119 if (!Tracker.hasAnyCopies())
1122 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1124 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1140 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1145 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1146 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1148 if (MODef.
getReg() != Src)
1151 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1154 if (hasImplicitOverlap(
MI, MODef))
1157 if (hasOverlappingMultipleDef(
MI, MODef, Dst))
1160 if (!canUpdateSrcUsers(*Copy, *CopyOperands.
Source))
1165 <<
MI <<
" from " << *Copy);
1170 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1171 for (MachineOperand &MO : SrcUser->uses()) {
1172 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1180 MaybeDeadCopies.insert(Copy);
1182 ++NumCopyBackwardPropagated;
1186void MachineCopyPropagation::backwardCopyPropagateBlock(
1187 MachineBasicBlock &
MBB) {
1193 std::optional<DestSourcePair> CopyOperands =
1194 isCopyInstr(
MI, *
TII, UseCopyInstr);
1195 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1196 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1198 if (!
TRI->regsOverlap(Dst, Src)) {
1201 if (isBackwardPropagatableCopy(
MI, *CopyOperands)) {
1202 Tracker.invalidateRegister(Src, *
TRI, *
TII, UseCopyInstr);
1203 Tracker.invalidateRegister(Dst, *
TRI, *
TII, UseCopyInstr);
1204 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1211 for (
const MachineOperand &MO :
MI.operands())
1212 if (MO.isReg() && MO.isEarlyClobber()) {
1216 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1220 for (
const MachineOperand &MO :
MI.operands()) {
1228 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1231 if (MO.readsReg()) {
1236 for (MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1237 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1238 CopyDbgUsers[
Copy].insert(&
MI);
1241 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1244 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1251 for (
auto *Copy : MaybeDeadCopies) {
1252 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1253 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1254 const auto &DbgUsers = CopyDbgUsers[
Copy];
1259 Copy->eraseFromParent();
1263 MaybeDeadCopies.clear();
1264 CopyDbgUsers.clear();
1272 auto &SC = SpillChain[Leader];
1273 auto &RC = ReloadChain[Leader];
1274 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1318void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &
MBB) {
1323 unsigned CopyCount = 0;
1324 for (
const MachineInstr &
MI :
MBB) {
1325 if (isCopyInstr(
MI, *
TII, UseCopyInstr) && ++CopyCount > 6)
1333 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1338 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1341 DenseSet<const MachineInstr *> CopySourceInvalid;
1343 auto TryFoldSpillageCopies =
1344 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1345 const SmallVectorImpl<MachineInstr *> &RC) {
1346 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1361 for (
const MachineInstr *Spill :
drop_begin(SC))
1362 if (CopySourceInvalid.
count(Spill))
1365 for (
const MachineInstr *Reload :
drop_end(RC))
1366 if (CopySourceInvalid.
count(Reload))
1370 return TRI->getCommonMinimalPhysRegClass(Dst, Src);
1373 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1374 const MachineOperand *
New) {
1375 for (MachineOperand &MO :
MI->operands()) {
1377 MO.setReg(
New->getReg());
1381 DestSourcePair InnerMostSpillCopy =
1382 *isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1383 DestSourcePair OuterMostSpillCopy =
1384 *isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1385 DestSourcePair InnerMostReloadCopy =
1386 *isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1387 DestSourcePair OuterMostReloadCopy =
1388 *isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1389 if (!CheckCopyConstraint(getSrcMCReg(OuterMostSpillCopy),
1390 getSrcMCReg(InnerMostSpillCopy)) ||
1391 !CheckCopyConstraint(getDstMCReg(InnerMostReloadCopy),
1392 getDstMCReg(OuterMostReloadCopy)))
1395 SpillageChainsLength += SC.
size() + RC.size();
1396 NumSpillageChains += 1;
1398 OuterMostSpillCopy.
Source);
1399 UpdateReg(RC[0], InnerMostReloadCopy.
Source,
1402 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1403 SC[
I]->eraseFromParent();
1404 RC[
I]->eraseFromParent();
1409 auto GetFoldableCopy =
1410 [
this](
const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
1411 if (MaybeCopy.getNumImplicitOperands() > 0)
1412 return std::nullopt;
1413 std::optional<DestSourcePair> CopyOperands =
1414 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1416 return std::nullopt;
1417 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1418 if (Src && Dst && !
TRI->regsOverlap(Src, Dst) &&
1419 CopyOperands->Source->isRenamable() &&
1420 CopyOperands->Destination->isRenamable())
1421 return CopyOperands;
1423 return std::nullopt;
1426 auto IsSpillReloadPair = [&](
const MachineInstr &
Spill,
1427 const MachineInstr &Reload) {
1428 std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
1429 if (!FoldableSpillCopy)
1431 std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
1432 if (!FoldableReloadCopy)
1434 return FoldableSpillCopy->Source->getReg() ==
1435 FoldableReloadCopy->Destination->getReg() &&
1436 FoldableSpillCopy->Destination->getReg() ==
1437 FoldableReloadCopy->Source->getReg();
1440 auto IsChainedCopy = [&](
const MachineInstr &Prev,
1441 const MachineInstr &Current) {
1442 std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
1443 if (!FoldablePrevCopy)
1445 std::optional<DestSourcePair> FoldableCurrentCopy =
1446 GetFoldableCopy(Current);
1447 if (!FoldableCurrentCopy)
1449 return FoldablePrevCopy->Source->getReg() ==
1450 FoldableCurrentCopy->Destination->getReg();
1454 std::optional<DestSourcePair> CopyOperands =
1455 isCopyInstr(
MI, *
TII, UseCopyInstr);
1458 SmallSet<Register, 8> RegsToClobber;
1459 if (!CopyOperands) {
1460 for (
const MachineOperand &MO :
MI.operands()) {
1461 if (MO.isRegMask()) {
1462 BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *
TRI);
1463 Tracker.clobberNonPreservedRegs(PreservedRegUnits, *
TRI, *
TII);
1471 MachineInstr *LastUseCopy =
1478 CopySourceInvalid.
insert(LastUseCopy);
1492 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1499 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1501 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1503 MachineInstr *MaybeSpill =
1504 Tracker.findAvailCopy(
MI, Src, *
TRI, *
TII, UseCopyInstr);
1505 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1506 if (!MaybeSpillIsChained && MaybeSpill &&
1507 IsSpillReloadPair(*MaybeSpill,
MI)) {
1542 MachineInstr *MaybePrevReload = Tracker.findLastSeenUseInCopy(Dst, *
TRI);
1543 auto Leader = ChainLeader.
find(MaybePrevReload);
1544 MachineInstr *
L =
nullptr;
1545 if (Leader == ChainLeader.
end() ||
1546 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1549 "SpillChain should not have contained newly found chain");
1551 assert(MaybePrevReload &&
1552 "Found a valid leader through nullptr should not happend");
1555 "Existing chain's length should be larger than zero");
1558 "Newly found paired spill-reload should not belong to any chain "
1560 ChainLeader.
insert({MaybeSpill,
L});
1562 SpillChain[
L].push_back(MaybeSpill);
1563 ReloadChain[
L].push_back(&
MI);
1566 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1583 Tracker.clobberRegister(Src, *
TRI, *
TII, UseCopyInstr);
1587 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1590 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1591 auto &SC =
I->second;
1593 "Reload chain of the same leader should exist");
1594 auto &RC = ReloadChain[
I->first];
1595 TryFoldSpillageCopies(SC, RC);
1598 MaybeDeadCopies.clear();
1599 CopyDbgUsers.clear();
1603bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1607 return MachineCopyPropagation(UseCopyInstr).run(MF);
1614 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1622 bool IsSpillageCopyElimEnabled =
false;
1625 IsSpillageCopyElimEnabled =
1629 IsSpillageCopyElimEnabled =
true;
1632 IsSpillageCopyElimEnabled =
false;
1643 if (IsSpillageCopyElimEnabled)
1644 eliminateSpillageCopies(
MBB);
1645 backwardCopyPropagateBlock(
MBB);
1646 forwardCopyPropagateBlock(
MBB);
1652MachineFunctionPass *
1654 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)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
bool test(unsigned Idx) const
Returns true if bit Idx is set.
void resize(unsigned N, bool t=false)
Grow or shrink the bitvector.
BitVector & set()
Set all bits in 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.
LLVM_ABI 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 void updateDbgUsersToReg(MCRegister OldReg, MCRegister NewReg, ArrayRef< MachineInstr * > Users) const
updateDbgUsersToReg - Update a collection of debug instructions to refer to the designated register.
LLVM_ABI bool isConstantPhysReg(MCRegister PhysReg) const
Returns true if PhysReg is unallocatable and constant throughout the function.
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)
DXILDebugInfoMap run(Module &M)
LLVM_ABI 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.
MCRegisterClass TargetRegisterClass
const MachineOperand * Source
const MachineOperand * Destination