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 (MCRegUnit SafeUnit :
TRI.regunits(SafeReg))
141 PreservedRegUnits.
set(
static_cast<unsigned>(SafeUnit));
143 return PreservedRegUnits;
150 const TargetRegisterInfo &
TRI) {
151 for (MCRegister
Reg : Regs) {
153 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
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());
180 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
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);
224 for (MCRegUnit SrcUnit :
TRI.regunits(Src)) {
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) {
255 for (MCRegUnit Unit :
TRI.regunits(
Reg)) {
256 clobberRegUnit(Unit,
TRI,
TII, UseCopyInstr);
263 bool trackSrcUsers(MCRegister
Reg, MachineInstr &
MI,
264 const TargetRegisterInfo &
TRI,
const TargetInstrInfo &
TII,
266 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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) {
290 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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();
308 for (MCRegUnit Unit :
TRI.regunits(Def))
309 Copies[
Unit] = {
MI,
nullptr, {}, {},
true};
313 for (MCRegUnit Unit :
TRI.regunits(Src)) {
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,
351 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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) {
380 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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,
412 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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) {
441 MCRegUnit RU = *
TRI.regunits(
Reg).begin();
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)
535 for (MCRegUnit Unit :
TRI->regunits(
Reg)) {
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();
941 if (!
TRI->regsOverlap(RegDef, RegSrc)) {
944 if (!
MRI->isReserved(Def))
945 MaybeDeadCopies.insert(&
MI);
950 const MachineOperand *RegMask =
nullptr;
951 for (
const MachineOperand &MO :
MI.operands()) {
961 "MachineCopyPropagation should be run after register allocation!");
963 if (MO.isDef() && !MO.isEarlyClobber()) {
965 if (!
MRI->isConstantPhysReg(
Reg)) {
969 }
else if (MO.readsReg())
970 ReadRegister(
Reg.
asMCReg(),
MI, MO.isDebug() ? DebugUse : RegularUse);
977 BitVector &PreservedRegUnits =
978 Tracker.getPreservedRegUnits(*RegMask, *
TRI);
981 for (SmallSetVector<MachineInstr *, 8>::iterator DI =
982 MaybeDeadCopies.begin();
983 DI != MaybeDeadCopies.end();) {
984 MachineInstr *MaybeDead = *DI;
985 std::optional<DestSourcePair> CopyOperands =
986 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
987 MCRegister
Reg = CopyOperands->Destination->getReg().asMCReg();
997 bool MIRefedinCopyInfo =
false;
998 for (MCRegUnit RegUnit :
TRI->regunits(
Reg)) {
999 if (!PreservedRegUnits.
test(
static_cast<unsigned>(RegUnit)))
1000 Tracker.clobberRegUnit(RegUnit, *
TRI, *
TII, UseCopyInstr);
1002 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *
TRI)) {
1003 MIRefedinCopyInfo =
true;
1010 DI = MaybeDeadCopies.erase(DI);
1013 if (MIRefedinCopyInfo)
1016 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to regmask clobbering: "
1026 for (MCRegister
Reg : Defs)
1027 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1030 Register RegSrc = CopyOperands->Source->getReg();
1031 Register RegDef = CopyOperands->Destination->getReg();
1032 if (!
TRI->regsOverlap(RegDef, RegSrc)) {
1033 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1038 bool TracksLiveness =
MRI->tracksLiveness();
1043 readSuccessorLiveIns(
MBB);
1049 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1050 LLVM_DEBUG(
dbgs() <<
"MCP: Removing copy due to no live-out succ: ";
1053 std::optional<DestSourcePair> CopyOperands =
1054 isCopyInstr(*MaybeDead, *
TII, UseCopyInstr);
1057 Register SrcReg = CopyOperands->Source->getReg();
1058 Register DestReg = CopyOperands->Destination->getReg();
1062 const auto &DbgUsers = CopyDbgUsers[MaybeDead];
1074 MaybeDeadCopies.clear();
1075 CopyDbgUsers.clear();
1087 if (
MRI.isReserved(Def) ||
MRI.isReserved(Src))
1093void MachineCopyPropagation::propagateDefs(MachineInstr &
MI) {
1094 if (!Tracker.hasAnyCopies())
1097 for (
unsigned OpIdx = 0, OpEnd =
MI.getNumOperands();
OpIdx != OpEnd;
1099 MachineOperand &MODef =
MI.getOperand(
OpIdx);
1115 MachineInstr *
Copy = Tracker.findAvailBackwardCopy(
1120 std::optional<DestSourcePair> CopyOperands =
1121 isCopyInstr(*Copy, *
TII, UseCopyInstr);
1122 Register Def = CopyOperands->Destination->getReg();
1123 Register Src = CopyOperands->Source->getReg();
1125 if (MODef.
getReg() != Src)
1128 if (!isBackwardPropagatableRegClassCopy(*Copy,
MI,
OpIdx))
1131 if (hasImplicitOverlap(
MI, MODef))
1134 if (hasOverlappingMultipleDef(
MI, MODef, Def))
1137 if (!canUpdateSrcUsers(*Copy, *CopyOperands->Source))
1142 <<
MI <<
" from " << *Copy);
1147 for (
auto *SrcUser : Tracker.getSrcUsers(Src, *
TRI)) {
1148 for (MachineOperand &MO : SrcUser->uses()) {
1149 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1152 MO.setIsRenamable(CopyOperands->Destination->isRenamable());
1157 MaybeDeadCopies.insert(Copy);
1159 ++NumCopyBackwardPropagated;
1163void MachineCopyPropagation::BackwardCopyPropagateBlock(
1164 MachineBasicBlock &
MBB) {
1170 std::optional<DestSourcePair> CopyOperands =
1171 isCopyInstr(
MI, *
TII, UseCopyInstr);
1172 if (CopyOperands &&
MI.getNumImplicitOperands() == 0) {
1173 Register DefReg = CopyOperands->Destination->getReg();
1174 Register SrcReg = CopyOperands->Source->getReg();
1176 if (!
TRI->regsOverlap(DefReg, SrcReg)) {
1184 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1191 for (
const MachineOperand &MO :
MI.operands())
1192 if (MO.isReg() && MO.isEarlyClobber()) {
1196 Tracker.invalidateRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1200 for (
const MachineOperand &MO :
MI.operands()) {
1208 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1211 if (MO.readsReg()) {
1216 for (MCRegUnit Unit :
TRI->regunits(MO.getReg().asMCReg())) {
1217 if (
auto *Copy = Tracker.findCopyDefViaUnit(Unit, *
TRI)) {
1218 CopyDbgUsers[
Copy].insert(&
MI);
1221 }
else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(),
MI, *
TRI, *
TII,
1224 Tracker.invalidateRegister(MO.getReg().asMCReg(), *
TRI, *
TII,
1231 for (
auto *Copy : MaybeDeadCopies) {
1232 std::optional<DestSourcePair> CopyOperands =
1233 isCopyInstr(*Copy, *
TII, UseCopyInstr);
1234 Register Src = CopyOperands->Source->getReg();
1235 Register Def = CopyOperands->Destination->getReg();
1236 const auto &DbgUsers = CopyDbgUsers[
Copy];
1240 MRI->updateDbgUsersToReg(Src.asMCReg(),
Def.asMCReg(), MaybeDeadDbgUsers);
1241 Copy->eraseFromParent();
1245 MaybeDeadCopies.clear();
1246 CopyDbgUsers.clear();
1254 auto &SC = SpillChain[Leader];
1255 auto &RC = ReloadChain[Leader];
1256 for (
auto I = SC.rbegin(),
E = SC.rend();
I !=
E; ++
I)
1300void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &
MBB) {
1303 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;
1308 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;
1311 DenseSet<const MachineInstr *> CopySourceInvalid;
1313 auto TryFoldSpillageCopies =
1314 [&,
this](
const SmallVectorImpl<MachineInstr *> &SC,
1315 const SmallVectorImpl<MachineInstr *> &RC) {
1316 assert(SC.
size() == RC.size() &&
"Spill-reload should be paired");
1331 for (
const MachineInstr *Spill :
drop_begin(SC))
1332 if (CopySourceInvalid.
count(Spill))
1335 for (
const MachineInstr *Reload :
drop_end(RC))
1336 if (CopySourceInvalid.
count(Reload))
1340 for (
const TargetRegisterClass *RC :
TRI->regclasses()) {
1341 if (RC->contains(Def) && RC->contains(Src))
1347 auto UpdateReg = [](MachineInstr *
MI,
const MachineOperand *Old,
1348 const MachineOperand *
New) {
1349 for (MachineOperand &MO :
MI->operands()) {
1351 MO.setReg(
New->getReg());
1355 std::optional<DestSourcePair> InnerMostSpillCopy =
1356 isCopyInstr(*SC[0], *
TII, UseCopyInstr);
1357 std::optional<DestSourcePair> OuterMostSpillCopy =
1358 isCopyInstr(*SC.
back(), *
TII, UseCopyInstr);
1359 std::optional<DestSourcePair> InnerMostReloadCopy =
1360 isCopyInstr(*RC[0], *
TII, UseCopyInstr);
1361 std::optional<DestSourcePair> OuterMostReloadCopy =
1362 isCopyInstr(*RC.back(), *
TII, UseCopyInstr);
1363 if (!CheckCopyConstraint(OuterMostSpillCopy->Source->getReg(),
1364 InnerMostSpillCopy->Source->getReg()) ||
1365 !CheckCopyConstraint(InnerMostReloadCopy->Destination->getReg(),
1366 OuterMostReloadCopy->Destination->getReg()))
1369 SpillageChainsLength += SC.
size() + RC.size();
1370 NumSpillageChains += 1;
1371 UpdateReg(SC[0], InnerMostSpillCopy->Destination,
1372 OuterMostSpillCopy->Source);
1373 UpdateReg(RC[0], InnerMostReloadCopy->Source,
1374 OuterMostReloadCopy->Destination);
1376 for (
size_t I = 1;
I < SC.
size() - 1; ++
I) {
1377 SC[
I]->eraseFromParent();
1378 RC[
I]->eraseFromParent();
1383 auto IsFoldableCopy = [
this](
const MachineInstr &MaybeCopy) {
1384 if (MaybeCopy.getNumImplicitOperands() > 0)
1386 std::optional<DestSourcePair> CopyOperands =
1387 isCopyInstr(MaybeCopy, *
TII, UseCopyInstr);
1390 Register Src = CopyOperands->Source->getReg();
1391 Register Def = CopyOperands->Destination->getReg();
1392 return Src &&
Def && !
TRI->regsOverlap(Src, Def) &&
1393 CopyOperands->Source->isRenamable() &&
1394 CopyOperands->Destination->isRenamable();
1397 auto IsSpillReloadPair = [&,
this](
const MachineInstr &
Spill,
1398 const MachineInstr &Reload) {
1399 if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))
1401 std::optional<DestSourcePair> SpillCopy =
1402 isCopyInstr(Spill, *
TII, UseCopyInstr);
1403 std::optional<DestSourcePair> ReloadCopy =
1404 isCopyInstr(Reload, *
TII, UseCopyInstr);
1405 if (!SpillCopy || !ReloadCopy)
1407 return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&
1408 SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();
1411 auto IsChainedCopy = [&,
this](
const MachineInstr &Prev,
1412 const MachineInstr &Current) {
1413 if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))
1415 std::optional<DestSourcePair> PrevCopy =
1416 isCopyInstr(Prev, *
TII, UseCopyInstr);
1417 std::optional<DestSourcePair> CurrentCopy =
1418 isCopyInstr(Current, *
TII, UseCopyInstr);
1419 if (!PrevCopy || !CurrentCopy)
1421 return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();
1425 std::optional<DestSourcePair> CopyOperands =
1426 isCopyInstr(
MI, *
TII, UseCopyInstr);
1429 SmallSet<Register, 8> RegsToClobber;
1430 if (!CopyOperands) {
1431 for (
const MachineOperand &MO :
MI.operands()) {
1437 MachineInstr *LastUseCopy =
1444 CopySourceInvalid.
insert(LastUseCopy);
1458 Tracker.clobberRegister(
Reg, *
TRI, *
TII, UseCopyInstr);
1465 Register Src = CopyOperands->Source->getReg();
1466 Register Def = CopyOperands->Destination->getReg();
1468 LLVM_DEBUG(
dbgs() <<
"MCP: Searching paired spill for reload: ");
1470 MachineInstr *MaybeSpill =
1471 Tracker.findLastSeenDefInCopy(
MI, Src.asMCReg(), *
TRI, *
TII, UseCopyInstr);
1472 bool MaybeSpillIsChained = ChainLeader.
count(MaybeSpill);
1473 if (!MaybeSpillIsChained && MaybeSpill &&
1474 IsSpillReloadPair(*MaybeSpill,
MI)) {
1509 MachineInstr *MaybePrevReload =
1510 Tracker.findLastSeenUseInCopy(
Def.asMCReg(), *
TRI);
1511 auto Leader = ChainLeader.
find(MaybePrevReload);
1512 MachineInstr *
L =
nullptr;
1513 if (Leader == ChainLeader.
end() ||
1514 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload,
MI))) {
1517 "SpillChain should not have contained newly found chain");
1519 assert(MaybePrevReload &&
1520 "Found a valid leader through nullptr should not happend");
1523 "Existing chain's length should be larger than zero");
1526 "Newly found paired spill-reload should not belong to any chain "
1528 ChainLeader.
insert({MaybeSpill,
L});
1530 SpillChain[
L].push_back(MaybeSpill);
1531 ReloadChain[
L].push_back(&
MI);
1534 }
else if (MaybeSpill && !MaybeSpillIsChained) {
1551 Tracker.clobberRegister(Src.asMCReg(), *
TRI, *
TII, UseCopyInstr);
1555 Tracker.trackCopy(&
MI, *
TRI, *
TII, UseCopyInstr);
1558 for (
auto I = SpillChain.
begin(),
E = SpillChain.
end();
I !=
E; ++
I) {
1559 auto &SC =
I->second;
1561 "Reload chain of the same leader should exist");
1562 auto &RC = ReloadChain[
I->first];
1563 TryFoldSpillageCopies(SC, RC);
1566 MaybeDeadCopies.clear();
1567 CopyDbgUsers.clear();
1571bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {
1575 return MachineCopyPropagation(UseCopyInstr).run(MF);
1582 if (!MachineCopyPropagation(UseCopyInstr).
run(MF))
1590 bool isSpillageCopyElimEnabled =
false;
1593 isSpillageCopyElimEnabled =
1597 isSpillageCopyElimEnabled =
true;
1600 isSpillageCopyElimEnabled =
false;
1611 if (isSpillageCopyElimEnabled)
1612 EliminateSpillageCopies(
MBB);
1613 BackwardCopyPropagateBlock(
MBB);
1614 ForwardCopyPropagateBlock(
MBB);
1620MachineFunctionPass *
1622 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")
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 bool isBackwardPropagatableCopy(const DestSourcePair &CopyOperands, const MachineRegisterInfo &MRI)
static void printSpillReloadChain(DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &SpillChain, DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &ReloadChain, MachineInstr *Leader)
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.
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