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");
97static std::optional<DestSourcePair> isCopyInstr(
const MachineInstr &
MI,
101 return TII.isCopyInstr(
MI);
104 return std::optional<DestSourcePair>(
112 MachineInstr *MI =
nullptr;
113 MachineInstr *LastSeenUseInCopy =
nullptr;
114 SmallPtrSet<MachineInstr *, 4> SrcUsers;
119 DenseMap<MCRegUnit, CopyInfo> Copies;
124 DenseMap<const uint32_t *, BitVector> RegMaskToPreservedRegUnits;
128 BitVector &getPreservedRegUnits(
const MachineOperand &RegMaskOp,
129 const TargetRegisterInfo &
TRI) {
130 const uint32_t *RegMask = RegMaskOp.
getRegMask();
131 auto [It,
Inserted] = RegMaskToPreservedRegUnits.try_emplace(RegMask);
135 BitVector &PreservedRegUnits = It->second;
137 PreservedRegUnits.
resize(
TRI.getNumRegUnits());
138 for (
unsigned SafeReg = 0,
E =
TRI.getNumRegs(); SafeReg <
E; ++SafeReg)
140 for (
auto SafeUnit :
TRI.regunits(SafeReg))
141 PreservedRegUnits.
set(SafeUnit);
143 return PreservedRegUnits;
150 const TargetRegisterInfo &
TRI) {
151 for (MCRegister
Reg : Regs) {
154 auto CI = Copies.find(Unit);
155 if (CI != Copies.end())
156 CI->second.Avail =
false;
162 void invalidateRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
163 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
168 SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;
169 auto InvalidateCopy = [&](MachineInstr *
MI) {
170 std::optional<DestSourcePair> CopyOperands =
171 isCopyInstr(*
MI,
TII, UseCopyInstr);
172 assert(CopyOperands &&
"Expect copy");
174 auto Dest =
TRI.regunits(CopyOperands->Destination->getReg().asMCReg());
175 auto Src =
TRI.regunits(CopyOperands->Source->getReg().asMCReg());
181 auto I = Copies.find(Unit);
182 if (
I != Copies.end()) {
183 if (MachineInstr *
MI =
I->second.MI)
185 if (MachineInstr *
MI =
I->second.LastSeenUseInCopy)
189 for (
MCRegUnit Unit : RegUnitsToInvalidate)
194 void clobberRegUnit(
MCRegUnit Unit,
const TargetRegisterInfo &
TRI,
195 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
196 auto I = Copies.find(Unit);
197 if (
I != Copies.end()) {
200 markRegsUnavailable(
I->second.DefRegs,
TRI);
203 if (MachineInstr *
MI =
I->second.MI) {
204 std::optional<DestSourcePair> CopyOperands =
205 isCopyInstr(*
MI,
TII, UseCopyInstr);
207 MCRegister
Def = CopyOperands->Destination->getReg().asMCReg();
208 MCRegister Src = CopyOperands->Source->getReg().asMCReg();
210 markRegsUnavailable(Def,
TRI);
225 auto SrcCopy = Copies.find(SrcUnit);
226 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {
229 for (
auto itr = SrcCopy->second.DefRegs.begin();
230 itr != SrcCopy->second.DefRegs.end(); itr++) {
232 SrcCopy->second.DefRegs.erase(itr);
238 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {
239 Copies.erase(SrcCopy);
253 void clobberRegister(MCRegister
Reg,
const TargetRegisterInfo &
TRI,
254 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
256 clobberRegUnit(Unit,
TRI,
TII, UseCopyInstr);
263 bool trackSrcUsers(MCRegister
Reg, MachineInstr &
MI,
264 const TargetRegisterInfo &
TRI,
const TargetInstrInfo &
TII,
267 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
271 std::optional<DestSourcePair> CopyOperands =
272 isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
273 Register Src = CopyOperands->Source->getReg();
279 auto I = Copies.find(RU);
280 if (
I == Copies.end())
283 I->second.SrcUsers.insert(&
MI);
288 SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister
Reg,
289 const TargetRegisterInfo &
TRI) {
291 auto I = Copies.find(RU);
292 if (
I == Copies.end())
294 return I->second.SrcUsers;
298 void trackCopy(MachineInstr *
MI,
const TargetRegisterInfo &
TRI,
299 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
300 std::optional<DestSourcePair> CopyOperands =
301 isCopyInstr(*
MI,
TII, UseCopyInstr);
302 assert(CopyOperands &&
"Tracking non-copy?");
304 MCRegister Src = CopyOperands->Source->getReg().asMCReg();
305 MCRegister
Def = CopyOperands->Destination->getReg().asMCReg();
309 Copies[
Unit] = {
MI,
nullptr, {}, {},
true};
316 Copy.DefRegs.push_back(Def);
317 Copy.LastSeenUseInCopy =
MI;
321 bool hasAnyCopies() {
322 return !Copies.empty();
325 MachineInstr *findCopyForUnit(
MCRegUnit RegUnit,
326 const TargetRegisterInfo &
TRI,
327 bool MustBeAvailable =
false) {
328 auto CI = Copies.find(RegUnit);
329 if (CI == Copies.end())
331 if (MustBeAvailable && !CI->second.Avail)
333 return CI->second.MI;
336 MachineInstr *findCopyDefViaUnit(
MCRegUnit RegUnit,
337 const TargetRegisterInfo &
TRI) {
338 auto CI = Copies.find(RegUnit);
339 if (CI == Copies.end())
341 if (CI->second.DefRegs.size() != 1)
343 MCRegUnit RU = *
TRI.regunits(CI->second.DefRegs[0]).begin();
344 return findCopyForUnit(RU,
TRI,
true);
347 MachineInstr *findAvailBackwardCopy(MachineInstr &
I, MCRegister
Reg,
348 const TargetRegisterInfo &
TRI,
349 const TargetInstrInfo &
TII,
352 MachineInstr *AvailCopy = findCopyDefViaUnit(RU,
TRI);
357 std::optional<DestSourcePair> CopyOperands =
358 isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
359 Register AvailSrc = CopyOperands->Source->getReg();
360 Register AvailDef = CopyOperands->Destination->getReg();
361 if (!
TRI.isSubRegisterEq(AvailSrc,
Reg))
364 for (
const MachineInstr &
MI :
366 for (
const MachineOperand &MO :
MI.operands())
369 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
375 MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister
Reg,
376 const TargetRegisterInfo &
TRI,
377 const TargetInstrInfo &
TII,
bool UseCopyInstr) {
381 MachineInstr *AvailCopy =
382 findCopyForUnit(RU,
TRI,
true);
387 std::optional<DestSourcePair> CopyOperands =
388 isCopyInstr(*AvailCopy,
TII, UseCopyInstr);
389 Register AvailSrc = CopyOperands->Source->getReg();
390 Register AvailDef = CopyOperands->Destination->getReg();
391 if (!
TRI.isSubRegisterEq(AvailDef,
Reg))
396 for (
const MachineInstr &
MI :
398 for (
const MachineOperand &MO :
MI.operands())
400 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
407 MachineInstr *findLastSeenDefInCopy(
const MachineInstr &Current,
409 const TargetRegisterInfo &
TRI,
410 const TargetInstrInfo &
TII,
413 auto CI = Copies.find(RU);
414 if (CI == Copies.end() || !CI->second.Avail)
417 MachineInstr *DefCopy = CI->second.MI;
418 std::optional<DestSourcePair> CopyOperands =
419 isCopyInstr(*DefCopy,
TII, UseCopyInstr);
420 Register Def = CopyOperands->Destination->getReg();
421 if (!
TRI.isSubRegisterEq(Def,
Reg))
424 for (
const MachineInstr &
MI :
425 make_range(
static_cast<const MachineInstr *
>(DefCopy)->getIterator(),
427 for (
const MachineOperand &MO :
MI.operands())
429 if (MO.clobbersPhysReg(Def)) {
439 MachineInstr *findLastSeenUseInCopy(MCRegister
Reg,
440 const TargetRegisterInfo &
TRI) {
442 auto CI = Copies.find(RU);
443 if (CI == Copies.end())
445 return CI->second.LastSeenUseInCopy;
453class MachineCopyPropagation {
454 const TargetRegisterInfo *TRI =
nullptr;
455 const TargetInstrInfo *TII =
nullptr;
456 const MachineRegisterInfo *MRI =
nullptr;
462 MachineCopyPropagation(
bool CopyInstr =
false)
465 bool run(MachineFunction &MF);
468 typedef enum { DebugUse =
false, RegularUse =
true } DebugType;
470 void ReadRegister(MCRegister
Reg, MachineInstr &Reader, DebugType DT);
471 void readSuccessorLiveIns(
const MachineBasicBlock &
MBB);
472 void ForwardCopyPropagateBlock(MachineBasicBlock &
MBB);
473 void BackwardCopyPropagateBlock(MachineBasicBlock &
MBB);
474 void EliminateSpillageCopies(MachineBasicBlock &
MBB);
475 bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);
476 void forwardUses(MachineInstr &
MI);
477 void propagateDefs(MachineInstr &
MI);
478 bool isForwardableRegClassCopy(
const MachineInstr &Copy,
479 const MachineInstr &UseI,
unsigned UseIdx);
480 bool isBackwardPropagatableRegClassCopy(
const MachineInstr &Copy,
481 const MachineInstr &UseI,
483 bool hasImplicitOverlap(
const MachineInstr &
MI,
const MachineOperand &Use);
484 bool hasOverlappingMultipleDef(
const MachineInstr &
MI,
485 const MachineOperand &MODef,
Register Def);
486 bool canUpdateSrcUsers(
const MachineInstr &Copy,
487 const MachineOperand &CopySrc);
490 SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
493 DenseMap<MachineInstr *, SmallPtrSet<MachineInstr *, 2>> CopyDbgUsers;
497 bool Changed =
false;
506 MachineCopyPropagationLegacy(
bool UseCopyInstr =
false)
507 : MachineFunctionPass(ID), UseCopyInstr(UseCopyInstr) {}
509 void getAnalysisUsage(AnalysisUsage &AU)
const override {
514 bool runOnMachineFunction(MachineFunction &MF)
override;
516 MachineFunctionProperties getRequiredProperties()
const override {
517 return MachineFunctionProperties().setNoVRegs();
523char MachineCopyPropagationLegacy::ID = 0;
528 "Machine Copy Propagation Pass",
false,
false)
536 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
537 if (DT == RegularUse) {
538 LLVM_DEBUG(dbgs() <<
"MCP: Copy is used - not dead: "; Copy->dump());
539 MaybeDeadCopies.remove(Copy);
541 CopyDbgUsers[Copy].insert(&Reader);
547void MachineCopyPropagation::readSuccessorLiveIns(
549 if (MaybeDeadCopies.empty())
554 for (
const auto &LI : Succ->liveins()) {
555 for (MCRegUnitMaskIterator
U(LI.PhysReg,
TRI);
U.isValid(); ++U) {
557 if ((Mask & LI.LaneMask).any()) {
558 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *
TRI))
559 MaybeDeadCopies.remove(Copy);
576 std::optional<DestSourcePair> CopyOperands =
577 isCopyInstr(PreviousCopy, *
TII, UseCopyInstr);
578 MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();
579 MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();
580 if (Src == PreviousSrc && Def == PreviousDef)
582 if (!
TRI->isSubRegister(PreviousSrc, Src))
584 unsigned SubIdx =
TRI->getSubRegIndex(PreviousSrc, Src);
585 return SubIdx ==
TRI->getSubRegIndex(PreviousDef, Def);
591bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
592 MCRegister Src, MCRegister Def) {
595 if (
MRI->isReserved(Src) ||
MRI->isReserved(Def))
599 MachineInstr *PrevCopy =
600 Tracker.findAvailCopy(Copy, Def, *
TRI, *
TII, UseCopyInstr);
604 auto PrevCopyOperands = isCopyInstr(*PrevCopy, *
TII, UseCopyInstr);
606 if (PrevCopyOperands->Destination->isDead())
615 std::optional<DestSourcePair> CopyOperands =
616 isCopyInstr(Copy, *
TII, UseCopyInstr);
619 Register CopyDef = CopyOperands->Destination->getReg();
620 assert(CopyDef == Src || CopyDef == Def);
621 for (MachineInstr &
MI :
623 MI.clearRegisterKills(CopyDef,
TRI);
626 if (!CopyOperands->Source->isUndef()) {
627 PrevCopy->
getOperand(PrevCopyOperands->Source->getOperandNo())
631 Copy.eraseFromParent();
637bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
638 const MachineInstr &Copy,
const MachineInstr &UseI,
unsigned UseIdx) {
639 std::optional<DestSourcePair> CopyOperands =
640 isCopyInstr(Copy, *
TII, UseCopyInstr);
641 Register Def = CopyOperands->Destination->getReg();
643 if (
const TargetRegisterClass *URC =
645 return URC->contains(Def);
655bool MachineCopyPropagation::isForwardableRegClassCopy(
const MachineInstr &Copy,
656 const MachineInstr &UseI,
658 std::optional<DestSourcePair> CopyOperands =
659 isCopyInstr(Copy, *
TII, UseCopyInstr);
660 Register CopySrcReg = CopyOperands->Source->getReg();
664 if (
const TargetRegisterClass *URC =
666 return URC->contains(CopySrcReg);
668 auto UseICopyOperands = isCopyInstr(UseI, *
TII, UseCopyInstr);
669 if (!UseICopyOperands)
692 Register UseDstReg = UseICopyOperands->Destination->getReg();
694 bool IsCrossClass =
false;
695 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
696 if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {
698 if (
TRI->getCrossCopyRegClass(RC) != RC) {
710 Register CopyDstReg = CopyOperands->Destination->getReg();
711 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
712 if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&
713 TRI->getCrossCopyRegClass(RC) != RC)
727bool MachineCopyPropagation::hasImplicitOverlap(
const MachineInstr &
MI,
728 const MachineOperand &Use) {
729 for (
const MachineOperand &MIUse :
MI.uses())
730 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
731 MIUse.isUse() &&
TRI->regsOverlap(
Use.getReg(), MIUse.getReg()))
741bool MachineCopyPropagation::hasOverlappingMultipleDef(
742 const MachineInstr &
MI,
const MachineOperand &MODef,
Register Def) {
743 for (
const MachineOperand &MIDef :
MI.all_defs()) {
744 if ((&MIDef != &MODef) && MIDef.isReg() &&
745 TRI->regsOverlap(Def, MIDef.getReg()))
754bool MachineCopyPropagation::canUpdateSrcUsers(
const MachineInstr &Copy,
755 const MachineOperand &CopySrc) {
756 assert(CopySrc.
isReg() &&
"Expected a register operand");
757 for (
auto *SrcUser : Tracker.getSrcUsers(CopySrc.
getReg(), *
TRI)) {
758 if (hasImplicitOverlap(*SrcUser, CopySrc))
761 for (MachineOperand &MO : SrcUser->uses()) {
762 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.
getReg())
764 if (MO.isTied() || !MO.isRenamable() ||
765 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
775void MachineCopyPropagation::forwardUses(MachineInstr &
MI) {
776 if (!Tracker.hasAnyCopies())
782 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx < OpEnd;
784 MachineOperand &MOUse =
MI.getOperand(
OpIdx);
804 *
TRI, *
TII, UseCopyInstr);
808 std::optional<DestSourcePair> CopyOperands =
809 isCopyInstr(*Copy, *
TII, UseCopyInstr);
810 Register CopyDstReg = CopyOperands->Destination->getReg();
811 const MachineOperand &CopySrc = *CopyOperands->Source;
817 if (MOUse.
getReg() != CopyDstReg) {
818 unsigned SubRegIdx =
TRI->getSubRegIndex(CopyDstReg, MOUse.
getReg());
820 "MI source is not a sub-register of Copy destination");
821 ForwardedReg =
TRI->getSubReg(CopySrcReg, SubRegIdx);
823 LLVM_DEBUG(
dbgs() <<
"MCP: Copy source does not have sub-register "
824 <<
TRI->getSubRegIndexName(SubRegIdx) <<
'\n');
830 if (
MRI->isReserved(CopySrcReg) && !
MRI->isConstantPhysReg(CopySrcReg))
833 if (!isForwardableRegClassCopy(*Copy,
MI,
OpIdx))
836 if (hasImplicitOverlap(
MI, MOUse))
842 if (isCopyInstr(
MI, *
TII, UseCopyInstr) &&
843 MI.modifiesRegister(CopySrcReg,
TRI) &&
844 !
MI.definesRegister(CopySrcReg,
nullptr)) {
850 LLVM_DEBUG(
dbgs() <<
"MCP: Skipping forwarding due to debug counter:\n "
857 <<
"\n in " <<
MI <<
" from " << *Copy);
859 MOUse.
setReg(ForwardedReg);
868 for (MachineInstr &KMI :
870 KMI.clearRegisterKills(CopySrcReg,
TRI);
877void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &
MBB) {
883 std::optional<DestSourcePair> CopyOperands =
884 isCopyInstr(
MI, *
TII, UseCopyInstr);
886 Register RegSrc = CopyOperands->Source->getReg();
887 Register RegDef = CopyOperands->Destination->getReg();
888 if (!
TRI->regsOverlap(RegDef, RegSrc)) {
890 "MachineCopyPropagation should be run after register allocation!");
893 MCRegister Src = RegSrc.
asMCReg();
910 if (eraseIfRedundant(
MI, Def, Src) || eraseIfRedundant(
MI, Src, Def))
916 for (
const MachineOperand &MO :
MI.operands())
917 if (MO.isReg() && MO.isEarlyClobber()) {
923 ReadRegister(
Reg,
MI, RegularUse);
924 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
931 if (
TII->simplifyInstruction(
MI)) {
936 CopyOperands = isCopyInstr(
MI, *
TII, UseCopyInstr);
938 Register RegSrc = CopyOperands->Source->getReg();
939 Register RegDef = CopyOperands->Destination->getReg();
944 if (RegSrc == RegDef && !
MRI->isReserved(RegSrc)) {
945 MI.eraseFromParent();
951 if (!
TRI->regsOverlap(RegDef, RegSrc)) {
954 if (!
MRI->isReserved(Def))
955 MaybeDeadCopies.insert(&
MI);
960 const MachineOperand *RegMask =
nullptr;
961 for (
const MachineOperand &MO :
MI.operands()) {
971 "MachineCopyPropagation should be run after register allocation!");
973 if (MO.isDef() && !MO.isEarlyClobber()) {
975 if (!
MRI->isConstantPhysReg(
Reg)) {
979 }
else if (MO.readsReg())
980 ReadRegister(
Reg.
asMCReg(),
MI, MO.isDebug() ? DebugUse : RegularUse);
987 BitVector &PreservedRegUnits =
988 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
991 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
992 MaybeDeadCopies.begin();
993 DI != MaybeDeadCopies.end();) {
994 MachineInstr *MaybeDead = *DI;
995 std::optional<DestSourcePair> CopyOperands =
996 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
997 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
1007 bool MIRefedinCopyInfo =
false;
1008 for (
unsigned RegUnit :
TRI->regunits(
Reg)) {
1009 if (!PreservedRegUnits.
test(RegUnit))
1010 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1012 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1013 MIRefedinCopyInfo =
true;
1020 DI = MaybeDeadCopies.erase(DI);
1023 if (MIRefedinCopyInfo)
1026 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1036 for (MCRegister
Reg : Defs)
1037 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1040 Register RegSrc = CopyOperands->Source->getReg();
1041 Register RegDef = CopyOperands->Destination->getReg();
1042 if (!
TRI->regsOverlap(RegDef, RegSrc)) {
1043 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1048 bool TracksLiveness =
MRI->tracksLiveness();
1053 readSuccessorLiveIns(
MBB);
1059 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1060 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1063 std::optional<DestSourcePair> CopyOperands =
1064 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1067 Register SrcReg = CopyOperands->Source->getReg();
1068 Register DestReg = CopyOperands->Destination->getReg();
1072 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1084 MaybeDeadCopies.clear();
1085 CopyDbgUsers.clear();
1097 if (
MRI.isReserved(Def) ||
MRI.isReserved(Src))
1103void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1104 if (!Tracker.hasAnyCopies())
1107 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1109 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1125 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1130 std::optional<DestSourcePair> CopyOperands =
1131 isCopyInstr(*Copy, *
TII, UseCopyInstr);
1132 Register Def = CopyOperands->Destination->getReg();
1133 Register Src = CopyOperands->Source->getReg();
1135 if (MODef.
getReg() != Src)
1138 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1141 if (hasImplicitOverlap(
MI, MODef))
1144 if (hasOverlappingMultipleDef(
MI, MODef, Def))
1147 if (!canUpdateSrcUsers(*Copy, *CopyOperands->Source))
1152 <<
MI <<
" from " << *Copy);
1157 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1158 for (MachineOperand &MO : SrcUser->uses()) {
1159 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1162 MO.setIsRenamable(CopyOperands->Destination->isRenamable());
1167 MaybeDeadCopies.insert(Copy);
1169 ++NumCopyBackwardPropagated;
1173void MachineCopyPropagation::BackwardCopyPropagateBlock(
1174 MachineBasicBlock &
MBB) {
1180 std::optional<DestSourcePair> CopyOperands =
1181 isCopyInstr(
MI, *
TII, UseCopyInstr);
1182 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1183 Register DefReg = CopyOperands->Destination->getReg();
1184 Register SrcReg = CopyOperands->Source->getReg();
1186 if (!
TRI->regsOverlap(DefReg, SrcReg)) {
1194 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1201 for (
const MachineOperand &MO :
MI.operands())
1202 if (MO.isReg() && MO.isEarlyClobber()) {
1206 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1210 for (
const MachineOperand &MO :
MI.operands()) {
1218 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1221 if (MO.readsReg()) {
1226 for (
MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1227 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1228 CopyDbgUsers[
Copy].insert(&
MI);
1231 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1234 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1241 for (
auto *Copy : MaybeDeadCopies) {
1242 std::optional<DestSourcePair> CopyOperands =
1243 isCopyInstr(*Copy, *
TII, UseCopyInstr);
1244 Register Src = CopyOperands->Source->getReg();
1245 Register Def = CopyOperands->Destination->getReg();
1246 const auto &DbgUsers = CopyDbgUsers[
Copy];
1250 MRI->updateDbgUsersToReg(Src.asMCReg(),
Def.asMCReg(), MaybeDeadDbgUsers);
1251 Copy->eraseFromParent();
1255 MaybeDeadCopies.clear();
1256 CopyDbgUsers.clear();
1264 auto &SC = SpillChain[Leader];
1265 auto &RC = ReloadChain[Leader];
1266 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1310void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &
MBB) {
1313 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1318 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1321 DenseSet<const MachineInstr *> CopySourceInvalid;
1323 auto TryFoldSpillageCopies =
1324 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1325 const SmallVectorImpl<MachineInstr *> &RC) {
1326 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1341 for (
const MachineInstr *Spill :
drop_begin(SC))
1342 if (CopySourceInvalid.
count(Spill))
1345 for (
const MachineInstr *Reload :
drop_end(RC))
1346 if (CopySourceInvalid.
count(Reload))
1350 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
1351 if (RC->contains(Def) && RC->contains(Src))
1357 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1358 const MachineOperand *
New) {
1359 for (MachineOperand &MO :
MI->operands()) {
1361 MO.setReg(
New->getReg());
1365 std::optional<DestSourcePair> InnerMostSpillCopy =
1366 isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1367 std::optional<DestSourcePair> OuterMostSpillCopy =
1368 isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1369 std::optional<DestSourcePair> InnerMostReloadCopy =
1370 isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1371 std::optional<DestSourcePair> OuterMostReloadCopy =
1372 isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1373 if (!CheckCopyConstraint(OuterMostSpillCopy->Source->getReg(),
1374 InnerMostSpillCopy->Source->getReg()) ||
1375 !CheckCopyConstraint(InnerMostReloadCopy->Destination->getReg(),
1376 OuterMostReloadCopy->Destination->getReg()))
1379 SpillageChainsLength += SC.
size() + RC.size();
1380 NumSpillageChains += 1;
1381 UpdateReg(SC[0], InnerMostSpillCopy->Destination,
1382 OuterMostSpillCopy->Source);
1383 UpdateReg(RC[0], InnerMostReloadCopy->Source,
1384 OuterMostReloadCopy->Destination);
1386 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1387 SC[
I]->eraseFromParent();
1388 RC[
I]->eraseFromParent();
1393 auto IsFoldableCopy = [
this](
const MachineInstr &MaybeCopy) {
1394 if (MaybeCopy.getNumImplicitOperands() > 0)
1396 std::optional<DestSourcePair> CopyOperands =
1397 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1400 Register Src = CopyOperands->Source->getReg();
1401 Register Def = CopyOperands->Destination->getReg();
1402 return Src &&
Def && !
TRI->regsOverlap(Src, Def) &&
1403 CopyOperands->Source->isRenamable() &&
1404 CopyOperands->Destination->isRenamable();
1407 auto IsSpillReloadPair = [&,
this](
const MachineInstr &
Spill,
1408 const MachineInstr &Reload) {
1409 if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))
1411 std::optional<DestSourcePair> SpillCopy =
1412 isCopyInstr(Spill, *
TII, UseCopyInstr);
1413 std::optional<DestSourcePair> ReloadCopy =
1414 isCopyInstr(Reload, *
TII, UseCopyInstr);
1415 if (!SpillCopy || !ReloadCopy)
1417 return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&
1418 SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();
1421 auto IsChainedCopy = [&,
this](
const MachineInstr &Prev,
1422 const MachineInstr &Current) {
1423 if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))
1425 std::optional<DestSourcePair> PrevCopy =
1426 isCopyInstr(Prev, *
TII, UseCopyInstr);
1427 std::optional<DestSourcePair> CurrentCopy =
1428 isCopyInstr(Current, *
TII, UseCopyInstr);
1429 if (!PrevCopy || !CurrentCopy)
1431 return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();
1435 std::optional<DestSourcePair> CopyOperands =
1436 isCopyInstr(
MI, *
TII, UseCopyInstr);
1439 SmallSet<Register, 8> RegsToClobber;
1440 if (!CopyOperands) {
1441 for (
const MachineOperand &MO :
MI.operands()) {
1447 MachineInstr *LastUseCopy =
1454 CopySourceInvalid.
insert(LastUseCopy);
1468 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1475 Register Src = CopyOperands->Source->getReg();
1476 Register Def = CopyOperands->Destination->getReg();
1478 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1480 MachineInstr *MaybeSpill =
1481 Tracker.findLastSeenDefInCopy(
MI, Src.asMCReg(), *
TRI, *
TII, UseCopyInstr);
1482 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1483 if (!MaybeSpillIsChained && MaybeSpill &&
1484 IsSpillReloadPair(*MaybeSpill,
MI)) {
1519 MachineInstr *MaybePrevReload =
1520 Tracker.findLastSeenUseInCopy(
Def.asMCReg(), *
TRI);
1521 auto Leader = ChainLeader.
find(MaybePrevReload);
1522 MachineInstr *
L =
nullptr;
1523 if (Leader == ChainLeader.
end() ||
1524 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1527 "SpillChain should not have contained newly found chain");
1529 assert(MaybePrevReload &&
1530 "Found a valid leader through nullptr should not happend");
1533 "Existing chain's length should be larger than zero");
1536 "Newly found paired spill-reload should not belong to any chain "
1538 ChainLeader.
insert({MaybeSpill,
L});
1540 SpillChain[
L].push_back(MaybeSpill);
1541 ReloadChain[
L].push_back(&
MI);
1544 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1561 Tracker.clobberRegister(Src.asMCReg(), *
TRI, *
TII, UseCopyInstr);
1565 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1568 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1569 auto &SC =
I->second;
1571 "Reload chain of the same leader should exist");
1572 auto &RC = ReloadChain[
I->first];
1573 TryFoldSpillageCopies(SC, RC);
1576 MaybeDeadCopies.clear();
1577 CopyDbgUsers.clear();
1581bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1585 return MachineCopyPropagation(UseCopyInstr).run(MF);
1592 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1600 bool isSpillageCopyElimEnabled =
false;
1603 isSpillageCopyElimEnabled =
1607 isSpillageCopyElimEnabled =
true;
1610 isSpillageCopyElimEnabled =
false;
1621 if (isSpillageCopyElimEnabled)
1622 EliminateSpillageCopies(
MBB);
1623 BackwardCopyPropagateBlock(
MBB);
1624 ForwardCopyPropagateBlock(
MBB);
1630MachineFunctionPass *
1632 return new MachineCopyPropagationLegacy(UseCopyInstr);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ATTRIBUTE_UNUSED
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 LLVM_ATTRIBUTE_UNUSED printSpillReloadChain(DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &SpillChain, DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &ReloadChain, MachineInstr *Leader)
static bool isBackwardPropagatableCopy(const DestSourcePair &CopyOperands, const MachineRegisterInfo &MRI)
static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src, MCRegister Def, const TargetRegisterInfo *TRI, const TargetInstrInfo *TII, bool UseCopyInstr)
Return true if PreviousCopy did copy register Src to register Def.
static cl::opt< bool > MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false), cl::Hidden)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
bool test(unsigned Idx) const
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
Represents analyses that only rely on functions' control flow.
static bool shouldExecute(unsigned CounterName)
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Wrapper class representing physical registers. Should be passed by value.
An RAII based helper class to modify MachineFunctionProperties when running pass.
iterator_range< succ_iterator > successors()
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI const TargetRegisterClass * getRegClassConstraint(unsigned OpIdx, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const
Compute the static register class constraint for operand OpIdx.
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.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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 isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
void insert_range(Range &&R)
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool enableSpillageCopyElimination() const
Enable spillage copy elimination in MachineCopyPropagation pass.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
reverse_self_iterator getReverseIterator()
self_iterator getIterator()
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< DefNode * > Def
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.
unsigned MCRegUnit
Register units are used to compute register aliasing.
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