LLVM: lib/CodeGen/MachineCopyPropagation.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
74#include
75#include
76
77using namespace llvm;
78
79#define DEBUG_TYPE "machine-cp"
80
81STATISTIC(NumDeletes, "Number of dead copies deleted");
82STATISTIC(NumCopyForwards, "Number of copy uses forwarded");
83STATISTIC(NumCopyBackwardPropagated, "Number of copy defs backward propagated");
84STATISTIC(SpillageChainsLength, "Length of spillage chains");
85STATISTIC(NumSpillageChains, "Number of spillage chains");
87 "Controls which register COPYs are forwarded");
88
93
94namespace {
95
96static std::optional isCopyInstr(const MachineInstr &MI,
98 bool UseCopyInstr) {
99 if (UseCopyInstr)
100 return TII.isCopyInstr(MI);
101
102 if (MI.isCopy())
103 return std::optional(
105
106 return std::nullopt;
107}
108
109class CopyTracker {
110 struct CopyInfo {
115 bool Avail = false;
116 };
117
119
120
121
122
124
125public:
126
131 if (!Inserted) {
132 return It->second;
133 } else {
134 BitVector &PreservedRegUnits = It->second;
135
136 PreservedRegUnits.resize(TRI.getNumRegUnits());
137 for (unsigned SafeReg = 0, E = TRI.getNumRegs(); SafeReg < E; ++SafeReg)
139 for (auto SafeUnit : TRI.regunits(SafeReg))
140 PreservedRegUnits.set(SafeUnit);
141
142 return PreservedRegUnits;
143 }
144 }
145
146
147
151
153 auto CI = Copies.find(Unit);
154 if (CI != Copies.end())
155 CI->second.Avail = false;
156 }
157 }
158 }
159
160
163
164
165
166
169 std::optional CopyOperands =
170 isCopyInstr(*MI, TII, UseCopyInstr);
171 assert(CopyOperands && "Expect copy");
172
173 auto Dest = TRI.regunits(CopyOperands->Destination->getReg().asMCReg());
174 auto Src = TRI.regunits(CopyOperands->Source->getReg().asMCReg());
175 RegUnitsToInvalidate.insert(Dest.begin(), Dest.end());
176 RegUnitsToInvalidate.insert(Src.begin(), Src.end());
177 };
178
180 auto I = Copies.find(Unit);
183 InvalidateCopy(MI);
185 InvalidateCopy(MI);
186 }
187 }
188 for (MCRegUnit Unit : RegUnitsToInvalidate)
190 }
191
192
195 auto I = Copies.find(Unit);
197
198
199 markRegsUnavailable(I->second.DefRegs, TRI);
200
201
203 std::optional CopyOperands =
204 isCopyInstr(*MI, TII, UseCopyInstr);
205
206 MCRegister Def = CopyOperands->Destination->getReg().asMCReg();
207 MCRegister Src = CopyOperands->Source->getReg().asMCReg();
208
209 markRegsUnavailable(Def, TRI);
210
211
212
213
214
215
216
217
218
219
220
221
222
223 for (MCRegUnit SrcUnit : TRI.regunits(Src)) {
224 auto SrcCopy = Copies.find(SrcUnit);
225 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {
226
227
228 for (auto itr = SrcCopy->second.DefRegs.begin();
229 itr != SrcCopy->second.DefRegs.end(); itr++) {
230 if (*itr == Def) {
231 SrcCopy->second.DefRegs.erase(itr);
232
233
234
235
236
237 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {
238 Copies.erase(SrcCopy);
239 }
240 break;
241 }
242 }
243 }
244 }
245 }
246
248 }
249 }
250
251
255 clobberRegUnit(Unit, TRI, TII, UseCopyInstr);
256 }
257 }
258
259
260
261
264 bool UseCopyInstr) {
267 if (!AvailCopy)
268 return false;
269
270 std::optional CopyOperands =
271 isCopyInstr(*AvailCopy, TII, UseCopyInstr);
272 Register Src = CopyOperands->Source->getReg();
273
274
275 if (Src != Reg)
276 return false;
277
280 return false;
281
282 I->second.SrcUsers.insert(&MI);
283 return true;
284 }
285
286
292 return {};
293 return I->second.SrcUsers;
294 }
295
296
299 std::optional CopyOperands =
300 isCopyInstr(*MI, TII, UseCopyInstr);
301 assert(CopyOperands && "Tracking non-copy?");
302
303 MCRegister Src = CopyOperands->Source->getReg().asMCReg();
304 MCRegister Def = CopyOperands->Destination->getReg().asMCReg();
305
306
308 Copies[Unit] = {MI, nullptr, {}, {}, true};
309
310
311
315 Copy.DefRegs.push_back(Def);
316 Copy.LastSeenUseInCopy = MI;
317 }
318 }
319
320 bool hasAnyCopies() {
321 return .empty();
322 }
323
326 bool MustBeAvailable = false) {
327 auto CI = Copies.find(RegUnit);
328 if (CI == Copies.end())
329 return nullptr;
330 if (MustBeAvailable && !CI->second.Avail)
331 return nullptr;
332 return CI->second.MI;
333 }
334
337 auto CI = Copies.find(RegUnit);
338 if (CI == Copies.end())
339 return nullptr;
340 if (CI->second.DefRegs.size() != 1)
341 return nullptr;
342 MCRegUnit RU = *TRI.regunits(CI->second.DefRegs[0]).begin();
343 return findCopyForUnit(RU, TRI, true);
344 }
345
349 bool UseCopyInstr) {
352
353 if (!AvailCopy)
354 return nullptr;
355
356 std::optional CopyOperands =
357 isCopyInstr(*AvailCopy, TII, UseCopyInstr);
358 Register AvailSrc = CopyOperands->Source->getReg();
359 Register AvailDef = CopyOperands->Destination->getReg();
360 if (.isSubRegisterEq(AvailSrc, Reg))
361 return nullptr;
362
366 if (MO.isRegMask())
367
368 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
369 return nullptr;
370
371 return AvailCopy;
372 }
373
377
378
381 findCopyForUnit(RU, TRI, true);
382
383 if (!AvailCopy)
384 return nullptr;
385
386 std::optional CopyOperands =
387 isCopyInstr(*AvailCopy, TII, UseCopyInstr);
388 Register AvailSrc = CopyOperands->Source->getReg();
389 Register AvailDef = CopyOperands->Destination->getReg();
390 if (.isSubRegisterEq(AvailDef, Reg))
391 return nullptr;
392
393
394
398 if (MO.isRegMask())
399 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))
400 return nullptr;
401
402 return AvailCopy;
403 }
404
405
410 bool UseCopyInstr) {
412 auto CI = Copies.find(RU);
413 if (CI == Copies.end() || !CI->second.Avail)
414 return nullptr;
415
417 std::optional CopyOperands =
418 isCopyInstr(*DefCopy, TII, UseCopyInstr);
419 Register Def = CopyOperands->Destination->getReg();
420 if (.isSubRegisterEq(Def, Reg))
421 return nullptr;
422
427 if (MO.isRegMask())
428 if (MO.clobbersPhysReg(Def)) {
431 return nullptr;
432 }
433
434 return DefCopy;
435 }
436
437
441 auto CI = Copies.find(RU);
442 if (CI == Copies.end())
443 return nullptr;
444 return CI->second.LastSeenUseInCopy;
445 }
446
447 void clear() {
449 }
450};
451
456
457
458 bool UseCopyInstr;
459
460public:
461 static char ID;
462
463 MachineCopyPropagation(bool CopyInstr = false)
466 }
467
471 }
472
474
477 MachineFunctionProperties::Property::NoVRegs);
478 }
479
480private:
481 typedef enum { DebugUse = false, RegularUse = true } DebugType;
482
491 bool isForwardableRegClassCopy(const MachineInstr &Copy,
493 bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,
495 unsigned UseIdx);
497 bool hasOverlappingMultipleDef(const MachineInstr &MI,
499 bool canUpdateSrcUsers(const MachineInstr &Copy,
501
502
504
505
507
508 CopyTracker Tracker;
509
510 bool Changed = false;
511};
512
513}
514
515char MachineCopyPropagation::ID = 0;
516
518
520 "Machine Copy Propagation Pass", false, false)
521
523 DebugType DT) {
524
525
526
528 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {
529 if (DT == RegularUse) {
530 LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
531 MaybeDeadCopies.remove(Copy);
532 } else {
533 CopyDbgUsers[Copy].insert(&Reader);
534 }
535 }
536 }
537}
538
539void MachineCopyPropagation::readSuccessorLiveIns(
541 if (MaybeDeadCopies.empty())
542 return;
543
544
546 for (const auto &LI : Succ->liveins()) {
547 for (MCRegUnit Unit : TRI->regunits(LI.PhysReg)) {
548 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI))
549 MaybeDeadCopies.remove(Copy);
550 }
551 }
552 }
553}
554
555
556
557
558
559
560
564
565 std::optional CopyOperands =
566 isCopyInstr(PreviousCopy, *TII, UseCopyInstr);
567 MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();
568 MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();
569 if (Src == PreviousSrc && Def == PreviousDef)
570 return true;
571 if (->isSubRegister(PreviousSrc, Src))
572 return false;
573 unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);
574 return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);
575}
576
577
578
579
580bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,
582
583
584 if (MRI->isReserved(Src) || MRI->isReserved(Def))
585 return false;
586
587
589 Tracker.findAvailCopy(Copy, Def, *TRI, *TII, UseCopyInstr);
590 if (!PrevCopy)
591 return false;
592
593 auto PrevCopyOperands = isCopyInstr(*PrevCopy, *TII, UseCopyInstr);
594
595 if (PrevCopyOperands->Destination->isDead())
596 return false;
597 if ((*PrevCopy, Src, Def, TRI, TII, UseCopyInstr))
598 return false;
599
601
602
603
604 std::optional CopyOperands =
605 isCopyInstr(Copy, *TII, UseCopyInstr);
606 assert(CopyOperands);
607
608 Register CopyDef = CopyOperands->Destination->getReg();
609 assert(CopyDef == Src || CopyDef == Def);
612 MI.clearRegisterKills(CopyDef, TRI);
613
614
615 if (!CopyOperands->Source->isUndef()) {
616 PrevCopy->getOperand(PrevCopyOperands->Source->getOperandNo())
618 }
619
620 Copy.eraseFromParent();
621 Changed = true;
622 ++NumDeletes;
623 return true;
624}
625
626bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(
628 std::optional CopyOperands =
629 isCopyInstr(Copy, *TII, UseCopyInstr);
630 Register Def = CopyOperands->Destination->getReg();
631
634 return URC->contains(Def);
635
636
637
638 return false;
639}
640
641
642
643
644bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,
646 unsigned UseIdx) {
647 std::optional CopyOperands =
648 isCopyInstr(Copy, *TII, UseCopyInstr);
649 Register CopySrcReg = CopyOperands->Source->getReg();
650
651
652
655 return URC->contains(CopySrcReg);
656
657 auto UseICopyOperands = isCopyInstr(UseI, *TII, UseCopyInstr);
658 if (!UseICopyOperands)
659 return false;
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681 Register UseDstReg = UseICopyOperands->Destination->getReg();
682 bool Found = false;
683 bool IsCrossClass = false;
685 if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {
686 Found = true;
687 if (TRI->getCrossCopyRegClass(RC) != RC) {
688 IsCrossClass = true;
689 break;
690 }
691 }
692 }
693 if (!Found)
694 return false;
695 if (!IsCrossClass)
696 return true;
697
698
699 Register CopyDstReg = CopyOperands->Destination->getReg();
701 if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&
702 TRI->getCrossCopyRegClass(RC) != RC)
703 return true;
704 }
705 return false;
706}
707
708
709
710
711
712
713
714
715
716bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
719 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&
720 MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))
721 return true;
722
723 return false;
724}
725
726
727
728
729
730bool MachineCopyPropagation::hasOverlappingMultipleDef(
733 if ((&MIDef != &MODef) && MIDef.isReg() &&
734 TRI->regsOverlap(Def, MIDef.getReg()))
735 return true;
736 }
737
738 return false;
739}
740
741
742
743bool MachineCopyPropagation::canUpdateSrcUsers(const MachineInstr &Copy,
745 assert(CopySrc.isReg() && "Expected a register operand");
746 for (auto *SrcUser : Tracker.getSrcUsers(CopySrc.getReg(), *TRI)) {
747 if (hasImplicitOverlap(*SrcUser, CopySrc))
748 return false;
749
751 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.getReg())
752 continue;
753 if (MO.isTied() || !MO.isRenamable() ||
754 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,
755 MO.getOperandNo()))
756 return false;
757 }
758 }
759 return true;
760}
761
762
763
764void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
765 if (!Tracker.hasAnyCopies())
766 return;
767
768
769
770
771 for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;
772 ++OpIdx) {
774
775
776
777
778
781 continue;
782
784 continue;
785
786
787
788
790 continue;
791
793 *TRI, *TII, UseCopyInstr);
794 if (!Copy)
795 continue;
796
797 std::optional CopyOperands =
798 isCopyInstr(*Copy, *TII, UseCopyInstr);
799 Register CopyDstReg = CopyOperands->Destination->getReg();
800 const MachineOperand &CopySrc = *CopyOperands->Source;
802
803 Register ForwardedReg = CopySrcReg;
804
805
806 if (MOUse.getReg() != CopyDstReg) {
807 unsigned SubRegIdx = TRI->getSubRegIndex(CopyDstReg, MOUse.getReg());
809 "MI source is not a sub-register of Copy destination");
810 ForwardedReg = TRI->getSubReg(CopySrcReg, SubRegIdx);
811 if (!ForwardedReg) {
812 LLVM_DEBUG(dbgs() << "MCP: Copy source does not have sub-register "
813 << TRI->getSubRegIndexName(SubRegIdx) << '\n');
814 continue;
815 }
816 }
817
818
819 if (MRI->isReserved(CopySrcReg) && ->isConstantPhysReg(CopySrcReg))
820 continue;
821
822 if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
823 continue;
824
825 if (hasImplicitOverlap(MI, MOUse))
826 continue;
827
828
829
830
831 if (isCopyInstr(MI, *TII, UseCopyInstr) &&
832 MI.modifiesRegister(CopySrcReg, TRI) &&
833 .definesRegister(CopySrcReg, nullptr)) {
834 LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);
835 continue;
836 }
837
839 LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n "
840 << MI);
841 continue;
842 }
843
845 << "\n with " << printReg(ForwardedReg, TRI)
846 << "\n in " << MI << " from " << *Copy);
847
848 MOUse.setReg(ForwardedReg);
849
853
854 LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
855
856
858 make_range(Copy->getIterator(), std::next(MI.getIterator())))
859 KMI.clearRegisterKills(CopySrcReg, TRI);
860
861 ++NumCopyForwards;
862 Changed = true;
863 }
864}
865
866void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {
868 << "\n");
869
871
872 std::optional CopyOperands =
873 isCopyInstr(MI, *TII, UseCopyInstr);
874 if (CopyOperands) {
875
876 Register RegSrc = CopyOperands->Source->getReg();
877 Register RegDef = CopyOperands->Destination->getReg();
878
879 if (->regsOverlap(RegDef, RegSrc)) {
881 "MachineCopyPropagation should be run after register allocation!");
882
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901 if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def))
902 continue;
903
904 forwardUses(MI);
905
906
907 CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr);
908 Src = CopyOperands->Source->getReg().asMCReg();
909
910
911
912 ReadRegister(Src, MI, RegularUse);
914 if (!MO.isReg() || !MO.readsReg())
915 continue;
917 if (!Reg)
918 continue;
919 ReadRegister(Reg, MI, RegularUse);
920 }
921
923
924
925 if (->isReserved(Def))
926 MaybeDeadCopies.insert(&MI);
927
928
929
930
931
932
933
934
935 Tracker.clobberRegister(Def, *TRI, *TII, UseCopyInstr);
937 if (!MO.isReg() || !MO.isDef())
938 continue;
940 if (!Reg)
941 continue;
942 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
943 }
944
945 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
946
947 continue;
948 }
949 }
950
951
953 if (MO.isReg() && MO.isEarlyClobber()) {
955
956
957
958 if (MO.isTied())
959 ReadRegister(Reg, MI, RegularUse);
960 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
961 }
962
963 forwardUses(MI);
964
965
969 if (MO.isRegMask())
970 RegMask = &MO;
971 if (!MO.isReg())
972 continue;
974 if (!Reg)
975 continue;
976
978 "MachineCopyPropagation should be run after register allocation!");
979
980 if (MO.isDef() && !MO.isEarlyClobber()) {
981
982 if (->isConstantPhysReg(Reg)) {
984 continue;
985 }
986 } else if (MO.readsReg())
987 ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse);
988 }
989
990
991
992
993 if (RegMask) {
995 Tracker.getPreservedRegUnits(*RegMask, *TRI);
996
997
999 MaybeDeadCopies.begin();
1000 DI != MaybeDeadCopies.end();) {
1002 std::optional CopyOperands =
1003 isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
1004 MCRegister Reg = CopyOperands->Destination->getReg().asMCReg();
1006
1008 ++DI;
1009 continue;
1010 }
1011
1012 LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: ";
1013 MaybeDead->dump());
1014
1015
1016
1017 for (unsigned RegUnit : TRI->regunits(Reg))
1018 if (!PreservedRegUnits.test(RegUnit))
1019 Tracker.clobberRegUnit(RegUnit, *TRI, *TII, UseCopyInstr);
1020
1021
1022
1023 DI = MaybeDeadCopies.erase(DI);
1025 Changed = true;
1026 ++NumDeletes;
1027 }
1028 }
1029
1030
1032 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
1033 }
1034
1035 bool TracksLiveness = MRI->tracksLiveness();
1036
1037
1038
1039 if (TracksLiveness)
1040 readSuccessorLiveIns(MBB);
1041
1042
1043
1044
1046 for (MachineInstr *MaybeDead : MaybeDeadCopies) {
1047 LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";
1048 MaybeDead->dump());
1049
1050 std::optional CopyOperands =
1051 isCopyInstr(*MaybeDead, *TII, UseCopyInstr);
1052 assert(CopyOperands);
1053
1054 Register SrcReg = CopyOperands->Source->getReg();
1055 Register DestReg = CopyOperands->Destination->getReg();
1056 assert(->isReserved(DestReg));
1057
1058
1060 CopyDbgUsers[MaybeDead].begin(), CopyDbgUsers[MaybeDead].end());
1062 MaybeDeadDbgUsers);
1063
1065 Changed = true;
1066 ++NumDeletes;
1067 }
1068 }
1069
1070 MaybeDeadCopies.clear();
1071 CopyDbgUsers.clear();
1072 Tracker.clear();
1073}
1074
1079
1080 if (!Def || !Src)
1081 return false;
1082
1083 if (MRI.isReserved(Def) || MRI.isReserved(Src))
1084 return false;
1085
1087}
1088
1089void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {
1090 if (!Tracker.hasAnyCopies())
1091 return;
1092
1093 for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;
1094 ++OpIdx) {
1096
1097 if (!MODef.isReg() || MODef.isUse())
1098 continue;
1099
1100
1102 continue;
1103
1104 if (!MODef.getReg())
1105 continue;
1106
1107
1109 continue;
1110
1113 if (!Copy)
1114 continue;
1115
1116 std::optional CopyOperands =
1117 isCopyInstr(*Copy, *TII, UseCopyInstr);
1118 Register Def = CopyOperands->Destination->getReg();
1119 Register Src = CopyOperands->Source->getReg();
1120
1121 if (MODef.getReg() != Src)
1122 continue;
1123
1124 if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))
1125 continue;
1126
1127 if (hasImplicitOverlap(MI, MODef))
1128 continue;
1129
1130 if (hasOverlappingMultipleDef(MI, MODef, Def))
1131 continue;
1132
1133 if (!canUpdateSrcUsers(*Copy, *CopyOperands->Source))
1134 continue;
1135
1137 << "\n with " << printReg(Def, TRI) << "\n in "
1138 << MI << " from " << *Copy);
1139
1141 MODef.setIsRenamable(CopyOperands->Destination->isRenamable());
1142
1143 for (auto *SrcUser : Tracker.getSrcUsers(Src, *TRI)) {
1145 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)
1146 continue;
1147 MO.setReg(Def);
1148 MO.setIsRenamable(CopyOperands->Destination->isRenamable());
1149 }
1150 }
1151
1152 LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");
1153 MaybeDeadCopies.insert(Copy);
1154 Changed = true;
1155 ++NumCopyBackwardPropagated;
1156 }
1157}
1158
1159void MachineCopyPropagation::BackwardCopyPropagateBlock(
1162 << "\n");
1163
1165
1166 std::optional CopyOperands =
1167 isCopyInstr(MI, *TII, UseCopyInstr);
1168 if (CopyOperands) {
1169 Register DefReg = CopyOperands->Destination->getReg();
1170 Register SrcReg = CopyOperands->Source->getReg();
1171
1172 if (->regsOverlap(DefReg, SrcReg)) {
1173
1174
1176 Tracker.invalidateRegister(SrcReg.asMCReg(), *TRI, *TII,
1177 UseCopyInstr);
1178 Tracker.invalidateRegister(DefReg.asMCReg(), *TRI, *TII,
1179 UseCopyInstr);
1180 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
1181 continue;
1182 }
1183 }
1184 }
1185
1186
1188 if (MO.isReg() && MO.isEarlyClobber()) {
1190 if (!Reg)
1191 continue;
1192 Tracker.invalidateRegister(Reg, *TRI, *TII, UseCopyInstr);
1193 }
1194
1195 propagateDefs(MI);
1197 if (!MO.isReg())
1198 continue;
1199
1200 if (!MO.getReg())
1201 continue;
1202
1203 if (MO.isDef())
1204 Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
1205 UseCopyInstr);
1206
1207 if (MO.readsReg()) {
1208 if (MO.isDebug()) {
1209
1210
1211
1212 for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {
1213 if (auto *Copy = Tracker.findCopyDefViaUnit(Unit, *TRI)) {
1214 CopyDbgUsers[Copy].insert(&MI);
1215 }
1216 }
1217 } else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(), MI, *TRI, *TII,
1218 UseCopyInstr)) {
1219
1220 Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,
1221 UseCopyInstr);
1222 }
1223 }
1224 }
1225 }
1226
1227 for (auto *Copy : MaybeDeadCopies) {
1228 std::optional CopyOperands =
1229 isCopyInstr(*Copy, *TII, UseCopyInstr);
1230 Register Src = CopyOperands->Source->getReg();
1231 Register Def = CopyOperands->Destination->getReg();
1233 CopyDbgUsers[Copy].end());
1234
1235 MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);
1236 Copy->eraseFromParent();
1237 ++NumDeletes;
1238 }
1239
1240 MaybeDeadCopies.clear();
1241 CopyDbgUsers.clear();
1242 Tracker.clear();
1243}
1244
1249 auto &SC = SpillChain[Leader];
1250 auto &RC = ReloadChain[Leader];
1251 for (auto I = SC.rbegin(), E = SC.rend(); I != E; ++I)
1252 (*I)->dump();
1255}
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {
1296
1297
1299
1300
1301
1302
1304
1305
1307
1308 auto TryFoldSpillageCopies =
1311 assert(SC.size() == RC.size() && "Spill-reload should be paired");
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 if (SC.size() <= 2)
1323 return;
1324
1325
1327 if (CopySourceInvalid.count(Spill))
1328 return;
1329
1331 if (CopySourceInvalid.count(Reload))
1332 return;
1333
1336 if (RC->contains(Def) && RC->contains(Src))
1337 return true;
1338 }
1339 return false;
1340 };
1341
1345 if (&MO == Old)
1346 MO.setReg(New->getReg());
1347 }
1348 };
1349
1350 std::optional InnerMostSpillCopy =
1351 isCopyInstr(*SC[0], *TII, UseCopyInstr);
1352 std::optional OuterMostSpillCopy =
1353 isCopyInstr(*SC.back(), *TII, UseCopyInstr);
1354 std::optional InnerMostReloadCopy =
1355 isCopyInstr(*RC[0], *TII, UseCopyInstr);
1356 std::optional OuterMostReloadCopy =
1357 isCopyInstr(*RC.back(), *TII, UseCopyInstr);
1358 if (!CheckCopyConstraint(OuterMostSpillCopy->Source->getReg(),
1359 InnerMostSpillCopy->Source->getReg()) ||
1360 !CheckCopyConstraint(InnerMostReloadCopy->Destination->getReg(),
1361 OuterMostReloadCopy->Destination->getReg()))
1362 return;
1363
1364 SpillageChainsLength += SC.size() + RC.size();
1365 NumSpillageChains += 1;
1366 UpdateReg(SC[0], InnerMostSpillCopy->Destination,
1367 OuterMostSpillCopy->Source);
1368 UpdateReg(RC[0], InnerMostReloadCopy->Source,
1369 OuterMostReloadCopy->Destination);
1370
1371 for (size_t I = 1; I < SC.size() - 1; ++I) {
1372 SC[I]->eraseFromParent();
1373 RC[I]->eraseFromParent();
1374 NumDeletes += 2;
1375 }
1376 };
1377
1378 auto IsFoldableCopy = [this](const MachineInstr &MaybeCopy) {
1379 if (MaybeCopy.getNumImplicitOperands() > 0)
1380 return false;
1381 std::optional CopyOperands =
1382 isCopyInstr(MaybeCopy, *TII, UseCopyInstr);
1383 if (!CopyOperands)
1384 return false;
1385 Register Src = CopyOperands->Source->getReg();
1386 Register Def = CopyOperands->Destination->getReg();
1387 return Src && Def && ->regsOverlap(Src, Def) &&
1388 CopyOperands->Source->isRenamable() &&
1389 CopyOperands->Destination->isRenamable();
1390 };
1391
1394 if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))
1395 return false;
1396 std::optional SpillCopy =
1397 isCopyInstr(Spill, *TII, UseCopyInstr);
1398 std::optional ReloadCopy =
1399 isCopyInstr(Reload, *TII, UseCopyInstr);
1400 if (!SpillCopy || !ReloadCopy)
1401 return false;
1402 return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&
1403 SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();
1404 };
1405
1406 auto IsChainedCopy = [&, this](const MachineInstr &Prev,
1408 if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))
1409 return false;
1410 std::optional PrevCopy =
1411 isCopyInstr(Prev, *TII, UseCopyInstr);
1412 std::optional CurrentCopy =
1413 isCopyInstr(Current, *TII, UseCopyInstr);
1414 if (!PrevCopy || !CurrentCopy)
1415 return false;
1416 return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();
1417 };
1418
1420 std::optional CopyOperands =
1421 isCopyInstr(MI, *TII, UseCopyInstr);
1422
1423
1425 if (!CopyOperands) {
1427 if (!MO.isReg())
1428 continue;
1430 if (!Reg)
1431 continue;
1433 Tracker.findLastSeenUseInCopy(Reg.asMCReg(), *TRI);
1434 if (LastUseCopy) {
1439 CopySourceInvalid.insert(LastUseCopy);
1440 }
1441
1442
1443
1444
1445
1446
1447 if (Tracker.findLastSeenDefInCopy(MI, Reg.asMCReg(), *TRI, *TII,
1448 UseCopyInstr))
1449
1450 RegsToClobber.insert(Reg);
1451 }
1452 for (Register Reg : RegsToClobber) {
1453 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);
1455 << "\n");
1456 }
1457 continue;
1458 }
1459
1460 Register Src = CopyOperands->Source->getReg();
1461 Register Def = CopyOperands->Destination->getReg();
1462
1463 LLVM_DEBUG(dbgs() << "MCP: Searching paired spill for reload: ");
1466 Tracker.findLastSeenDefInCopy(MI, Src.asMCReg(), *TRI, *TII, UseCopyInstr);
1467 bool MaybeSpillIsChained = ChainLeader.count(MaybeSpill);
1468 if (!MaybeSpillIsChained && MaybeSpill &&
1469 IsSpillReloadPair(*MaybeSpill, MI)) {
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1505 Tracker.findLastSeenUseInCopy(Def.asMCReg(), *TRI);
1506 auto Leader = ChainLeader.find(MaybePrevReload);
1508 if (Leader == ChainLeader.end() ||
1509 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload, MI))) {
1512 "SpillChain should not have contained newly found chain");
1513 } else {
1514 assert(MaybePrevReload &&
1515 "Found a valid leader through nullptr should not happend");
1516 L = Leader->second;
1518 "Existing chain's length should be larger than zero");
1519 }
1521 "Newly found paired spill-reload should not belong to any chain "
1522 "at this point");
1523 ChainLeader.insert({MaybeSpill, L});
1525 SpillChain[L].push_back(MaybeSpill);
1526 ReloadChain[L].push_back(&MI);
1527 LLVM_DEBUG(dbgs() << "MCP: Chain " << L << " now is:\n");
1529 } else if (MaybeSpill && !MaybeSpillIsChained) {
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 LLVM_DEBUG(dbgs() << "MCP: Not paired spill-reload:\n");
1546 Tracker.clobberRegister(Src.asMCReg(), *TRI, *TII, UseCopyInstr);
1548 << "\n");
1549 }
1550 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);
1551 }
1552
1553 for (auto I = SpillChain.begin(), E = SpillChain.end(); I != E; ++I) {
1556 "Reload chain of the same leader should exist");
1557 auto &RC = ReloadChain[I->first];
1558 TryFoldSpillageCopies(SC, RC);
1559 }
1560
1561 MaybeDeadCopies.clear();
1562 CopyDbgUsers.clear();
1563 Tracker.clear();
1564}
1565
1566bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
1568 return false;
1569
1570 bool isSpillageCopyElimEnabled = false;
1573 isSpillageCopyElimEnabled =
1575 break;
1577 isSpillageCopyElimEnabled = true;
1578 break;
1580 isSpillageCopyElimEnabled = false;
1581 break;
1582 }
1583
1584 Changed = false;
1585
1589
1591 if (isSpillageCopyElimEnabled)
1592 EliminateSpillageCopies(MBB);
1593 BackwardCopyPropagateBlock(MBB);
1594 ForwardCopyPropagateBlock(MBB);
1595 }
1596
1597 return Changed;
1598}
1599
1602 return new MachineCopyPropagation(UseCopyInstr);
1603}
unsigned const MachineRegisterInfo * MRI
#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)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool test(unsigned Idx) const
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
static bool shouldExecute(unsigned CounterName)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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)
Implements a dense probed hash-table based set.
Wrapper class representing physical registers. Should be passed by value.
iterator_range< succ_iterator > successors()
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
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.
void setIsRenamable(bool Val=true)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
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 PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
iterator begin()
Get an iterator to the beginning of the SetVector.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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 const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual bool enableSpillageCopyElimination() const
Enable spillage copy elimination in MachineCopyPropagation pass.
virtual const TargetInstrInfo * getInstrInfo() const
A Use represents the edge between a Value definition and its users.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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...
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
MachineFunctionPass * createMachineCopyPropagationPass(bool UseCopyInstr)
void initializeMachineCopyPropagationPass(PassRegistry &)
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.
char & MachineCopyPropagationID
MachineCopyPropagation - This pass performs copy propagation on machine instructions.
const MachineOperand * Source
const MachineOperand * Destination