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 {
560 bool runOnMachineFunction(MachineFunction &MF)
override;
562 MachineFunctionProperties getRequiredProperties()
const override {
563 return MachineFunctionProperties().setNoVRegs();
569char MachineCopyPropagationLegacy::ID = 0;
574 "Machine Copy Propagation Pass",
false,
false)
581 for (MCRegUnit Unit :
TRI->regunits(
Reg)) {
582 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
583 if (DT == RegularUse) {
584 LLVM_DEBUG(dbgs() <<
"MCP: Copy is used - not dead: "; Copy->dump());
585 MaybeDeadCopies.remove(Copy);
587 CopyDbgUsers[Copy].insert(&Reader);
593void MachineCopyPropagation::readSuccessorLiveIns(
595 if (MaybeDeadCopies.empty())
600 for (
const auto &LI : Succ->liveins()) {
601 for (MCRegUnitMaskIterator
U(LI.PhysReg,
TRI);
U.isValid(); ++U) {
603 if ((Mask & LI.LaneMask).any()) {
604 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *
TRI))
605 MaybeDeadCopies.remove(Copy);
623 auto [PreviousDst, PreviousSrc] = getDstSrcMCRegs(CopyOperands);
624 if (Src == PreviousSrc && Dst == PreviousDst)
626 if (!
TRI->isSubRegister(PreviousSrc, Src))
628 unsigned SubIdx =
TRI->getSubRegIndex(PreviousSrc, Src);
629 return SubIdx ==
TRI->getSubRegIndex(PreviousDst, Dst);
635bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
636 MCRegister Dst, MCRegister Src) {
637 if (isNeverRedundant(Copy) || isNeverRedundant(Src) || isNeverRedundant(Dst))
641 MachineInstr *PrevCopy =
642 Tracker.findAvailCopy(Copy, Dst, *
TRI, *
TII, UseCopyInstr);
646 DestSourcePair PrevCopyOperands = *isCopyInstr(*PrevCopy, *
TII, UseCopyInstr);
657 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
659 MCRegister CopyDst = getDstMCReg(CopyOperands);
660 assert(CopyDst == Src || CopyDst == Dst);
661 for (MachineInstr &
MI :
663 MI.clearRegisterKills(CopyDst,
TRI);
671 Copy.eraseFromParent();
677bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
678 const MachineInstr &Copy,
const MachineInstr &UseI,
unsigned UseIdx) {
679 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
680 MCRegister Dst = getDstMCReg(CopyOperands);
684 return URC->contains(Dst);
691bool MachineCopyPropagation::isBackwardPropagatableCopy(
692 const MachineInstr &Copy,
const DestSourcePair &CopyOperands) {
693 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
698 if (isNeverRedundant(Copy) || isNeverRedundant(Dst) || isNeverRedundant(Src))
707bool MachineCopyPropagation::isForwardableRegClassCopy(
const MachineInstr &Copy,
708 const MachineInstr &UseI,
710 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
711 MCRegister CopySrc = getSrcMCReg(CopyOperands);
717 return URC->contains(CopySrc);
719 std::optional<DestSourcePair> UseICopyOperands =
720 isCopyInstr(UseI, *
TII, UseCopyInstr);
721 if (!UseICopyOperands)
744 MCRegister UseDst = getDstMCReg(*UseICopyOperands);
746 bool IsCrossClass =
false;
748 if (RC.contains(CopySrc) && RC.contains(UseDst)) {
750 if (
TRI->getCrossCopyRegClass(&RC) != &RC) {
762 MCRegister CopyDst = getDstMCReg(CopyOperands);
764 if (RC.contains(CopySrc) && RC.contains(CopyDst) &&
765 TRI->getCrossCopyRegClass(&RC) != &RC)
779bool MachineCopyPropagation::hasImplicitOverlap(
const MachineInstr &
MI,
780 const MachineOperand &Use) {
781 for (
const MachineOperand &MIUse :
MI.uses())
782 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
783 MIUse.isUse() &&
TRI->regsOverlap(
Use.getReg(), MIUse.getReg()))
793bool MachineCopyPropagation::hasOverlappingMultipleDef(
794 const MachineInstr &
MI,
const MachineOperand &MODef, MCRegister Def) {
795 for (
const MachineOperand &MIDef :
MI.all_defs()) {
796 if ((&MIDef != &MODef) && MIDef.isReg() &&
797 TRI->regsOverlap(Def, MIDef.getReg()))
806bool MachineCopyPropagation::canUpdateSrcUsers(
const MachineInstr &Copy,
807 const MachineOperand &CopySrc) {
808 assert(CopySrc.
isReg() &&
"Expected a register operand");
809 for (
auto *SrcUser : Tracker.getSrcUsers(CopySrc.
getReg(), *
TRI)) {
810 if (hasImplicitOverlap(*SrcUser, CopySrc))
813 for (MachineOperand &MO : SrcUser->uses()) {
814 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.
getReg())
816 if (MO.isTied() || !MO.isRenamable() ||
817 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
827void MachineCopyPropagation::forwardUses(MachineInstr &
MI) {
828 if (!Tracker.hasAnyCopies())
834 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx < OpEnd;
836 MachineOperand &MOUse =
MI.getOperand(
OpIdx);
856 *
TRI, *
TII, UseCopyInstr);
860 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
861 auto [CopyDst, CopySrc] = getDstSrcMCRegs(CopyOperands);
862 const MachineOperand &CopySrcOperand = *CopyOperands.
Source;
864 MCRegister ForwardedReg = CopySrc;
867 if (MOUse.
getReg() != CopyDst) {
868 unsigned SubRegIdx =
TRI->getSubRegIndex(CopyDst, MOUse.
getReg());
870 "MI source is not a sub-register of Copy destination");
871 ForwardedReg =
TRI->getSubReg(CopySrc, SubRegIdx);
872 if (!ForwardedReg ||
TRI->isArtificial(ForwardedReg)) {
873 LLVM_DEBUG(
dbgs() <<
"MCP: Copy source does not have sub-register "
874 <<
TRI->getSubRegIndexName(SubRegIdx) <<
'\n');
883 if (!isForwardableRegClassCopy(*Copy,
MI,
OpIdx))
886 if (hasImplicitOverlap(
MI, MOUse))
892 if (isCopyInstr(
MI, *
TII, UseCopyInstr) &&
893 MI.modifiesRegister(CopySrc,
TRI) &&
894 !
MI.definesRegister(CopySrc,
nullptr)) {
900 LLVM_DEBUG(
dbgs() <<
"MCP: Skipping forwarding due to debug counter:\n "
907 <<
"\n in " <<
MI <<
" from " << *Copy);
909 MOUse.
setReg(ForwardedReg);
918 for (MachineInstr &KMI :
920 KMI.clearRegisterKills(CopySrc,
TRI);
927void MachineCopyPropagation::forwardCopyPropagateBlock(MachineBasicBlock &
MBB) {
933 std::optional<DestSourcePair> CopyOperands =
934 isCopyInstr(
MI, *
TII, UseCopyInstr);
936 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
937 if (!
TRI->regsOverlap(Dst, Src)) {
953 if (eraseIfRedundant(
MI, Dst, Src) || eraseIfRedundant(
MI, Src, Dst))
959 for (
const MachineOperand &MO :
MI.operands())
960 if (MO.isReg() && MO.isEarlyClobber()) {
967 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
974 if (
TII->simplifyInstruction(
MI)) {
979 CopyOperands = isCopyInstr(
MI, *
TII, UseCopyInstr);
981 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
982 if (!
TRI->regsOverlap(Dst, Src)) {
985 if (!isNeverRedundant(
MI) && !isNeverRedundant(Dst))
986 MaybeDeadCopies.insert(&
MI);
991 const MachineOperand *RegMask =
nullptr;
992 for (
const MachineOperand &MO :
MI.operands()) {
1002 "MachineCopyPropagation should be run after register allocation!");
1004 if (MO.isDef() && !MO.isEarlyClobber()) {
1010 }
else if (MO.readsReg()) {
1019 BitVector &PreservedRegUnits =
1020 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
1023 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
1024 MaybeDeadCopies.begin();
1025 DI != MaybeDeadCopies.end();) {
1026 MachineInstr *MaybeDead = *DI;
1027 std::optional<DestSourcePair> CopyOperands =
1028 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1029 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
1030 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(
Reg));
1039 bool MIRefedinCopyInfo =
false;
1040 for (MCRegUnit RegUnit :
TRI->regunits(
Reg)) {
1041 if (!PreservedRegUnits.
test(
static_cast<unsigned>(RegUnit)))
1042 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1044 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1045 MIRefedinCopyInfo =
true;
1052 DI = MaybeDeadCopies.erase(DI);
1055 if (MIRefedinCopyInfo)
1058 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1068 for (MCRegister
Reg : Defs)
1069 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1072 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1073 if (!
TRI->regsOverlap(Dst, Src)) {
1074 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1084 readSuccessorLiveIns(
MBB);
1090 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1091 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1094 DestSourcePair CopyOperands =
1095 *isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1097 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1098 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(Dst));
1101 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1112 MaybeDeadCopies.clear();
1113 CopyDbgUsers.clear();
1117void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1118 if (!Tracker.hasAnyCopies())
1121 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1123 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1139 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1144 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1145 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1147 if (MODef.
getReg() != Src)
1150 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1153 if (hasImplicitOverlap(
MI, MODef))
1156 if (hasOverlappingMultipleDef(
MI, MODef, Dst))
1159 if (!canUpdateSrcUsers(*Copy, *CopyOperands.
Source))
1164 <<
MI <<
" from " << *Copy);
1169 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1170 for (MachineOperand &MO : SrcUser->uses()) {
1171 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1179 MaybeDeadCopies.insert(Copy);
1181 ++NumCopyBackwardPropagated;
1185void MachineCopyPropagation::backwardCopyPropagateBlock(
1186 MachineBasicBlock &
MBB) {
1192 std::optional<DestSourcePair> CopyOperands =
1193 isCopyInstr(
MI, *
TII, UseCopyInstr);
1194 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1195 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1197 if (!
TRI->regsOverlap(Dst, Src)) {
1200 if (isBackwardPropagatableCopy(
MI, *CopyOperands)) {
1201 Tracker.invalidateRegister(Src, *
TRI, *
TII, UseCopyInstr);
1202 Tracker.invalidateRegister(Dst, *
TRI, *
TII, UseCopyInstr);
1203 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1210 for (
const MachineOperand &MO :
MI.operands())
1211 if (MO.isReg() && MO.isEarlyClobber()) {
1215 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1219 for (
const MachineOperand &MO :
MI.operands()) {
1227 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1230 if (MO.readsReg()) {
1235 for (MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1236 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1237 CopyDbgUsers[
Copy].insert(&
MI);
1240 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1243 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1250 for (
auto *Copy : MaybeDeadCopies) {
1251 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1252 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1253 const auto &DbgUsers = CopyDbgUsers[
Copy];
1258 Copy->eraseFromParent();
1262 MaybeDeadCopies.clear();
1263 CopyDbgUsers.clear();
1271 auto &SC = SpillChain[Leader];
1272 auto &RC = ReloadChain[Leader];
1273 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1317void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &
MBB) {
1322 unsigned CopyCount = 0;
1323 for (
const MachineInstr &
MI :
MBB) {
1324 if (isCopyInstr(
MI, *
TII, UseCopyInstr) && ++CopyCount > 6)
1332 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1337 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1340 DenseSet<const MachineInstr *> CopySourceInvalid;
1342 auto TryFoldSpillageCopies =
1343 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1344 const SmallVectorImpl<MachineInstr *> &RC) {
1345 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1360 for (
const MachineInstr *Spill :
drop_begin(SC))
1361 if (CopySourceInvalid.
count(Spill))
1364 for (
const MachineInstr *Reload :
drop_end(RC))
1365 if (CopySourceInvalid.
count(Reload))
1369 return TRI->getCommonMinimalPhysRegClass(Dst, Src);
1372 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1373 const MachineOperand *
New) {
1374 for (MachineOperand &MO :
MI->operands()) {
1376 MO.setReg(
New->getReg());
1380 DestSourcePair InnerMostSpillCopy =
1381 *isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1382 DestSourcePair OuterMostSpillCopy =
1383 *isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1384 DestSourcePair InnerMostReloadCopy =
1385 *isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1386 DestSourcePair OuterMostReloadCopy =
1387 *isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1388 if (!CheckCopyConstraint(getSrcMCReg(OuterMostSpillCopy),
1389 getSrcMCReg(InnerMostSpillCopy)) ||
1390 !CheckCopyConstraint(getDstMCReg(InnerMostReloadCopy),
1391 getDstMCReg(OuterMostReloadCopy)))
1394 SpillageChainsLength += SC.
size() + RC.size();
1395 NumSpillageChains += 1;
1397 OuterMostSpillCopy.
Source);
1398 UpdateReg(RC[0], InnerMostReloadCopy.
Source,
1401 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1402 SC[
I]->eraseFromParent();
1403 RC[
I]->eraseFromParent();
1408 auto GetFoldableCopy =
1409 [
this](
const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
1410 if (MaybeCopy.getNumImplicitOperands() > 0)
1411 return std::nullopt;
1412 std::optional<DestSourcePair> CopyOperands =
1413 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1415 return std::nullopt;
1416 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1417 if (Src && Dst && !
TRI->regsOverlap(Src, Dst) &&
1418 CopyOperands->Source->isRenamable() &&
1419 CopyOperands->Destination->isRenamable())
1420 return CopyOperands;
1422 return std::nullopt;
1425 auto IsSpillReloadPair = [&](
const MachineInstr &
Spill,
1426 const MachineInstr &Reload) {
1427 std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
1428 if (!FoldableSpillCopy)
1430 std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
1431 if (!FoldableReloadCopy)
1433 return FoldableSpillCopy->Source->getReg() ==
1434 FoldableReloadCopy->Destination->getReg() &&
1435 FoldableSpillCopy->Destination->getReg() ==
1436 FoldableReloadCopy->Source->getReg();
1439 auto IsChainedCopy = [&](
const MachineInstr &Prev,
1440 const MachineInstr &Current) {
1441 std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
1442 if (!FoldablePrevCopy)
1444 std::optional<DestSourcePair> FoldableCurrentCopy =
1445 GetFoldableCopy(Current);
1446 if (!FoldableCurrentCopy)
1448 return FoldablePrevCopy->Source->getReg() ==
1449 FoldableCurrentCopy->Destination->getReg();
1453 std::optional<DestSourcePair> CopyOperands =
1454 isCopyInstr(
MI, *
TII, UseCopyInstr);
1457 SmallSet<Register, 8> RegsToClobber;
1458 if (!CopyOperands) {
1459 for (
const MachineOperand &MO :
MI.operands()) {
1460 if (MO.isRegMask()) {
1461 BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *
TRI);
1462 Tracker.clobberNonPreservedRegs(PreservedRegUnits, *
TRI, *
TII);
1470 MachineInstr *LastUseCopy =
1477 CopySourceInvalid.
insert(LastUseCopy);
1491 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1498 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1500 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1502 MachineInstr *MaybeSpill =
1503 Tracker.findAvailCopy(
MI, Src, *
TRI, *
TII, UseCopyInstr);
1504 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1505 if (!MaybeSpillIsChained && MaybeSpill &&
1506 IsSpillReloadPair(*MaybeSpill,
MI)) {
1541 MachineInstr *MaybePrevReload = Tracker.findLastSeenUseInCopy(Dst, *
TRI);
1542 auto Leader = ChainLeader.
find(MaybePrevReload);
1543 MachineInstr *
L =
nullptr;
1544 if (Leader == ChainLeader.
end() ||
1545 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1548 "SpillChain should not have contained newly found chain");
1550 assert(MaybePrevReload &&
1551 "Found a valid leader through nullptr should not happend");
1554 "Existing chain's length should be larger than zero");
1557 "Newly found paired spill-reload should not belong to any chain "
1559 ChainLeader.
insert({MaybeSpill,
L});
1561 SpillChain[
L].push_back(MaybeSpill);
1562 ReloadChain[
L].push_back(&
MI);
1565 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1582 Tracker.clobberRegister(Src, *
TRI, *
TII, UseCopyInstr);
1586 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1589 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1590 auto &SC =
I->second;
1592 "Reload chain of the same leader should exist");
1593 auto &RC = ReloadChain[
I->first];
1594 TryFoldSpillageCopies(SC, RC);
1597 MaybeDeadCopies.clear();
1598 CopyDbgUsers.clear();
1602bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1606 return MachineCopyPropagation(UseCopyInstr).run(MF);
1613 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1621 bool IsSpillageCopyElimEnabled =
false;
1624 IsSpillageCopyElimEnabled =
1628 IsSpillageCopyElimEnabled =
true;
1631 IsSpillageCopyElimEnabled =
false;
1642 if (IsSpillageCopyElimEnabled)
1643 eliminateSpillageCopies(
MBB);
1644 backwardCopyPropagateBlock(
MBB);
1645 forwardCopyPropagateBlock(
MBB);
1651MachineFunctionPass *
1653 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
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