LLVM: lib/Target/Hexagon/HexagonHardwareLoops.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
53#include
54#include
55#include
56#include
57#include
58#include
59#include
60#include
61#include
62
63using namespace llvm;
64
65#define DEBUG_TYPE "hwloops"
66
67#ifndef NDEBUG
69
70
73#endif
74
75
78 cl::desc("Add a preheader to a hardware loop if one doesn't exist"));
79
80
81
82
84 cl::desc("Allow speculation of preheader "
85 "instructions"));
86
87STATISTIC(NumHWLoops, "Number of loops converted to hardware loops");
88
89namespace llvm {
90
93
94}
95
96namespace {
97
98 class CountValue;
99
106#ifndef NDEBUG
107 static int Counter;
108#endif
109
110 public:
111 static char ID;
112
114
116
118
123 }
124
125 private:
126 using LoopFeederMap = std::map<Register, MachineInstr *>;
127
128
131 EQ = 0x01,
132 NE = 0x02,
133 L = 0x04,
134 G = 0x08,
135 U = 0x40,
136 LTs = L,
138 GTs = G,
144 };
145
146 static Kind getSwappedComparison(Kind Cmp) {
147 assert ((!((Cmp & L) && (Cmp & G))) && "Malformed comparison operator");
148 if ((Cmp & L) || (Cmp & G))
149 return (Kind)(Cmp ^ (L|G));
150 return Cmp;
151 }
152
153 static Kind getNegatedComparison(Kind Cmp) {
154 if ((Cmp & L) || (Cmp & G))
155 return (Kind)((Cmp ^ (L | G)) ^ EQ);
156 if ((Cmp & NE) || (Cmp & EQ))
157 return (Kind)(Cmp ^ (EQ | NE));
158 return (Kind)0;
159 }
160
161 static bool isSigned(Kind Cmp) {
162 return (Cmp & (L | G) && !(Cmp & U));
163 }
164
165 static bool isUnsigned(Kind Cmp) {
166 return (Cmp & U);
167 }
168 };
169
170
171
172
173
174
175
176
177
178
179
180
181
184
185
186 Comparison::Kind getComparisonKind(unsigned CondOpc,
189 int64_t IVBump) const;
190
191
192
193
194 CountValue *getLoopTripCount(MachineLoop *L,
196
197
198
199
200
201
202
203
206 int64_t IVBump, Comparison::Kind Cmp) const;
207
208
209
211 bool IsInnerHWLoop) const;
212
213
214
215 bool containsInvalidInstruction(MachineLoop *L, bool IsInnerHWLoop) const;
216
217
218
219 bool convertToHardwareLoop(MachineLoop *L, bool &L0used, bool &L1used);
220
221
224
225
227
228
229
230
231
233
234
235
236
239 LoopFeederMap &LoopFeederPhi) const;
240
241
242
245 LoopFeederMap &LoopFeederPhi) const;
246
247
248
249 bool loopCountMayWrapOrUnderFlow(const MachineOperand *InitVal,
252 LoopFeederMap &LoopFeederPhi) const;
253
254
255
256
257 bool checkForImmediate(const MachineOperand &MO, int64_t &Val) const;
258
259
261 int64_t V;
262 return checkForImmediate(MO, V);
263 }
264
265
266 int64_t getImmediate(const MachineOperand &MO) const {
267 int64_t V;
268 if (!checkForImmediate(MO, V))
270 return V;
271 }
272
273
274
275
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 bool fixupInductionVariable(MachineLoop *L);
298
299
300
302 };
303
304 char HexagonHardwareLoops::ID = 0;
305#ifndef NDEBUG
306 int HexagonHardwareLoops::Counter = 0;
307#endif
308
309
310
311
312 class CountValue {
313 public:
314 enum CountValueType {
315 CV_Register,
316 CV_Immediate
317 };
318
319 private:
320 CountValueType Kind;
321 union Values {
323 Values(const Values&) = default;
324 struct {
326 unsigned Sub;
327 } R;
328 unsigned ImmVal;
329 } Contents;
330
331 public:
332 explicit CountValue(CountValueType t, Register v, unsigned u = 0) {
334 if (Kind == CV_Register) {
335 Contents.R.Reg = v;
336 Contents.R.Sub = u;
337 } else {
338 Contents.ImmVal = v;
339 }
340 }
341
342 bool isReg() const { return Kind == CV_Register; }
343 bool isImm() const { return Kind == CV_Immediate; }
344
346 assert(isReg() && "Wrong CountValue accessor");
347 return Contents.R.Reg;
348 }
349
350 unsigned getSubReg() const {
351 assert(isReg() && "Wrong CountValue accessor");
352 return Contents.R.Sub;
353 }
354
355 unsigned getImm() const {
356 assert(isImm() && "Wrong CountValue accessor");
357 return Contents.ImmVal;
358 }
359
361 if (isReg()) { OS << printReg(Contents.R.Reg, TRI, Contents.R.Sub); }
362 if (isImm()) { OS << Contents.ImmVal; }
363 }
364 };
365
366}
367
369 "Hexagon Hardware Loops", false, false)
374
376 return new HexagonHardwareLoops();
377}
378
379bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
380 LLVM_DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");
382 return false;
383
384 bool Changed = false;
385
386 MLI = &getAnalysis().getLI();
388 MDT = &getAnalysis().getDomTree();
392
393 for (auto &L : *MLI)
394 if (L->isOutermost()) {
395 bool L0Used = false;
396 bool L1Used = false;
397 Changed |= convertToHardwareLoop(L, L0Used, L1Used);
398 }
399
400 return Changed;
401}
402
403bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L,
405 int64_t &IVBump,
407 ) const {
412 if (!Header || !Preheader || !Latch || !ExitingBlock)
413 return false;
414
415
416
417 using RegisterBump = std::pair<Register, int64_t>;
418
419
420
421
422
423 using InductionMap = std::map<Register, RegisterBump>;
424
425 InductionMap IndMap;
426
428
429 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
430 I != E && I->isPHI(); ++I) {
432
433
434
435
436 for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) {
437 if (Phi->getOperand(i+1).getMBB() != Latch)
438 continue;
439
440 Register PhiOpReg = Phi->getOperand(i).getReg();
442
444
445
448 int64_t V;
449 if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
451 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
452 }
453 }
454 }
455 }
456
460 if (NotAnalyzed)
461 return false;
462
464 unsigned PredPos, PredRegFlags;
466 return false;
467
470 return false;
471
473 int64_t CmpImm = 0, CmpMask = 0;
474 bool CmpAnalyzed =
476
477
478
479 if (!CmpAnalyzed)
480 return false;
481
482
483
484 InductionMap::iterator IndMapEnd = IndMap.end();
485 InductionMap::iterator F = IndMapEnd;
486 if (CmpReg1 != 0) {
487 InductionMap::iterator F1 = IndMap.find(CmpReg1);
488 if (F1 != IndMapEnd)
489 F = F1;
490 }
491 if (CmpReg2 != 0) {
492 InductionMap::iterator F2 = IndMap.find(CmpReg2);
493 if (F2 != IndMapEnd) {
494 if (F != IndMapEnd)
495 return false;
496 F = F2;
497 }
498 }
499 if (F == IndMapEnd)
500 return false;
501
503 IVBump = F->second.second;
504 IVOp = MRI->getVRegDef(F->first);
505 return true;
506}
507
508
509HexagonHardwareLoops::Comparison::Kind
510HexagonHardwareLoops::getComparisonKind(unsigned CondOpc,
513 int64_t IVBump) const {
514 Comparison::Kind Cmp = (Comparison::Kind)0;
515 switch (CondOpc) {
516 case Hexagon::C2_cmpeq:
517 case Hexagon::C2_cmpeqi:
518 case Hexagon::C2_cmpeqp:
519 Cmp = Comparison::EQ;
520 break;
521 case Hexagon::C4_cmpneq:
522 case Hexagon::C4_cmpneqi:
523 Cmp = Comparison::NE;
524 break;
525 case Hexagon::C2_cmplt:
526 Cmp = Comparison::LTs;
527 break;
528 case Hexagon::C2_cmpltu:
529 Cmp = Comparison::LTu;
530 break;
531 case Hexagon::C4_cmplte:
532 case Hexagon::C4_cmpltei:
533 Cmp = Comparison::LEs;
534 break;
535 case Hexagon::C4_cmplteu:
536 case Hexagon::C4_cmplteui:
537 Cmp = Comparison::LEu;
538 break;
539 case Hexagon::C2_cmpgt:
540 case Hexagon::C2_cmpgti:
541 case Hexagon::C2_cmpgtp:
542 Cmp = Comparison::GTs;
543 break;
544 case Hexagon::C2_cmpgtu:
545 case Hexagon::C2_cmpgtui:
546 case Hexagon::C2_cmpgtup:
547 Cmp = Comparison::GTu;
548 break;
549 case Hexagon::C2_cmpgei:
550 Cmp = Comparison::GEs;
551 break;
552 case Hexagon::C2_cmpgeui:
553 Cmp = Comparison::GEs;
554 break;
555 default:
556 return (Comparison::Kind)0;
557 }
558 return Cmp;
559}
560
561
562
563
564
565
566
567
568CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L,
573 "Loop must have more than one incoming edge!");
575 if (PI == TopMBB->pred_end())
576 return nullptr;
578 if (PI != TopMBB->pred_end())
579 return nullptr;
580
581
582
584 if (L->contains(Backedge))
585 return nullptr;
587 } else if (->contains(Backedge))
588 return nullptr;
589
590
591
592
594 if (!ExitingBlock)
595 return nullptr;
596
598 int64_t IVBump = 0;
600 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);
601 if (!FoundIV)
602 return nullptr;
603
605
609 for (unsigned i = 1, n = IV_Phi->getNumOperands(); i < n; i += 2) {
611 if (MBB == Preheader)
612 InitialValue = &IV_Phi->getOperand(i);
613 else if (MBB == Latch)
614 IVReg = IV_Phi->getOperand(i).getReg();
615 }
616 if (!InitialValue)
617 return nullptr;
618
622 if (NotAnalyzed)
623 return nullptr;
624
626
627
628
629 assert (TB && "Exit block without a branch?");
630 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
633 bool NotAnalyzed = TII->analyzeBranch(*Latch, LTB, LFB, LCond, false);
634 if (NotAnalyzed)
635 return nullptr;
636 if (TB == Latch)
637 TB = (LTB == Header) ? LTB : LFB;
638 else
639 FB = (LTB == Header) ? LTB: LFB;
640 }
641 assert ((!FB || TB == Header || FB == Header) && "Branches not to header?");
642 if (!TB || (FB && TB != Header && FB != Header))
643 return nullptr;
644
645
646
647
648
651 unsigned PredPos, PredRegFlags;
653 return nullptr;
655 unsigned CondOpc = CondI->getOpcode();
656
658 int64_t Mask = 0, ImmValue = 0;
659 bool AnalyzedCmp =
661 if (!AnalyzedCmp)
662 return nullptr;
663
664
665
668
669
670
671
672
673
674 Comparison::Kind Cmp;
675 bool isSwapped = false;
679
680 if (Op1.isReg()) {
681 if (Op2.isImm() || Op1.getReg() == IVReg)
682 EndValue = &Op2;
683 else {
684 EndValue = &Op1;
685 isSwapped = true;
686 }
687 }
688
689 if (!EndValue)
690 return nullptr;
691
692 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);
693 if (!Cmp)
694 return nullptr;
695 if (Negated)
696 Cmp = Comparison::getNegatedComparison(Cmp);
697 if (isSwapped)
698 Cmp = Comparison::getSwappedComparison(Cmp);
699
700 if (InitialValue->isReg()) {
704 int64_t V;
705 if (!checkForImmediate(*InitialValue, V))
706 return nullptr;
707 }
709 }
710 if (EndValue->isReg()) {
714 int64_t V;
715 if (!checkForImmediate(*EndValue, V))
716 return nullptr;
717 }
719 }
720
721 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);
722}
723
724
725
726
727
728CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop,
732 int64_t IVBump,
733 Comparison::Kind Cmp) const {
734
735 if (Cmp == Comparison::EQ)
736 return nullptr;
737
738
739
740 if (Start->isReg()) {
741 const MachineInstr *StartValInstr = MRI->getVRegDef(Start->getReg());
742 if (StartValInstr && (StartValInstr->getOpcode() == Hexagon::A2_tfrsi ||
743 StartValInstr->getOpcode() == Hexagon::A2_tfrpi))
744 Start = &StartValInstr->getOperand(1);
745 }
746 if (End->isReg()) {
748 if (EndValInstr && (EndValInstr->getOpcode() == Hexagon::A2_tfrsi ||
749 EndValInstr->getOpcode() == Hexagon::A2_tfrpi))
751 }
752
753 if (!Start->isReg() && !Start->isImm())
754 return nullptr;
755 if (->isReg() &&
->isImm())
756 return nullptr;
757
758 bool CmpLess = Cmp & Comparison::L;
759 bool CmpGreater = Cmp & Comparison::G;
760 bool CmpHasEqual = Cmp & Comparison::EQ;
761
762
763 if (CmpLess && IVBump < 0)
764
765 return nullptr;
766
767 if (CmpGreater && IVBump > 0)
768
769 return nullptr;
770
771
772 LoopFeederMap LoopFeederPhi;
773
774
775
776
778 LoopFeederPhi))
779 return nullptr;
780
781 if (Start->isImm() && End->isImm()) {
782
783 int64_t StartV = Start->getImm();
784 int64_t EndV = End->getImm();
785 int64_t Dist = EndV - StartV;
786 if (Dist == 0)
787 return nullptr;
788
789 bool Exact = (Dist % IVBump) == 0;
790
791 if (Cmp == Comparison::NE) {
792 if (!Exact)
793 return nullptr;
794 if ((Dist < 0) ^ (IVBump < 0))
795 return nullptr;
796 }
797
798
799
800 if (CmpHasEqual)
801 Dist = Dist > 0 ? Dist+1 : Dist-1;
802
803
804
805
806
807 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))
808 return nullptr;
809
810
811 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump
812 : (-Dist + (-IVBump - 1)) / (-IVBump);
813 assert (Dist1 > 0 && "Fishy thing. Both operands have the same sign.");
814
816
817 if (Count > 0xFFFFFFFFULL)
818 return nullptr;
819
820 return new CountValue(CountValue::CV_Immediate, Count);
821 }
822
823
824
825
826
827
828
830 return nullptr;
831
833 assert (PH && "Should have a preheader by now");
836 if (InsertPos != PH->end())
837 DL = InsertPos->getDebugLoc();
838
839
840
841
842
843
844
845
846 if (IVBump < 0) {
848 IVBump = -IVBump;
849 }
850
851
852
853 bool RegToImm = Start->isReg() && End->isImm();
854 bool RegToReg = Start->isReg() && End->isReg();
855
856 int64_t StartV = 0, EndV = 0;
857 if (Start->isImm())
858 StartV = Start->getImm();
859 if (End->isImm())
860 EndV = End->getImm();
861
862 int64_t AdjV = 0;
863
864
865
866
867
868
869
870
871 if (CmpHasEqual) {
872
873 if (Start->isImm())
874 StartV--;
875 else if (End->isImm())
876 EndV++;
877 else
878 AdjV += 1;
879 }
880
881 if (Cmp != Comparison::NE) {
882 if (Start->isImm())
883 StartV -= (IVBump-1);
884 else if (End->isImm())
885 EndV += (IVBump-1);
886 else
887 AdjV += (IVBump-1);
888 }
889
891 unsigned SR = 0;
892 if (Start->isReg()) {
893 R = Start->getReg();
894 SR = Start->getSubReg();
895 } else {
897 SR = End->getSubReg();
898 }
900
901
902 if (!SR && RC == &Hexagon::DoubleRegsRegClass)
903 return nullptr;
905
906
908 unsigned DistSR;
909
910
911 if (Start->isImm() && StartV == 0) {
912 DistR = End->getReg();
913 DistSR = End->getSubReg();
914 } else {
915 const MCInstrDesc &SubD = RegToReg ? TII->get(Hexagon::A2_sub) :
916 (RegToImm ? TII->get(Hexagon::A2_subri) :
917 TII->get(Hexagon::A2_addi));
918 if (RegToReg || RegToImm) {
919 Register SubR = MRI->createVirtualRegister(IntRC);
921 BuildMI(*PH, InsertPos, DL, SubD, SubR);
922
923 if (RegToReg)
924 SubIB.addReg(End->getReg(), 0, End->getSubReg())
925 .addReg(Start->getReg(), 0, Start->getSubReg());
926 else
928 .addReg(Start->getReg(), 0, Start->getSubReg());
929 DistR = SubR;
930 } else {
931
932
933
935 if (EndValInstr->getOpcode() == Hexagon::A2_addi &&
939 } else {
940 Register SubR = MRI->createVirtualRegister(IntRC);
942 BuildMI(*PH, InsertPos, DL, SubD, SubR);
943 SubIB.addReg(End->getReg(), 0, End->getSubReg())
945 DistR = SubR;
946 }
947 }
948 DistSR = 0;
949 }
950
951
953 unsigned AdjSR;
954
955 if (AdjV == 0) {
956 AdjR = DistR;
957 AdjSR = DistSR;
958 } else {
959
960 Register AddR = MRI->createVirtualRegister(IntRC);
961 MCInstrDesc const &AddD = TII->get(Hexagon::A2_addi);
962 BuildMI(*PH, InsertPos, DL, AddD, AddR)
963 .addReg(DistR, 0, DistSR)
965
966 AdjR = AddR;
967 AdjSR = 0;
968 }
969
970
972 unsigned CountSR;
973
974 if (IVBump == 1) {
975 CountR = AdjR;
976 CountSR = AdjSR;
977 } else {
978
979 unsigned Shift = Log2_32(IVBump);
980
981
982 Register LsrR = MRI->createVirtualRegister(IntRC);
983 const MCInstrDesc &LsrD = TII->get(Hexagon::S2_lsr_i_r);
984 BuildMI(*PH, InsertPos, DL, LsrD, LsrR)
985 .addReg(AdjR, 0, AdjSR)
987
988 CountR = LsrR;
989 CountSR = 0;
990 }
991
992 return new CountValue(CountValue::CV_Register, CountR, CountSR);
993}
994
995
996bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,
997 bool IsInnerHWLoop) const {
998
999
1000 if (MI->getDesc().isCall())
1002
1003
1004 using namespace Hexagon;
1005
1006 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };
1007 static const Register Regs1[] = { LC1, SA1 };
1008 auto CheckRegs = IsInnerHWLoop ? ArrayRef(Regs01) : ArrayRef(Regs1);
1009 for (Register R : CheckRegs)
1010 if (MI->modifiesRegister(R, TRI))
1011 return true;
1012
1013 return false;
1014}
1015
1016
1017
1018bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L,
1019 bool IsInnerHWLoop) const {
1024 if (isInvalidLoopOperation(&MI, IsInnerHWLoop)) {
1025 LLVM_DEBUG(dbgs() << "\nCannot convert to hw_loop due to:";
1027 return true;
1028 }
1029 }
1030 }
1031 return false;
1032}
1033
1034
1035
1036
1037
1038bool HexagonHardwareLoops::isDead(const MachineInstr *MI,
1040
1043 continue;
1044
1046 if (MRI->use_nodbg_empty(Reg))
1047 continue;
1048
1050
1051
1052
1053
1054 use_nodbg_iterator I = MRI->use_nodbg_begin(Reg);
1055 use_nodbg_iterator End = MRI->use_nodbg_end();
1056 if (std::next(I) != End || ->getParent()->isPHI())
1057 return false;
1058
1061 if (!OPO.isReg() || !OPO.isDef())
1062 continue;
1063
1064 Register OPReg = OPO.getReg();
1065 use_nodbg_iterator nextJ;
1066 for (use_nodbg_iterator J = MRI->use_nodbg_begin(OPReg);
1067 J != End; J = nextJ) {
1068 nextJ = std::next(J);
1071
1072
1074 return false;
1075 }
1076 }
1078 }
1079
1080
1081 return true;
1082}
1083
1084void HexagonHardwareLoops::removeIfDead(MachineInstr *MI) {
1085
1086
1090
1091
1092
1093
1096 continue;
1098
1099
1104 continue;
1107 }
1108 }
1109
1110 MI->eraseFromParent();
1111 for (unsigned i = 0; i < DeadPhis.size(); ++i)
1112 DeadPhis[i]->eraseFromParent();
1113 }
1114}
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L,
1125 bool &RecL0used,
1126 bool &RecL1used) {
1127
1128 assert(L->getHeader() && "Loop without a header?");
1129
1130 bool Changed = false;
1131 bool L0Used = false;
1132 bool L1Used = false;
1133
1134
1136 Changed |= convertToHardwareLoop(I, RecL0used, RecL1used);
1137 L0Used |= RecL0used;
1138 L1Used |= RecL1used;
1139 }
1140
1141
1142 if (Changed && L0Used && L1Used)
1143 return Changed;
1144
1145 unsigned LOOP_i;
1146 unsigned LOOP_r;
1147 unsigned ENDLOOP;
1148
1149
1150
1151
1152 unsigned IsInnerHWLoop = 1;
1153
1154 if (L0Used) {
1155 LOOP_i = Hexagon::J2_loop1i;
1156 LOOP_r = Hexagon::J2_loop1r;
1157 ENDLOOP = Hexagon::ENDLOOP1;
1158 IsInnerHWLoop = 0;
1159 } else {
1160 LOOP_i = Hexagon::J2_loop0i;
1161 LOOP_r = Hexagon::J2_loop0r;
1162 ENDLOOP = Hexagon::ENDLOOP0;
1163 }
1164
1165#ifndef NDEBUG
1166
1168 if (Limit >= 0) {
1170 return false;
1171 Counter++;
1172 }
1173#endif
1174
1175
1176 if (containsInvalidInstruction(L, IsInnerHWLoop))
1177 return false;
1178
1180
1181 if (!LastMBB)
1182 return false;
1183
1185 if (LastI == LastMBB->end())
1186 return false;
1187
1188
1189 if (!fixupInductionVariable(L))
1190 return false;
1191
1192
1193
1195 if (!Preheader) {
1196 Preheader = createPreheaderForLoop(L);
1197 if (!Preheader)
1198 return false;
1199 }
1200
1202
1204
1205 CountValue *TripCount = getLoopTripCount(L, OldInsts);
1206 if (!TripCount)
1207 return false;
1208
1209
1210 if (TripCount->isReg()) {
1211
1212
1213 MachineInstr *TCDef = MRI->getVRegDef(TripCount->getReg());
1215 if (!MDT->dominates(BBDef, Preheader))
1216 return false;
1217 }
1218
1219
1223 if (ExitingBlock != L->getLoopLatch()) {
1226
1228 return false;
1229
1230 if (L->contains(TB))
1231 LoopStart = TB;
1232 else if (L->contains(FB))
1233 LoopStart = FB;
1234 else
1235 return false;
1236 }
1237 else
1238 LoopStart = TopBlock;
1239
1240
1241 LLVM_DEBUG(dbgs() << "Change to hardware loop at "; L->dump());
1243 if (InsertPos != Preheader->end())
1244 DL = InsertPos->getDebugLoc();
1245
1246 if (TripCount->isReg()) {
1247
1248 Register CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1249 BuildMI(*Preheader, InsertPos, DL, TII->get(TargetOpcode::COPY), CountReg)
1250 .addReg(TripCount->getReg(), 0, TripCount->getSubReg());
1251
1252 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_r)).addMBB(LoopStart)
1254 } else {
1255 assert(TripCount->isImm() && "Expecting immediate value for trip count");
1256
1257
1258
1259 int64_t CountImm = TripCount->getImm();
1261 Register CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1262 BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::A2_tfrsi), CountReg)
1264 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_r))
1266 } else
1267 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_i))
1269 }
1270
1271
1273
1274
1275 DebugLoc LastIDL = LastI->getDebugLoc();
1276 BuildMI(*LastMBB, LastI, LastIDL, TII->get(ENDLOOP)).addMBB(LoopStart);
1277
1278
1279
1280
1281 if (LastI->getOpcode() == Hexagon::J2_jumpt ||
1282 LastI->getOpcode() == Hexagon::J2_jumpf) {
1283
1285 LastI = LastMBB->erase(LastI);
1286 if (->contains(BranchTarget)) {
1287 if (LastI != LastMBB->end())
1288 LastI = LastMBB->erase(LastI);
1291 }
1292 } else {
1293
1294 LastMBB->erase(LastI);
1295 }
1296 delete TripCount;
1297
1298
1299
1300 for (unsigned i = 0; i < OldInsts.size(); ++i)
1301 removeIfDead(OldInsts[i]);
1302
1303 ++NumHWLoops;
1304
1305
1306
1307
1308 if (L0Used)
1309 RecL1used = true;
1310 else
1311 RecL0used = true;
1312
1313 return true;
1314}
1315
1316bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI,
1318 assert (BumpI != CmpI && "Bump and compare in the same instruction?");
1319
1322 return false;
1323
1325
1326
1327 for (instr_iterator I(BumpI), E = BB->instr_end(); I != E; ++I)
1328 if (&*I == CmpI)
1329 return true;
1330
1331
1333 bool FoundBump = false;
1334 instr_iterator CmpIt = CmpI->getIterator(), NextIt = std::next(CmpIt);
1335 for (instr_iterator I = NextIt, E = BB->instr_end(); I != E; ++I) {
1337 for (unsigned i = 0, n = In->getNumOperands(); i < n; ++i) {
1340 if (MO.getReg() == PredR)
1341 return false;
1342 }
1343 }
1344
1345 if (In == BumpI) {
1347 FoundBump = true;
1348 break;
1349 }
1350 }
1351 assert (FoundBump && "Cannot determine instruction order");
1352 return FoundBump;
1353}
1354
1355
1356
1357
1358
1359
1363 LoopFeederMap &LoopFeederPhi) const {
1364 if (LoopFeederPhi.find(MO->getReg()) == LoopFeederPhi.end()) {
1367
1369 return false;
1371 LoopFeederPhi.insert(std::make_pair(MO->getReg(), Def));
1372 return true;
1373 } else
1374
1375 return false;
1376}
1377
1378
1379
1380bool HexagonHardwareLoops::phiMayWrapOrUnderflow(
1382 MachineLoop *L, LoopFeederMap &LoopFeederPhi) const {
1383 assert(Phi->isPHI() && "Expecting a Phi.");
1384
1385
1386 for (int i = 1, n = Phi->getNumOperands(); i < n; i += 2)
1387 if (isLoopFeeder(L, MBB, Phi, &(Phi->getOperand(i)), LoopFeederPhi))
1388 if (loopCountMayWrapOrUnderFlow(&(Phi->getOperand(i)), EndVal,
1389 Phi->getParent(), L, LoopFeederPhi))
1390 return true;
1391 return false;
1392}
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(
1411 LoopFeederMap &LoopFeederPhi) const {
1412
1413 if (!InitVal->isReg())
1414 return false;
1415
1416 if (!EndVal->isImm())
1417 return false;
1418
1419
1420
1421 int64_t Imm;
1422 if (checkForImmediate(*InitVal, Imm))
1423 return (EndVal->getImm() == Imm);
1424
1426
1427
1428 if (.isVirtual())
1429 return true;
1430
1432 if (!Def)
1433 return true;
1434
1435
1436
1437 if (Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal, Def->getParent(),
1438 L, LoopFeederPhi))
1439 return false;
1440 if (Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(Def->getOperand(1)),
1441 EndVal, Def->getParent(),
1442 L, LoopFeederPhi))
1443 return false;
1444
1445
1446
1447
1449 E = MRI->use_instr_nodbg_end(); I != E; ++I) {
1452 int64_t CmpMask = 0, CmpValue = 0;
1453
1455 continue;
1456
1460 continue;
1461
1462 Comparison::Kind Cmp =
1463 getComparisonKind(MI->getOpcode(), nullptr, nullptr, 0);
1464 if (Cmp == 0)
1465 continue;
1467 Cmp = Comparison::getNegatedComparison(Cmp);
1468 if (CmpReg2 != 0 && CmpReg2 == Reg)
1469 Cmp = Comparison::getSwappedComparison(Cmp);
1470
1471
1472 if (Comparison::isSigned(Cmp))
1473 return false;
1474
1475
1476
1477
1478 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)
1479 return false;
1480 }
1481
1482
1483
1484
1485 if (->isCopy() &&
->isPHI())
1486 return false;
1487
1488 return true;
1489}
1490
1491bool HexagonHardwareLoops::checkForImmediate(const MachineOperand &MO,
1492 int64_t &Val) const {
1493 if (MO.isImm()) {
1495 return true;
1496 }
1497 if (!MO.isReg())
1498 return false;
1499
1500
1501
1502
1503 int64_t TV;
1504
1506 if (.isVirtual())
1507 return false;
1509 unsigned DOpc = DI->getOpcode();
1510 switch (DOpc) {
1511 case TargetOpcode::COPY:
1512 case Hexagon::A2_tfrsi:
1513 case Hexagon::A2_tfrpi:
1514 case Hexagon::CONST32:
1515 case Hexagon::CONST64:
1516
1517
1518
1519 if (!checkForImmediate(DI->getOperand(1), TV))
1520 return false;
1521 break;
1522 case Hexagon::A2_combineii:
1523 case Hexagon::A4_combineir:
1524 case Hexagon::A4_combineii:
1525 case Hexagon::A4_combineri:
1526 case Hexagon::A2_combinew: {
1529 int64_t V1, V2;
1530 if (!checkForImmediate(S1, V1) || !checkForImmediate(S2, V2))
1531 return false;
1532 TV = V2 | (static_cast<uint64_t>(V1) << 32);
1533 break;
1534 }
1535 case TargetOpcode::REG_SEQUENCE: {
1538 int64_t V1, V3;
1539 if (!checkForImmediate(S1, V1) || !checkForImmediate(S3, V3))
1540 return false;
1543 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)
1544 TV = V1 | (V3 << 32);
1545 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)
1546 TV = V3 | (V1 << 32);
1547 else
1549 break;
1550 }
1551
1552 default:
1553 return false;
1554 }
1555
1556
1557
1559 case Hexagon::isub_lo:
1560 Val = TV & 0xFFFFFFFFULL;
1561 break;
1562 case Hexagon::isub_hi:
1563 Val = (TV >> 32) & 0xFFFFFFFFULL;
1564 break;
1565 default:
1566 Val = TV;
1567 break;
1568 }
1569 return true;
1570}
1571
1572void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) {
1573 if (MO.isImm()) {
1575 return;
1576 }
1577
1581
1583 Register NewR = MRI->createVirtualRegister(RC);
1588}
1589
1590bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
1594
1595 if (!(Header && Latch && ExitingBlock))
1596 return false;
1597
1598
1599
1600 using RegisterBump = std::pair<Register, int64_t>;
1601 using RegisterInduction = std::pair<Register, RegisterBump>;
1602 using RegisterInductionSet = std::set;
1603
1604
1605 RegisterInductionSet IndRegs;
1606
1607
1608
1609
1611
1612 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
1613 I != E && I->isPHI(); ++I) {
1615
1616
1617 for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) {
1618 if (Phi->getOperand(i+1).getMBB() != Latch)
1619 continue;
1620
1621 Register PhiReg = Phi->getOperand(i).getReg();
1623
1625
1626
1629 int64_t V;
1630 if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {
1632 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));
1633 }
1634 }
1635 }
1636 }
1637
1638 if (IndRegs.empty())
1639 return false;
1640
1643
1645 if (NotAnalyzed || Cond.empty())
1646 return false;
1647
1648 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {
1651 bool NotAnalyzed = TII->analyzeBranch(*Latch, LTB, LFB, LCond, false);
1652 if (NotAnalyzed)
1653 return false;
1654
1655
1656
1657 if (TB == Latch)
1658 TB = (LTB == Header) ? LTB : LFB;
1659 else
1660 FB = (LTB == Header) ? LTB : LFB;
1661 }
1662 if (TB != Header) {
1663 if (FB != Header) {
1664
1665 return false;
1666 }
1667
1668
1669
1670
1671
1672
1674 return false;
1675 }
1676
1677
1678
1679
1680
1681
1682 unsigned CSz = Cond.size();
1683 if (CSz != 1 && CSz != 2)
1684 return false;
1685
1687 return false;
1688
1691
1693 return false;
1694
1697
1698
1699
1700
1701
1703 if (MO.isReg()) {
1704
1705
1707 continue;
1708 if (MO.isUse()) {
1709 if (!isImmediate(MO)) {
1711 continue;
1712 }
1713
1714 if (CmpImmOp)
1715 return false;
1716 CmpImmOp = &MO;
1717 }
1718 } else if (MO.isImm()) {
1719 if (CmpImmOp)
1720 return false;
1721 CmpImmOp = &MO;
1722 }
1723 }
1724
1725 if (CmpRegs.empty())
1726 return false;
1727
1728
1729 for (RegisterInductionSet::iterator I = IndRegs.begin(), E = IndRegs.end();
1731
1732
1733
1734 if (CmpRegs.count(I->first))
1735 return true;
1736
1737
1738
1739
1740 const RegisterBump &RB = I->second;
1741 if (CmpRegs.count(RB.first)) {
1742 if (!CmpImmOp) {
1743
1744
1749
1750 for (unsigned i = 1, n = PredDef->getNumOperands(); i < n; ++i) {
1752 if (MO.isReg() && MO.getReg() == RB.first) {
1754 << ") = " << *(MRI->getVRegDef(I->first)));
1755 if (IndI)
1756 return false;
1757
1758 IndI = MRI->getVRegDef(I->first);
1759 IndMO = &MO;
1760 } else if (MO.isReg()) {
1762 << ") = " << *(MRI->getVRegDef(MO.getReg())));
1763 if (nonIndI)
1764 return false;
1765
1766 nonIndI = MRI->getVRegDef(MO.getReg());
1767 nonIndMO = &MO;
1768 }
1769 }
1770 if (IndI && nonIndI &&
1771 nonIndI->getOpcode() == Hexagon::A2_addi &&
1774 bool Order = orderBumpCompare(IndI, PredDef);
1775 if (Order) {
1778 return true;
1779 }
1780 }
1781 return false;
1782 }
1783
1784
1785
1786 Comparison::Kind Cmp =
1787 getComparisonKind(PredDef->getOpcode(), nullptr, nullptr, 0);
1788 if (!Cmp || Comparison::isUnsigned(Cmp))
1789 return false;
1790
1791
1792
1793
1794 int64_t CmpImm = getImmediate(*CmpImmOp);
1795 int64_t V = RB.second;
1796
1797 if (((V > 0) && (CmpImm > INT64_MAX - V)) ||
1798 ((V < 0) && (CmpImm < INT64_MIN - V)))
1799 return false;
1800 CmpImm += V;
1801
1802
1803
1806 return false;
1807
1808
1809
1811 bool Order = orderBumpCompare(BumpI, PredDef);
1812 if (!Order)
1813 return false;
1814
1815
1816 setImmediate(*CmpImmOp, CmpImm);
1818 if (MO.isReg() && MO.getReg() == RB.first) {
1820 return true;
1821 }
1822 }
1823 }
1824 }
1825
1826 return false;
1827}
1828
1829
1833 return TmpPH;
1835 return nullptr;
1836
1842
1843#ifndef NDEBUG
1845 return nullptr;
1846#endif
1847
1848 if (!Latch || !ExitingBlock || Header->hasAddressTaken())
1849 return nullptr;
1850
1852
1853
1854
1855 using MBBVector = std::vector<MachineBasicBlock *>;
1856
1857 MBBVector Preds(Header->pred_begin(), Header->pred_end());
1860
1862 return nullptr;
1863
1866 if (NotAnalyzed)
1867 return nullptr;
1868 }
1869
1871 MF->insert(Header->getIterator(), NewPH);
1872
1873 if (Header->pred_size() > 2) {
1874
1875
1876
1877
1878
1879 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
1880 I != E && I->isPHI(); ++I) {
1882
1885 NewPH->insert(NewPH->end(), NewPN);
1886
1889 Register NewPR = MRI->createVirtualRegister(RC);
1891
1892
1893
1894 for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) {
1898 if (PredB == Latch)
1899 continue;
1900
1905 }
1906
1907
1908
1909 for (int i = PN->getNumOperands()-2; i > 0; i -= 2) {
1911 if (PredB != Latch) {
1914 }
1915 }
1918 }
1919 } else {
1920 assert(Header->pred_size() == 2);
1921
1922
1923
1924
1925
1926
1927 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();
1928 I != E && I->isPHI(); ++I) {
1930 for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) {
1932 if (MO.getMBB() != Latch)
1934 }
1935 }
1936 }
1937
1938
1939
1940
1943
1944 TB = FB = nullptr;
1945
1947 if (PB != Latch) {
1950 (void)NotAnalyzed;
1951 assert (!NotAnalyzed && "Should be analyzable!");
1952 if (TB != Header && (Tmp2.empty() || FB != Header))
1954 PB->ReplaceUsesOfBlockWith(Header, NewPH);
1955 }
1956 }
1957
1958
1959
1960 TB = FB = nullptr;
1961 bool LatchNotAnalyzed = TII->analyzeBranch(*Latch, TB, FB, Tmp2, false);
1962 (void)LatchNotAnalyzed;
1963 assert (!LatchNotAnalyzed && "Should be analyzable!");
1964 if (!TB && !FB)
1966
1967
1970
1971 MachineLoop *ParentLoop = L->getParentLoop();
1972 if (ParentLoop)
1974
1975
1976 if (MDT) {
1979 MDT->addNewBlock(NewPH, DHN->getBlock());
1981 }
1982 }
1983 }
1984
1985 return NewPH;
1986}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
static cl::opt< bool > HWCreatePreheader("hexagon-hwloop-preheader", cl::Hidden, cl::init(true), cl::desc("Add a preheader to a hardware loop if one doesn't exist"))
static cl::opt< bool > SpecPreheader("hwloop-spec-preheader", cl::Hidden, cl::desc("Allow speculation of preheader " "instructions"))
static cl::opt< std::string > PHFn("hexagon-hwloop-phfn", cl::Hidden, cl::init(""))
static cl::opt< int > HWLoopLimit("hexagon-max-hwloop", cl::Hidden, cl::init(-1))
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
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.
AnalysisUsage & addRequired()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Base class for the actual dominator tree node.
DomTreeNodeBase * getIDom() const
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
FunctionPass class - This class is used to implement most global optimizations.
bool doesNotReturn(const MachineInstr &CallMI) const
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
bool getPredReg(ArrayRef< MachineOperand > Cond, Register &PredReg, unsigned &PredRegPos, unsigned &PredRegFlags) const
bool isValidOffset(unsigned Opcode, int Offset, const TargetRegisterInfo *TRI, bool Extend=true) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const override
For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Insert branch code into the end of the specified MachineBasicBlock.
bool predOpcodeHasNot(ArrayRef< MachineOperand > Cond) const
bool isExtendable(const MachineInstr &MI) const
const HexagonInstrInfo * getInstrInfo() const override
const HexagonRegisterInfo * getRegisterInfo() const override
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
Represents a single loop in the control flow graph.
Describe properties that are true of each instruction in the target description file.
bool isAdd() const
Return true if the instruction is an add instruction.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator pred_iterator
Instructions::iterator instr_iterator
pred_iterator pred_begin()
instr_iterator instr_end()
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
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...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
iterator_range< mop_iterator > operands()
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setMBB(MachineBasicBlock *MBB)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
defusechain_iterator - This class provides iterator support for machine operands in the function that...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_iterator< true, false, true, true, false, false > use_nodbg_iterator
use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the specified register,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
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.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
@ PD
PD - Prefix code for packed double precision vector floating point operations performed in the SSE re...
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
FunctionPass * createHexagonHardwareLoops()
void initializeHexagonHardwareLoopsPass(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.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...