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) {
187 SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;
188 auto InvalidateCopy = [&](MachineInstr *
MI) {
189 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
190 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
191 auto DstUnits =
TRI.regunits(Dst);
192 auto SrcUnits =
TRI.regunits(Src);
197 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
198 auto I = Copies.find(Unit);
199 if (
I != Copies.end()) {
200 if (MachineInstr *
MI =
I->second.MI)
202 if (MachineInstr *
MI =
I->second.LastSeenUseInCopy)
206 for (MCRegUnit Unit : RegUnitsToInvalidate)
211 void clobberRegUnit(MCRegUnit Unit,
const TargetRegisterInfo &
TRI,
212 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
213 auto I = Copies.find(Unit);
214 if (
I != Copies.end()) {
217 markRegsUnavailable(
I->second.DefRegs,
TRI);
220 if (MachineInstr *
MI =
I->second.MI) {
221 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
222 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
224 markRegsUnavailable(Dst,
TRI);
238 for (MCRegUnit SrcUnit :
TRI.regunits(Src)) {
239 auto SrcCopy = Copies.find(SrcUnit);
240 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {
244 for (
auto Itr = SrcCopy->second.DefRegs.begin();
245 Itr != SrcCopy->second.DefRegs.end(); Itr++) {
247 SrcCopy->second.DefRegs.erase(Itr);
253 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {
254 Copies.erase(SrcCopy);
268 void clobberRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
269 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
275 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
276 clobberRegUnit(Unit,
TRI,
TII, UseCopyInstr);
283 bool trackSrcUsers(MCRegister
Reg, MachineInstr &
MI,
284 const TargetRegisterInfo &
TRI,
const TargetInstrInfo &
TII,
286 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
287 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
291 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
292 MCRegister Src = getSrcMCReg(CopyOperands);
298 auto I = Copies.find(RU);
299 if (
I == Copies.end())
302 I->second.SrcUsers.insert(&
MI);
307 SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister
Reg,
308 const TargetRegisterInfo &
TRI) {
309 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
310 auto I = Copies.find(RU);
311 if (
I == Copies.end())
313 return I->second.SrcUsers;
317 void trackCopy(MachineInstr *
MI,
const TargetRegisterInfo &
TRI,
318 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
319 DestSourcePair CopyOperands = *isCopyInstr(*
MI,
TII, UseCopyInstr);
320 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
323 for (MCRegUnit Unit :
TRI.regunits(Dst))
324 Copies[
Unit] = {
MI,
nullptr, {}, {},
true};
328 for (MCRegUnit Unit :
TRI.regunits(Src)) {
331 Copy.DefRegs.push_back(Dst);
332 Copy.LastSeenUseInCopy =
MI;
336 bool hasAnyCopies() {
337 return !Copies.empty();
340 MachineInstr *findCopyForUnit(MCRegUnit RegUnit,
341 const TargetRegisterInfo &
TRI,
342 bool MustBeAvailable =
false) {
343 auto CI = Copies.find(RegUnit);
344 if (CI == Copies.end())
346 if (MustBeAvailable && !CI->second.Avail)
348 return CI->second.MI;
351 MachineInstr *findCopyDefViaUnit(MCRegUnit RegUnit,
352 const TargetRegisterInfo &
TRI) {
353 auto CI = Copies.find(RegUnit);
354 if (CI == Copies.end())
356 if (CI->second.DefRegs.size() != 1)
358 MCRegUnit RU = *
TRI.regunits(CI->second.DefRegs[0]).begin();
359 return findCopyForUnit(RU,
TRI,
true);
362 MachineInstr *findAvailBackwardCopy(MachineInstr &
I, MCRegister
Reg,
363 const TargetRegisterInfo &
TRI,
364 const TargetInstrInfo &
TII,
366 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
367 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
372 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
373 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
374 if (!
TRI.isSubRegisterEq(AvailSrc,
Reg))
377 for (
const MachineInstr &
MI :
379 for (
const MachineOperand &MO :
MI.operands())
382 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
388 MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister
Reg,
389 const TargetRegisterInfo &
TRI,
390 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
393 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
394 MachineInstr *AvailCopy =
395 findCopyForUnit(RU,
TRI,
true);
400 DestSourcePair CopyOperands = *isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
401 auto [AvailDst, AvailSrc] = getDstSrcMCRegs(CopyOperands);
402 if (!
TRI.isSubRegisterEq(AvailDst,
Reg))
407 for (
const MachineInstr &
MI :
409 for (
const MachineOperand &MO :
MI.operands())
411 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDst))
418 MachineInstr *findLastSeenDefInCopy(
const MachineInstr &Current,
420 const TargetRegisterInfo &
TRI,
421 const TargetInstrInfo &
TII,
423 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
424 auto CI = Copies.find(RU);
425 if (CI == Copies.end() || !CI->second.Avail)
428 MachineInstr *DefCopy = CI->second.MI;
429 DestSourcePair CopyOperands = *isCopyInstr(*DefCopy,
TII, UseCopyInstr);
430 MCRegister Dst = getDstMCReg(CopyOperands);
431 if (!
TRI.isSubRegisterEq(Dst,
Reg))
437 void clobberNonPreservedRegs(
const BitVector &PreservedRegUnits,
438 const TargetRegisterInfo &
TRI,
439 const TargetInstrInfo &
TII) {
441 for (
auto &[Unit,
_] : Copies)
442 if (!PreservedRegUnits.
test(
static_cast<unsigned>(Unit)))
445 for (MCRegUnit Unit : UnitsToClobber) {
450 auto RegUnitInfo = Copies.find(Unit);
451 if (RegUnitInfo == Copies.end())
454 for (MCRegister DstReg : RegUnitInfo->second.DefRegs) {
455 for (MCRegUnit DstUnit :
TRI.regunits(DstReg)) {
456 if (!PreservedRegUnits.
test(
static_cast<unsigned>(DstUnit))) {
457 if (
auto CI = Copies.find(DstUnit); CI != Copies.end()) {
458 CI->second.Avail =
false;
463 Copies.erase(RegUnitInfo);
468 MachineInstr *findLastSeenUseInCopy(MCRegister
Reg,
469 const TargetRegisterInfo &
TRI) {
470 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
471 auto CI = Copies.find(RU);
472 if (CI == Copies.end())
474 return CI->second.LastSeenUseInCopy;
482class MachineCopyPropagation {
483 const TargetRegisterInfo *TRI =
nullptr;
484 const TargetInstrInfo *TII =
nullptr;
485 const MachineRegisterInfo *MRI =
nullptr;
491 MachineCopyPropagation(
bool CopyInstr =
false)
494 bool run(MachineFunction &MF);
497 typedef enum { DebugUse =
false, RegularUse =
true } DebugType;
500 void readSuccessorLiveIns(
const MachineBasicBlock &
MBB);
501 void forwardCopyPropagateBlock(MachineBasicBlock &
MBB);
502 void backwardCopyPropagateBlock(MachineBasicBlock &
MBB);
503 void eliminateSpillageCopies(MachineBasicBlock &
MBB);
504 bool eraseIfRedundant(MachineInstr &Copy, MCRegister Dst, MCRegister Src);
505 void forwardUses(MachineInstr &
MI);
506 void propagateDefs(MachineInstr &
MI);
507 bool isForwardableRegClassCopy(
const MachineInstr &Copy,
508 const MachineInstr &UseI,
unsigned UseIdx);
509 bool isBackwardPropagatableRegClassCopy(
const MachineInstr &Copy,
510 const MachineInstr &UseI,
512 bool isBackwardPropagatableCopy(
const MachineInstr &Copy,
513 const DestSourcePair &CopyOperands);
516 bool isNeverRedundant(MCRegister CopyOperand) {
520 return MRI->isReserved(CopyOperand);
524 bool isNeverRedundant(
const MachineInstr &Copy) {
528 bool hasImplicitOverlap(
const MachineInstr &
MI,
const MachineOperand &Use);
529 bool hasOverlappingMultipleDef(
const MachineInstr &
MI,
530 const MachineOperand &MODef, MCRegister Def);
531 bool canUpdateSrcUsers(
const MachineInstr &Copy,
532 const MachineOperand &CopySrc);
535 SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
538 DenseMap<MachineInstr *, SmallPtrSet<MachineInstr *, 2>> CopyDbgUsers;
542 bool Changed =
false;
551 MachineCopyPropagationLegacy(
bool UseCopyInstr =
false)
552 : MachineFunctionPass(ID), UseCopyInstr(UseCopyInstr) {}
554 void getAnalysisUsage(AnalysisUsage &AU)
const override {
559 bool runOnMachineFunction(MachineFunction &MF)
override;
561 MachineFunctionProperties getRequiredProperties()
const override {
562 return MachineFunctionProperties().setNoVRegs();
568char MachineCopyPropagationLegacy::ID = 0;
573 "Machine Copy Propagation Pass",
false,
false)
580 for (MCRegUnit Unit :
TRI->regunits(
Reg)) {
581 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
582 if (DT == RegularUse) {
583 LLVM_DEBUG(dbgs() <<
"MCP: Copy is used - not dead: "; Copy->dump());
584 MaybeDeadCopies.remove(Copy);
586 CopyDbgUsers[Copy].insert(&Reader);
592void MachineCopyPropagation::readSuccessorLiveIns(
594 if (MaybeDeadCopies.empty())
599 for (
const auto &LI : Succ->liveins()) {
600 for (MCRegUnitMaskIterator
U(LI.PhysReg,
TRI);
U.isValid(); ++U) {
602 if ((Mask & LI.LaneMask).any()) {
603 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *
TRI))
604 MaybeDeadCopies.remove(Copy);
622 auto [PreviousDst, PreviousSrc] = getDstSrcMCRegs(CopyOperands);
623 if (Src == PreviousSrc && Dst == PreviousDst)
625 if (!
TRI->isSubRegister(PreviousSrc, Src))
627 unsigned SubIdx =
TRI->getSubRegIndex(PreviousSrc, Src);
628 return SubIdx ==
TRI->getSubRegIndex(PreviousDst, Dst);
634bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
635 MCRegister Dst, MCRegister Src) {
636 if (isNeverRedundant(Copy) || isNeverRedundant(Src) || isNeverRedundant(Dst))
640 MachineInstr *PrevCopy =
641 Tracker.findAvailCopy(Copy, Dst, *
TRI, *
TII, UseCopyInstr);
645 DestSourcePair PrevCopyOperands = *isCopyInstr(*PrevCopy, *
TII, UseCopyInstr);
656 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
658 MCRegister CopyDst = getDstMCReg(CopyOperands);
659 assert(CopyDst == Src || CopyDst == Dst);
660 for (MachineInstr &
MI :
662 MI.clearRegisterKills(CopyDst,
TRI);
670 Copy.eraseFromParent();
676bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
677 const MachineInstr &Copy,
const MachineInstr &UseI,
unsigned UseIdx) {
678 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
679 MCRegister Dst = getDstMCReg(CopyOperands);
681 if (
const TargetRegisterClass *URC =
683 return URC->contains(Dst);
690bool MachineCopyPropagation::isBackwardPropagatableCopy(
691 const MachineInstr &Copy,
const DestSourcePair &CopyOperands) {
692 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
697 if (isNeverRedundant(Copy) || isNeverRedundant(Dst) || isNeverRedundant(Src))
706bool MachineCopyPropagation::isForwardableRegClassCopy(
const MachineInstr &Copy,
707 const MachineInstr &UseI,
709 DestSourcePair CopyOperands = *isCopyInstr(Copy, *
TII, UseCopyInstr);
710 MCRegister CopySrc = getSrcMCReg(CopyOperands);
714 if (
const TargetRegisterClass *URC =
716 return URC->contains(CopySrc);
718 std::optional<DestSourcePair> UseICopyOperands =
719 isCopyInstr(UseI, *
TII, UseCopyInstr);
720 if (!UseICopyOperands)
743 MCRegister UseDst = getDstMCReg(*UseICopyOperands);
745 bool IsCrossClass =
false;
746 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
747 if (RC->contains(CopySrc) && RC->contains(UseDst)) {
749 if (
TRI->getCrossCopyRegClass(RC) != RC) {
761 MCRegister CopyDst = getDstMCReg(CopyOperands);
762 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
763 if (RC->contains(CopySrc) && RC->contains(CopyDst) &&
764 TRI->getCrossCopyRegClass(RC) != RC)
778bool MachineCopyPropagation::hasImplicitOverlap(
const MachineInstr &
MI,
779 const MachineOperand &Use) {
780 for (
const MachineOperand &MIUse :
MI.uses())
781 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
782 MIUse.isUse() &&
TRI->regsOverlap(
Use.getReg(), MIUse.getReg()))
792bool MachineCopyPropagation::hasOverlappingMultipleDef(
793 const MachineInstr &
MI,
const MachineOperand &MODef, MCRegister Def) {
794 for (
const MachineOperand &MIDef :
MI.all_defs()) {
795 if ((&MIDef != &MODef) && MIDef.isReg() &&
796 TRI->regsOverlap(Def, MIDef.getReg()))
805bool MachineCopyPropagation::canUpdateSrcUsers(
const MachineInstr &Copy,
806 const MachineOperand &CopySrc) {
807 assert(CopySrc.
isReg() &&
"Expected a register operand");
808 for (
auto *SrcUser : Tracker.getSrcUsers(CopySrc.
getReg(), *
TRI)) {
809 if (hasImplicitOverlap(*SrcUser, CopySrc))
812 for (MachineOperand &MO : SrcUser->uses()) {
813 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.
getReg())
815 if (MO.isTied() || !MO.isRenamable() ||
816 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
826void MachineCopyPropagation::forwardUses(MachineInstr &
MI) {
827 if (!Tracker.hasAnyCopies())
833 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx < OpEnd;
835 MachineOperand &MOUse =
MI.getOperand(
OpIdx);
855 *
TRI, *
TII, UseCopyInstr);
859 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
860 auto [CopyDst, CopySrc] = getDstSrcMCRegs(CopyOperands);
861 const MachineOperand &CopySrcOperand = *CopyOperands.
Source;
863 MCRegister ForwardedReg = CopySrc;
866 if (MOUse.
getReg() != CopyDst) {
867 unsigned SubRegIdx =
TRI->getSubRegIndex(CopyDst, MOUse.
getReg());
869 "MI source is not a sub-register of Copy destination");
870 ForwardedReg =
TRI->getSubReg(CopySrc, SubRegIdx);
871 if (!ForwardedReg ||
TRI->isArtificial(ForwardedReg)) {
872 LLVM_DEBUG(
dbgs() <<
"MCP: Copy source does not have sub-register "
873 <<
TRI->getSubRegIndexName(SubRegIdx) <<
'\n');
882 if (!isForwardableRegClassCopy(*Copy,
MI,
OpIdx))
885 if (hasImplicitOverlap(
MI, MOUse))
891 if (isCopyInstr(
MI, *
TII, UseCopyInstr) &&
892 MI.modifiesRegister(CopySrc,
TRI) &&
893 !
MI.definesRegister(CopySrc,
nullptr)) {
899 LLVM_DEBUG(
dbgs() <<
"MCP: Skipping forwarding due to debug counter:\n "
906 <<
"\n in " <<
MI <<
" from " << *Copy);
908 MOUse.
setReg(ForwardedReg);
917 for (MachineInstr &KMI :
919 KMI.clearRegisterKills(CopySrc,
TRI);
926void MachineCopyPropagation::forwardCopyPropagateBlock(MachineBasicBlock &
MBB) {
932 std::optional<DestSourcePair> CopyOperands =
933 isCopyInstr(
MI, *
TII, UseCopyInstr);
935 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
936 if (!
TRI->regsOverlap(Dst, Src)) {
952 if (eraseIfRedundant(
MI, Dst, Src) || eraseIfRedundant(
MI, Src, Dst))
958 for (
const MachineOperand &MO :
MI.operands())
959 if (MO.isReg() && MO.isEarlyClobber()) {
966 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
973 if (
TII->simplifyInstruction(
MI)) {
978 CopyOperands = isCopyInstr(
MI, *
TII, UseCopyInstr);
980 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
981 if (!
TRI->regsOverlap(Dst, Src)) {
984 if (!isNeverRedundant(
MI) && !isNeverRedundant(Dst))
985 MaybeDeadCopies.insert(&
MI);
990 const MachineOperand *RegMask =
nullptr;
991 for (
const MachineOperand &MO :
MI.operands()) {
1001 "MachineCopyPropagation should be run after register allocation!");
1003 if (MO.isDef() && !MO.isEarlyClobber()) {
1009 }
else if (MO.readsReg()) {
1018 BitVector &PreservedRegUnits =
1019 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
1022 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
1023 MaybeDeadCopies.begin();
1024 DI != MaybeDeadCopies.end();) {
1025 MachineInstr *MaybeDead = *DI;
1026 std::optional<DestSourcePair> CopyOperands =
1027 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1028 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
1029 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(
Reg));
1038 bool MIRefedinCopyInfo =
false;
1039 for (MCRegUnit RegUnit :
TRI->regunits(
Reg)) {
1040 if (!PreservedRegUnits.
test(
static_cast<unsigned>(RegUnit)))
1041 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1043 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1044 MIRefedinCopyInfo =
true;
1051 DI = MaybeDeadCopies.erase(DI);
1054 if (MIRefedinCopyInfo)
1057 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1067 for (MCRegister
Reg : Defs)
1068 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1071 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1072 if (!
TRI->regsOverlap(Dst, Src)) {
1073 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1083 readSuccessorLiveIns(
MBB);
1089 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1090 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1093 DestSourcePair CopyOperands =
1094 *isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1096 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1097 assert(!isNeverRedundant(*MaybeDead) && !isNeverRedundant(Dst));
1100 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1111 MaybeDeadCopies.clear();
1112 CopyDbgUsers.clear();
1116void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1117 if (!Tracker.hasAnyCopies())
1120 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1122 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1138 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1143 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1144 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1146 if (MODef.
getReg() != Src)
1149 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1152 if (hasImplicitOverlap(
MI, MODef))
1155 if (hasOverlappingMultipleDef(
MI, MODef, Dst))
1158 if (!canUpdateSrcUsers(*Copy, *CopyOperands.
Source))
1163 <<
MI <<
" from " << *Copy);
1168 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1169 for (MachineOperand &MO : SrcUser->uses()) {
1170 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1178 MaybeDeadCopies.insert(Copy);
1180 ++NumCopyBackwardPropagated;
1184void MachineCopyPropagation::backwardCopyPropagateBlock(
1185 MachineBasicBlock &
MBB) {
1191 std::optional<DestSourcePair> CopyOperands =
1192 isCopyInstr(
MI, *
TII, UseCopyInstr);
1193 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1194 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1196 if (!
TRI->regsOverlap(Dst, Src)) {
1199 if (isBackwardPropagatableCopy(
MI, *CopyOperands)) {
1200 Tracker.invalidateRegister(Src, *
TRI, *
TII, UseCopyInstr);
1201 Tracker.invalidateRegister(Dst, *
TRI, *
TII, UseCopyInstr);
1202 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1209 for (
const MachineOperand &MO :
MI.operands())
1210 if (MO.isReg() && MO.isEarlyClobber()) {
1214 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1218 for (
const MachineOperand &MO :
MI.operands()) {
1226 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1229 if (MO.readsReg()) {
1234 for (MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1235 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1236 CopyDbgUsers[
Copy].insert(&
MI);
1239 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1242 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1249 for (
auto *Copy : MaybeDeadCopies) {
1250 DestSourcePair CopyOperands = *isCopyInstr(*Copy, *
TII, UseCopyInstr);
1251 auto [Dst, Src] = getDstSrcMCRegs(CopyOperands);
1252 const auto &DbgUsers = CopyDbgUsers[
Copy];
1257 Copy->eraseFromParent();
1261 MaybeDeadCopies.clear();
1262 CopyDbgUsers.clear();
1270 auto &SC = SpillChain[Leader];
1271 auto &RC = ReloadChain[Leader];
1272 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1316void MachineCopyPropagation::eliminateSpillageCopies(MachineBasicBlock &
MBB) {
1321 unsigned CopyCount = 0;
1322 for (
const MachineInstr &
MI :
MBB) {
1323 if (isCopyInstr(
MI, *
TII, UseCopyInstr) && ++CopyCount > 6)
1331 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1336 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1339 DenseSet<const MachineInstr *> CopySourceInvalid;
1341 auto TryFoldSpillageCopies =
1342 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1343 const SmallVectorImpl<MachineInstr *> &RC) {
1344 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1359 for (
const MachineInstr *Spill :
drop_begin(SC))
1360 if (CopySourceInvalid.
count(Spill))
1363 for (
const MachineInstr *Reload :
drop_end(RC))
1364 if (CopySourceInvalid.
count(Reload))
1368 return TRI->getCommonMinimalPhysRegClass(Dst, Src);
1371 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1372 const MachineOperand *
New) {
1373 for (MachineOperand &MO :
MI->operands()) {
1375 MO.setReg(
New->getReg());
1379 DestSourcePair InnerMostSpillCopy =
1380 *isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1381 DestSourcePair OuterMostSpillCopy =
1382 *isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1383 DestSourcePair InnerMostReloadCopy =
1384 *isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1385 DestSourcePair OuterMostReloadCopy =
1386 *isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1387 if (!CheckCopyConstraint(getSrcMCReg(OuterMostSpillCopy),
1388 getSrcMCReg(InnerMostSpillCopy)) ||
1389 !CheckCopyConstraint(getDstMCReg(InnerMostReloadCopy),
1390 getDstMCReg(OuterMostReloadCopy)))
1393 SpillageChainsLength += SC.
size() + RC.size();
1394 NumSpillageChains += 1;
1396 OuterMostSpillCopy.
Source);
1397 UpdateReg(RC[0], InnerMostReloadCopy.
Source,
1400 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1401 SC[
I]->eraseFromParent();
1402 RC[
I]->eraseFromParent();
1407 auto GetFoldableCopy =
1408 [
this](
const MachineInstr &MaybeCopy) -> std::optional<DestSourcePair> {
1409 if (MaybeCopy.getNumImplicitOperands() > 0)
1410 return std::nullopt;
1411 std::optional<DestSourcePair> CopyOperands =
1412 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1414 return std::nullopt;
1415 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1416 if (Src && Dst && !
TRI->regsOverlap(Src, Dst) &&
1417 CopyOperands->Source->isRenamable() &&
1418 CopyOperands->Destination->isRenamable())
1419 return CopyOperands;
1421 return std::nullopt;
1424 auto IsSpillReloadPair = [&](
const MachineInstr &
Spill,
1425 const MachineInstr &Reload) {
1426 std::optional<DestSourcePair> FoldableSpillCopy = GetFoldableCopy(Spill);
1427 if (!FoldableSpillCopy)
1429 std::optional<DestSourcePair> FoldableReloadCopy = GetFoldableCopy(Reload);
1430 if (!FoldableReloadCopy)
1432 return FoldableSpillCopy->Source->getReg() ==
1433 FoldableReloadCopy->Destination->getReg() &&
1434 FoldableSpillCopy->Destination->getReg() ==
1435 FoldableReloadCopy->Source->getReg();
1438 auto IsChainedCopy = [&](
const MachineInstr &Prev,
1439 const MachineInstr &Current) {
1440 std::optional<DestSourcePair> FoldablePrevCopy = GetFoldableCopy(Prev);
1441 if (!FoldablePrevCopy)
1443 std::optional<DestSourcePair> FoldableCurrentCopy =
1444 GetFoldableCopy(Current);
1445 if (!FoldableCurrentCopy)
1447 return FoldablePrevCopy->Source->getReg() ==
1448 FoldableCurrentCopy->Destination->getReg();
1452 std::optional<DestSourcePair> CopyOperands =
1453 isCopyInstr(
MI, *
TII, UseCopyInstr);
1456 SmallSet<Register, 8> RegsToClobber;
1457 if (!CopyOperands) {
1458 for (
const MachineOperand &MO :
MI.operands()) {
1459 if (MO.isRegMask()) {
1460 BitVector &PreservedRegUnits = Tracker.getPreservedRegUnits(MO, *
TRI);
1461 Tracker.clobberNonPreservedRegs(PreservedRegUnits, *
TRI, *
TII);
1469 MachineInstr *LastUseCopy =
1476 CopySourceInvalid.
insert(LastUseCopy);
1490 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1497 auto [Dst, Src] = getDstSrcMCRegs(*CopyOperands);
1499 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1501 MachineInstr *MaybeSpill =
1502 Tracker.findLastSeenDefInCopy(
MI, Src, *
TRI, *
TII, UseCopyInstr);
1503 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1504 if (!MaybeSpillIsChained && MaybeSpill &&
1505 IsSpillReloadPair(*MaybeSpill,
MI)) {
1540 MachineInstr *MaybePrevReload = Tracker.findLastSeenUseInCopy(Dst, *
TRI);
1541 auto Leader = ChainLeader.
find(MaybePrevReload);
1542 MachineInstr *
L =
nullptr;
1543 if (Leader == ChainLeader.
end() ||
1544 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1547 "SpillChain should not have contained newly found chain");
1549 assert(MaybePrevReload &&
1550 "Found a valid leader through nullptr should not happend");
1553 "Existing chain's length should be larger than zero");
1556 "Newly found paired spill-reload should not belong to any chain "
1558 ChainLeader.
insert({MaybeSpill,
L});
1560 SpillChain[
L].push_back(MaybeSpill);
1561 ReloadChain[
L].push_back(&
MI);
1564 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1581 Tracker.clobberRegister(Src, *
TRI, *
TII, UseCopyInstr);
1585 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1588 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1589 auto &SC =
I->second;
1591 "Reload chain of the same leader should exist");
1592 auto &RC = ReloadChain[
I->first];
1593 TryFoldSpillageCopies(SC, RC);
1596 MaybeDeadCopies.clear();
1597 CopyDbgUsers.clear();
1601bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1605 return MachineCopyPropagation(UseCopyInstr).run(MF);
1612 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1620 bool IsSpillageCopyElimEnabled =
false;
1623 IsSpillageCopyElimEnabled =
1627 IsSpillageCopyElimEnabled =
true;
1630 IsSpillageCopyElimEnabled =
false;
1641 if (IsSpillageCopyElimEnabled)
1642 eliminateSpillageCopies(
MBB);
1643 backwardCopyPropagateBlock(
MBB);
1644 forwardCopyPropagateBlock(
MBB);
1650MachineFunctionPass *
1652 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 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)
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.
const MachineOperand * Source
const MachineOperand * Destination