LLVM: lib/Target/Hexagon/HexagonVLIWPacketizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
50#include
51#include
52#include
53
54using namespace llvm;
55
56#define DEBUG_TYPE "packets"
57
60 cl::desc("Disable Hexagon packetizer pass"));
61
64 cl::desc("Allow slot1 store and slot0 load"));
65
68 cl::desc("Allow non-solo packetization of volatile memory references"));
69
72 cl::desc("Generate all instruction with TC"));
73
76 cl::desc("Disable vector double new-value-stores"));
77
79
80namespace llvm {
81
84
85}
86
87namespace {
88
90 public:
91 static char ID;
92
93 HexagonPacketizer(bool Min = false)
95
105 }
106
109
112 MachineFunctionProperties::Property::NoVRegs);
113 }
114
115 private:
118 const bool Minimal = false;
119 };
120
121}
122
123char HexagonPacketizer::ID = 0;
124
126 "Hexagon Packetizer", false, false)
133
138 Minimal(Minimal) {
141
142 addMutation(std::make_uniqueHexagonSubtarget::UsrOverflowMutation());
143 addMutation(std::make_uniqueHexagonSubtarget::HVXMemLatencyMutation());
144 addMutation(std::make_uniqueHexagonSubtarget::BankConflictMutation());
145}
146
147
151 for (auto &MO : FirstI.operands()) {
152 if (!MO.isReg() || !MO.isDef())
153 continue;
156 return true;
157 }
158 return false;
159}
160
161
167 else
168 InsertPt = std::next(BundleIt).getInstrIterator();
169
171
172
173 assert(MI.isBundledWithPred());
174 if (MI.isBundledWithSucc()) {
177 } else {
178
179
180
181 MI.unbundleFromPred();
182 }
183 B.splice(InsertPt, &B, MI.getIterator());
184
185
188 unsigned Size = 0;
189 for (++I; I != E && I->isBundledWithPred(); ++I)
191
192
193
194 if (Size > 1)
195 return BundleIt;
196
197
199 MachineInstr &SingleI = *BundleIt->getNextNode();
202 BundleIt->eraseFromParent();
203 return NextIt;
204}
205
206bool HexagonPacketizer::runOnMachineFunction(MachineFunction &MF) {
207
209 MachineFunctionProperties::Property::FailsVerification);
210
213 HRI = HST.getRegisterInfo();
214 auto &MLI = getAnalysis().getLI();
215 auto *AA = &getAnalysis().getAAResults();
216 auto *MBPI =
217 &getAnalysis().getMBPI();
218
220 HII->genAllInsnTimingClasses(MF);
221
222
223 bool MinOnly = Minimal || DisablePacketizer || !HST.usePackets() ||
226
227
228 assert(Packetizer.getResourceTracker() && "Empty DFA table!");
229
230
231
232
233
234
235
236
237
240 if (MI.isKill())
241 MB.erase(&MI);
242 }
243
244
245 if (HST.isTinyCoreWithDuplex())
246 HII->translateInstrsForDup(MF, true);
247
248
249 for (auto &MB : MF) {
250 auto Begin = MB.begin(), End = MB.end();
251 while (Begin != End) {
252
253
255 while (RB != End && HII->isSchedulingBoundary(*RB, &MB, MF))
256 ++RB;
257
258
260 while (RE != End && !HII->isSchedulingBoundary(*RE, &MB, MF))
261 ++RE;
262
263 if (RE != End)
264 ++RE;
265
266 if (RB != End)
267 Packetizer.PacketizeMIs(&MB, RB, RE);
268
269 Begin = RE;
270 }
271 }
272
273
274 if (HST.isTinyCoreWithDuplex())
275 HII->translateInstrsForDup(MF, false);
276
277 Packetizer.unpacketizeSoloInstrs(MF);
278 return true;
279}
280
281
282
286}
287
290}
291
292
293
297 if (Reserve && Avail)
300 return Avail;
301}
302
304 SDep::Kind DepType, unsigned DepReg) {
305
306 if (DepReg == HRI->getRARegister())
307 return true;
308
309 if (HII->isDeallocRet(MI))
311 return true;
312
313
314
315
316
317
320 if (MO.isReg() && MO.getReg() == DepReg && !MO.isImplicit())
321 return true;
322 }
323
324 return false;
325}
326
330}
331
333 return MI.getOpcode() == Hexagon::J2_jump;
334}
335
337 switch (MI.getOpcode()) {
338 case Hexagon::Y2_barrier:
339 return true;
340 }
341 return false;
342}
343
345 return MI.getDesc().isTerminator() || MI.getDesc().isCall();
346}
347
348
352 for (auto *CSR = TRI->getCalleeSavedRegs(&MF); CSR && *CSR; ++CSR)
353 if (MI.modifiesRegister(*CSR, TRI))
354 return true;
355 return false;
356}
357
358
359
362
363
364 if (NewRC == &Hexagon::PredRegsRegClass) {
365 if (HII->isHVXVec(MI) && MI.mayStore())
366 return false;
367 return HII->isPredicated(MI) && HII->getDotNewPredOp(MI, nullptr) > 0;
368 }
369
370 return HII->mayBeNewStore(MI);
371}
372
373
374
375
380 int CurOpcode = HII->getDotCurOp(MI);
381 MI.setDesc(HII->get(CurOpcode));
382 return true;
383}
384
388 LLVM_DEBUG(dbgs() << "Cleanup packet has "; BI->dump(););
389 if (HII->isDotCurInst(*BI)) {
390 MI = BI;
391 continue;
392 }
393 if (MI) {
394 for (auto &MO : BI->operands())
395 if (MO.isReg() && MO.getReg() == MI->getOperand(0).getReg())
396 return;
397 }
398 }
399 if ()
400 return;
401
402 MI->setDesc(HII->get(HII->getNonDotCurOp(*MI)));
404}
405
406
410 if (!HII->isHVXVec(MI))
411 return false;
412 if (!HII->isHVXVec(*MII))
413 return false;
414
415
416 if (HII->isDotCurInst(MI) && !HII->mayBeCurLoad(MI))
417 return false;
418
419 if (!HII->mayBeCurLoad(MI))
420 return false;
421
422
424 return false;
425
426
428 dbgs() << "in packet\n";);
431 dbgs() << "Checking CUR against ";
432 MJ.dump();
433 });
434 Register DestReg = MI.getOperand(0).getReg();
435 bool FoundMatch = false;
436 for (auto &MO : MJ.operands())
437 if (MO.isReg() && MO.getReg() == DestReg)
438 FoundMatch = true;
439 if (!FoundMatch)
440 return false;
441
442
443
447 return false;
448 }
449
451
452 return true;
453}
454
455
456
457
462 int NewOpcode;
463 if (RC == &Hexagon::PredRegsRegClass)
464 NewOpcode = HII->getDotNewPredOp(MI, MBPI);
465 else
466 NewOpcode = HII->getDotNewOp(MI);
467 MI.setDesc(HII->get(NewOpcode));
468 return true;
469}
470
472 int NewOpcode = HII->getDotOldOp(MI);
473 MI.setDesc(HII->get(NewOpcode));
474 return true;
475}
476
478 unsigned Opc = MI.getOpcode();
479 switch (Opc) {
480 case Hexagon::S2_storerd_io:
481 case Hexagon::S2_storeri_io:
482 case Hexagon::S2_storerh_io:
483 case Hexagon::S2_storerb_io:
484 break;
485 default:
487 }
491 if (HII->isValidOffset(Opc, NewOff, HRI)) {
492 Off.setImm(NewOff);
493 return true;
494 }
495 return false;
496}
497
499 unsigned Opc = MI.getOpcode();
500 switch (Opc) {
501 case Hexagon::S2_storerd_io:
502 case Hexagon::S2_storeri_io:
503 case Hexagon::S2_storerh_io:
504 case Hexagon::S2_storerb_io:
505 break;
506 default:
508 }
512}
513
514
515
520
521 unsigned BPI, OPI;
522 if (!HII->getBaseAndOffsetPosition(MI, BPI, OPI))
523 return false;
524 unsigned BPJ, OPJ;
525 if (!HII->getBaseAndOffsetPosition(MJ, BPJ, OPJ))
526 return false;
527 Register Reg = MI.getOperand(BPI).getReg();
529 return false;
530
531
532
533 for (const auto &PI : SUI->Preds)
535 (PI.getKind() != SDep::Data || PI.getReg() != Reg))
536 return false;
537 int Incr;
538 if (!HII->getIncrementValue(MJ, Incr))
539 return false;
540
541 int64_t Offset = MI.getOperand(OPI).getImm();
542 if (!HII->isValidOffset(MI.getOpcode(), Offset+Incr, HRI))
543 return false;
544
545 MI.getOperand(OPI).setImm(Offset + Incr);
546 ChangedOffset = Offset;
547 return true;
548}
549
550
551
553 unsigned BP, OP;
554 if (!HII->getBaseAndOffsetPosition(MI, BP, OP))
555 llvm_unreachable("Unable to find base and offset operands.");
556 MI.getOperand(OP).setImm(ChangedOffset);
557}
558
564
565
566
574}
575
579#ifndef NDEBUG
580
581
582
584 for (auto &MO : MI.operands())
585 if (MO.isReg() && MO.isDef())
586 DefRegsSet.insert(MO.getReg());
587
588 for (auto &MO : MI.operands())
589 if (MO.isReg() && MO.isUse() && DefRegsSet.count(MO.getReg()))
590 return MO;
591#else
592 if (MI.mayLoad()) {
594
595 assert(Op1.isReg() && "Post increment operand has be to a register.");
596 return Op1;
597 }
598 if (MI.getDesc().mayStore()) {
600
601 assert(Op0.isReg() && "Post increment operand has be to a register.");
602 return Op0;
603 }
604#endif
605
606 llvm_unreachable("mayLoad or mayStore not set for Post Increment operation");
607}
608
609
611
612 return MI.getOperand(MI.getNumOperands()-1);
613}
614
616 unsigned Opc = MI.getOpcode();
617 switch (Opc) {
618 case Hexagon::L4_loadrd_ap:
619 case Hexagon::L4_loadrb_ap:
620 case Hexagon::L4_loadrh_ap:
621 case Hexagon::L4_loadrub_ap:
622 case Hexagon::L4_loadruh_ap:
623 case Hexagon::L4_loadri_ap:
624 return true;
625 }
626 return false;
627}
628
631 return MI.getOperand(1);
632}
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
652 const MachineInstr &PacketMI, unsigned DepReg) {
653
654 if (!HII->mayBeNewStore(MI))
655 return false;
656
657
659 if (Val.isReg() && Val.getReg() != DepReg)
660 return false;
661
663
664
666
667 if (PacketRC == &Hexagon::DoubleRegsRegClass)
668 return false;
669
670
671
675 return false;
676 }
677
678
679
680 if (HII->isPostIncrement(MI) &&
682 return false;
683 }
684
685 if (HII->isPostIncrement(PacketMI) && PacketMI.mayLoad() &&
687
688
689
690
691
692 return false;
693 }
694
696 return false;
697
698
699
700 if (HII->isPredicated(PacketMI)) {
701 if (!HII->isPredicated(MI))
702 return false;
703
704
705
706 unsigned predRegNumSrc = 0;
707 unsigned predRegNumDst = 0;
709
710
711 for (auto &MO : PacketMI.operands()) {
712 if (!MO.isReg())
713 continue;
714 predRegNumSrc = MO.getReg();
715 predRegClass = HRI->getMinimalPhysRegClass(predRegNumSrc);
716 if (predRegClass == &Hexagon::PredRegsRegClass)
717 break;
718 }
719 assert((predRegClass == &Hexagon::PredRegsRegClass) &&
720 "predicate register not found in a predicated PacketMI instruction");
721
722
723 for (auto &MO : MI.operands()) {
724 if (!MO.isReg())
725 continue;
726 predRegNumDst = MO.getReg();
727 predRegClass = HRI->getMinimalPhysRegClass(predRegNumDst);
728 if (predRegClass == &Hexagon::PredRegsRegClass)
729 break;
730 }
731 assert((predRegClass == &Hexagon::PredRegsRegClass) &&
732 "predicate register not found in a predicated MI instruction");
733
734
735
736
737
738
739
740
741
742 if (predRegNumDst != predRegNumSrc ||
743 HII->isDotNewInst(PacketMI) != HII->isDotNewInst(MI) ||
745 return false;
746 }
747
748
749
750
751
752
753
754
755
756 unsigned StartCheck = 0;
757
761
762
763
764
765 if (&TempMI != &PacketMI && !StartCheck)
766 continue;
767
768 StartCheck = 1;
769 if (&TempMI == &PacketMI)
770 continue;
771
772 for (auto &MO : MI.operands())
774 return false;
775 }
776
777
778
779
780
781
782
783 if (!HII->isPostIncrement(MI)) {
784 for (unsigned opNum = 0; opNum < MI.getNumOperands()-1; opNum++) {
787 return false;
788 }
789 }
790
791
792
793
794
795 for (auto &MO : PacketMI.operands()) {
796 if (MO.isRegMask() && MO.clobbersPhysReg(DepReg))
797 return false;
798 if (!MO.isReg() || !MO.isDef() || !MO.isImplicit())
799 continue;
801 if (R == DepReg || HRI->isSuperRegister(DepReg, R))
802 return false;
803 }
804
805
806
807
808
809
810 for (auto &MO : MI.operands()) {
811 if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.getReg() == DepReg)
812 return false;
813 }
814
815
816 return true;
817}
818
819
821 const SUnit *PacketSU, unsigned DepReg,
823 if (!HII->mayBeNewStore(MI))
824 return false;
825
826
829 return true;
830
831
832
833 return false;
834}
835
837 unsigned DepReg) {
838 for (auto &MO : I.operands()) {
839 if (CheckDef && MO.isRegMask() && MO.clobbersPhysReg(DepReg))
840 return true;
841 if (!MO.isReg() || MO.getReg() != DepReg || !MO.isImplicit())
842 continue;
843 if (CheckDef == MO.isDef())
844 return true;
845 }
846 return false;
847}
848
849
853
854 if (HII->isDotNewInst(MI) && !HII->mayBeNewStore(MI))
855 return false;
856
858 return false;
859
861
862
864 return false;
865
866
867
869 return false;
870
871
872
875 return false;
876
880 return false;
881
882
883 if (RC == &Hexagon::PredRegsRegClass)
884 return HII->predCanBeUsedAsDotNew(PI, DepReg);
885
886 if (RC != &Hexagon::PredRegsRegClass && !HII->mayBeNewStore(MI))
887 return false;
888
889
890
891 int NewOpcode = (RC != &Hexagon::PredRegsRegClass) ? HII->getDotNewOp(MI) :
892 HII->getDotNewPredOp(MI, MBPI);
897 if (!ResourcesAvailable)
898 return false;
899
900
902 return false;
903
904 return true;
905}
906
907
908
909
910
911
912
913
914
915
916
917
918
919
921 unsigned DepReg) {
923
925
926 if (!HII->isPredicated(*I))
927 continue;
928
929
931
932
933
934
935 if (PacketSU->isSucc(PacketSUDep)) {
936 for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) {
937 auto &Dep = PacketSU->Succs[i];
938 if (Dep.getSUnit() == PacketSUDep && Dep.getKind() == SDep::Anti &&
939 Dep.getReg() == DepReg)
940 return true;
941 }
942 }
943 }
944
945 return false;
946}
947
948
951
952
954
955 for (auto &Op : MI.operands()) {
956 if (Op.isReg() && Op.getReg() && Op.isUse() &&
957 Hexagon::PredRegsRegClass.contains(Op.getReg()))
958 return Op.getReg();
959 }
960
962 return 0;
963}
964
965
966
969
970
973 return false;
974
975
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
995
997
998
999 if (PacketSU->isSucc(SU)) {
1000 for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) {
1001 auto Dep = PacketSU->Succs[i];
1002
1003
1004
1005
1006 if (Dep.getSUnit() == SU && Dep.getKind() == SDep::Data &&
1007 Hexagon::PredRegsRegClass.contains(Dep.getReg())) {
1008
1009
1010
1011
1012
1014 return false;
1015 }
1016 }
1017 }
1018 }
1019
1020
1021
1022
1023
1026 return PReg1 == PReg2 &&
1027 Hexagon::PredRegsRegClass.contains(PReg1) &&
1028 Hexagon::PredRegsRegClass.contains(PReg2) &&
1030 HII->isDotNewInst(MI1) == HII->isDotNewInst(MI2);
1031}
1032
1033
1036 PromotedToDotNew = false;
1037 GlueToNewValueJump = false;
1038 GlueAllocframeStore = false;
1039 FoundSequentialDependence = false;
1041}
1042
1043
1046 if (MI.isDebugInstr())
1047 return true;
1048
1049 if (MI.isCFIInstruction())
1050 return false;
1051
1052
1053 if (MI.isInlineAsm())
1054 return false;
1055
1056 if (MI.isImplicitDef())
1057 return false;
1058
1059
1060
1064}
1065
1067
1068 if (MI.isBundle())
1069 return true;
1070
1071 if (MI.isEHLabel() || MI.isCFIInstruction())
1072 return true;
1073
1074
1075
1076
1077
1078
1080 return true;
1081
1083 return true;
1084
1085 if (HII->isSolo(MI))
1086 return true;
1087
1088 if (MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER ||
1089 MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT ||
1090 MI.getOpcode() == Hexagon::PATCHABLE_TAIL_CALL)
1091 return true;
1092
1093 if (MI.getOpcode() == Hexagon::A2_nop)
1094 return true;
1095
1096 return false;
1097}
1098
1099
1100
1101
1102
1103
1104
1105
1111 return true;
1112
1113
1114
1116 return true;
1117
1118
1119
1120
1121
1122 if (MI.isInlineAsm())
1125
1126
1128 return true;
1129
1130 switch (MI.getOpcode()) {
1131 case Hexagon::S2_storew_locked:
1132 case Hexagon::S4_stored_locked:
1133 case Hexagon::L2_loadw_locked:
1134 case Hexagon::L4_loadd_locked:
1135 case Hexagon::Y2_dccleana:
1136 case Hexagon::Y2_dccleaninva:
1137 case Hexagon::Y2_dcinva:
1138 case Hexagon::Y2_dczeroa:
1139 case Hexagon::Y4_l2fetch:
1140 case Hexagon::Y5_l2fetch: {
1141
1142
1143
1144 unsigned TJ = HII.getType(MJ);
1148 return true;
1149 break;
1150 }
1151 default:
1152 break;
1153 }
1154
1155
1156
1157 return false;
1158}
1159
1160
1164}
1165
1170 if (MI.isBundle())
1171 BundleIt = MI.getIterator();
1172 if (.isInsideBundle())
1173 continue;
1174
1175
1176
1177
1178
1179
1180
1181 bool InsertBeforeBundle;
1182 if (MI.isInlineAsm())
1184 else if (MI.isDebugInstr())
1185 InsertBeforeBundle = true;
1186 else
1187 continue;
1188
1189 BundleIt = moveInstrOut(MI, BundleIt, InsertBeforeBundle);
1190 }
1191 }
1192}
1193
1194
1196 unsigned Opc = MI.getOpcode();
1197 switch (Opc) {
1198 case Hexagon::Y2_barrier:
1199 case Hexagon::Y2_dcfetchbo:
1200 case Hexagon::Y4_l2fetch:
1201 case Hexagon::Y5_l2fetch:
1202 return true;
1203 }
1204 return false;
1205}
1206
1209
1210
1211
1212 if (I.isCall() || J.isCall())
1213 return false;
1214 if (HII->isPredicated(I) || HII->isPredicated(J))
1215 return false;
1216
1217 BitVector DeadDefs(Hexagon::NUM_TARGET_REGS);
1218 for (auto &MO : I.operands()) {
1219 if (!MO.isReg() || !MO.isDef() || !MO.isDead())
1220 continue;
1221 DeadDefs[MO.getReg()] = true;
1222 }
1223
1224 for (auto &MO : J.operands()) {
1225 if (!MO.isReg() || !MO.isDef() || !MO.isDead())
1226 continue;
1228 if (R != Hexagon::USR_OVF && DeadDefs[R])
1229 return true;
1230 }
1231 return false;
1232}
1233
1236
1237
1238 if ((HII->isSaveCalleeSavedRegsCall(I) &&
1240 (HII->isSaveCalleeSavedRegsCall(J) &&
1242 return true;
1243
1244
1246 return true;
1247
1248
1249
1250
1251 auto isBadForLoopN = [this] (const MachineInstr &MI) -> bool {
1252 if (MI.isCall() || HII->isDeallocRet(MI) || HII->isNewValueJump(MI))
1253 return true;
1254 if (HII->isPredicated(MI) && HII->isPredicatedNew(MI) && HII->isJumpR(MI))
1255 return true;
1256 return false;
1257 };
1258
1259 if (HII->isLoopN(I) && isBadForLoopN(J))
1260 return true;
1261 if (HII->isLoopN(J) && isBadForLoopN(I))
1262 return true;
1263
1264
1265
1266 return HII->isDeallocRet(I) &&
1268}
1269
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1284 if (!OpJ.isRegMask())
1285 continue;
1286 assert((J.isCall() || HII->isTailCall(J)) && "Regmask on a non-call");
1288 if (OpI.isReg()) {
1289 if (OpJ.clobbersPhysReg(OpI.getReg()))
1290 return true;
1291 } else if (OpI.isRegMask()) {
1292
1293 return true;
1294 }
1295 }
1296 }
1297 return false;
1298}
1299
1303 bool StoreI = I.mayStore(), StoreJ = J.mayStore();
1304 if ((SysI && StoreJ) || (SysJ && StoreI))
1305 return true;
1306
1307 if (StoreI && StoreJ) {
1308 if (HII->isNewValueInst(J) || HII->isMemOp(J) || HII->isMemOp(I))
1309 return true;
1310 } else {
1311
1312
1313 bool MopStI = HII->isMemOp(I) || StoreI;
1314 bool MopStJ = HII->isMemOp(J) || StoreJ;
1315 if (MopStI && MopStJ)
1316 return true;
1317 }
1318
1319 return (StoreJ && HII->isDeallocRet(I)) || (StoreI && HII->isDeallocRet(J));
1320}
1321
1322
1323
1324
1329
1330
1332 IgnoreDepMIs.clear();
1333
1335
1336
1338
1340 return false;
1341
1344 return false;
1345
1346
1347
1348
1349
1352 return false;
1353
1354
1355
1356
1359 return false;
1360
1361
1363 ++NextMII;
1364 if (NextMII != I.getParent()->end() && HII->isNewValueJump(*NextMII)) {
1366
1367 bool secondRegMatch = false;
1370
1371 if (NOp1.isReg() && I.getOperand(0).getReg() == NOp1.getReg())
1372 secondRegMatch = true;
1373
1375
1376 if (PI->isCall()) {
1378 break;
1379 }
1380
1381
1382
1383
1384
1385
1386
1387
1388 if (PI->getOpcode() == Hexagon::S2_allocframe || PI->mayStore() ||
1389 HII->isLoopN(*PI)) {
1391 break;
1392 }
1393
1394 const MachineOperand &OpR = secondRegMatch ? NOp0 : NOp1;
1395 if (OpR.isReg() && PI->modifiesRegister(OpR.getReg(), HRI)) {
1397 break;
1398 }
1399 }
1400
1401 GlueToNewValueJump = true;
1403 return false;
1404 }
1405
1406
1407 if (!SUJ->isSucc(SUI))
1408 return true;
1409
1410 for (unsigned i = 0; i < SUJ->Succs.size(); ++i) {
1411 if (FoundSequentialDependence)
1412 break;
1413
1414 if (SUJ->Succs[i].getSUnit() != SUI)
1415 continue;
1416
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433 unsigned DepReg = 0;
1436 DepReg = SUJ->Succs[i].getReg();
1437 RC = HRI->getMinimalPhysRegClass(DepReg);
1438 }
1439
1440 if (I.isCall() || HII->isJumpR(I) || I.isReturn() || HII->isTailCall(I)) {
1442 continue;
1444 continue;
1445 }
1446
1450 continue;
1451 }
1452
1453
1454 if (DepType == SDep::Data && HII->isDotCurInst(J)) {
1455 if (HII->isHVXVec(I))
1456 continue;
1457 }
1458
1459
1463 PromotedToDotNew = true;
1465 FoundSequentialDependence = true;
1466 continue;
1467 }
1468 }
1469 if (HII->isNewValueJump(I))
1470 continue;
1471 }
1472
1473
1474
1475 if (HII->isPredicated(I) && HII->isPredicated(J) &&
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489 auto Itr = find(IgnoreDepMIs, &J);
1490 if (Itr != IgnoreDepMIs.end()) {
1492 return false;
1493 }
1494 IgnoreDepMIs.push_back(&I);
1495 continue;
1496 }
1497
1498
1499
1502 continue;
1503
1504
1505
1506 if (I.isConditionalBranch() && DepType != SDep::Data &&
1508 continue;
1509
1511 FoundSequentialDependence = true;
1512 break;
1513 }
1514
1515
1516
1517
1518
1519
1520
1524 if (OrdRefs) {
1525 FoundSequentialDependence = true;
1526 break;
1527 }
1528 }
1529
1531 bool LoadI = I.mayLoad(), StoreI = I.mayStore();
1532 bool NVStoreJ = HII->isNewValueStore(J);
1533 bool NVStoreI = HII->isNewValueStore(I);
1534 bool IsVecJ = HII->isHVXVec(J);
1535 bool IsVecI = HII->isHVXVec(I);
1536
1537
1538
1539 if (LoadJ && LoadI && HII->isPureSlot0(J)) {
1540 FoundSequentialDependence = true;
1541 break;
1542 }
1543
1545 ((LoadJ && StoreI && !NVStoreI) ||
1546 (StoreJ && LoadI && !NVStoreJ)) &&
1547 (J.getOpcode() != Hexagon::S2_allocframe &&
1548 I.getOpcode() != Hexagon::S2_allocframe) &&
1549 (J.getOpcode() != Hexagon::L2_deallocframe &&
1550 I.getOpcode() != Hexagon::L2_deallocframe) &&
1551 (!HII->isMemOp(J) && !HII->isMemOp(I)) && (!IsVecJ && !IsVecI))
1553 else
1554 if (StoreJ && LoadI && alias(J, I)) {
1555 FoundSequentialDependence = true;
1556 break;
1557 }
1558
1559 if (!StoreJ)
1560 if (!LoadJ || (!LoadI && !StoreI)) {
1561
1562
1563 FoundSequentialDependence = true;
1564 break;
1565 }
1566
1567
1568
1569
1570 continue;
1571 }
1572
1573
1574
1575
1576
1578 unsigned Opc = I.getOpcode();
1579 switch (Opc) {
1580 case Hexagon::S2_storerd_io:
1581 case Hexagon::S2_storeri_io:
1582 case Hexagon::S2_storerh_io:
1583 case Hexagon::S2_storerb_io:
1585
1586
1587
1588
1590 if (GlueAllocframeStore)
1591 continue;
1592 }
1593 break;
1594 default:
1595 break;
1596 }
1597 }
1598
1599
1600
1601
1602
1603
1604
1606
1607
1608
1610 if (Op.isReg() && Op.isDef()) {
1613 continue;
1614 } else if (.isRegMask()) {
1615
1616 continue;
1617 }
1618 FoundSequentialDependence = true;
1619 break;
1620 }
1621 }
1622
1623
1624
1625
1626
1627
1628
1630 FoundSequentialDependence = true;
1631 break;
1632 }
1633 }
1634
1635 if (FoundSequentialDependence) {
1637 return false;
1638 }
1639
1640 return true;
1641}
1642
1647
1649
1651 return true;
1652
1653
1654
1655 if (PromotedToDotNew)
1657
1659
1660
1661
1662 if (GlueAllocframeStore) {
1664 GlueAllocframeStore = false;
1665 }
1666
1669
1670 if (GlueToNewValueJump) {
1671
1672
1673 GlueToNewValueJump = false;
1674 return false;
1675 }
1676
1677 if (!Coexist)
1678 return false;
1679
1681 FoundSequentialDependence = false;
1683 return true;
1684 }
1685
1686 return false;
1687}
1688
1689
1691 bool FoundLoad = false;
1692 bool FoundStore = false;
1693
1695 unsigned Opc = MJ->getOpcode();
1696 if (Opc == Hexagon::S2_allocframe || Opc == Hexagon::L2_deallocframe)
1697 continue;
1698 if (HII->isMemOp(*MJ))
1699 continue;
1700 if (MJ->mayLoad())
1701 FoundLoad = true;
1702 if (MJ->mayStore() && !HII->isNewValueStore(*MJ))
1703 FoundStore = true;
1704 }
1705 return FoundLoad && FoundStore;
1706}
1707
1708
1713
1715 PacketStalls = false;
1716 PacketStallCycles = 0;
1717 }
1719 PacketStallCycles = std::max(PacketStallCycles, calcStall(MI));
1720
1721 if (MI.isImplicitDef()) {
1722
1723
1725 return MII;
1726 }
1728
1729 bool ExtMI = HII->isExtended(MI) || HII->isConstExtended(MI);
1730 bool Good = true;
1731
1732 if (GlueToNewValueJump) {
1734
1735
1736
1737
1739 if (ExtMI)
1741
1742 bool ExtNvjMI = HII->isExtended(NvjMI) || HII->isConstExtended(NvjMI);
1743 if (Good) {
1746 else
1747 Good = false;
1748 }
1749 if (Good && ExtNvjMI)
1751
1752 if (!Good) {
1756 if (ExtMI) {
1759 }
1762 if (ExtNvjMI) {
1765 }
1766 }
1769 return MII;
1770 }
1771
1775 if (PromotedToDotNew)
1777 if (GlueAllocframeStore) {
1779 GlueAllocframeStore = false;
1780 }
1783 }
1784
1786 return MII;
1787}
1788
1791
1794 dbgs() << "Finalizing packet:\n";
1795 unsigned Idx = 0;
1796 for (MachineInstr *MI : CurrentPacketMIs) {
1797 unsigned R = ResourceTracker->getUsedResources(Idx++);
1798 dbgs() << " * [res:0x" << utohexstr(R) << "] " << *MI;
1799 }
1800 }
1801 });
1802
1803 bool memShufDisabled = getmemShufDisabled();
1804 if (memShufDisabled && !foundLSInPacket()) {
1805 setmemShufDisabled(false);
1806 LLVM_DEBUG(dbgs() << " Not added to NoShufPacket\n");
1807 }
1808 memShufDisabled = getmemShufDisabled();
1809
1810 OldPacketMIs.clear();
1813 for (auto &I : make_range(HII->expandVGatherPseudo(*MI), NextMI))
1814 OldPacketMIs.push_back(&I);
1815 }
1816 CurrentPacketMIs.clear();
1817
1818 if (OldPacketMIs.size() > 1) {
1822 auto BundleMII = std::prev(FirstMI);
1823 if (memShufDisabled)
1824 HII->setBundleNoShuf(BundleMII);
1825
1826 setmemShufDisabled(false);
1827 }
1828
1829 PacketHasDuplex = false;
1830 PacketHasSLOT0OnlyInsn = false;
1831 ResourceTracker->clearResources();
1833}
1834
1836 if (Minimal)
1837 return false;
1838
1840 return false;
1841
1842
1843
1844 auto &HST = MI.getParent()->getParent()->getSubtarget<HexagonSubtarget>();
1845
1846
1847
1848
1849
1850
1851
1852 if (HST.isTinyCoreWithDuplex() && CurrentPacketMIs.size() > 0 &&
1853 !PacketHasDuplex) {
1854
1856 PacketHasSLOT0OnlyInsn |= HII->isPureSlot0(*MJ);
1857
1858 int Opcode = HII->getDuplexOpcode(MI, false);
1859 if (Opcode >= 0) {
1860
1862 if (HII->isDuplexPair(MI, *MJ) && !PacketHasSLOT0OnlyInsn) {
1863 PacketHasDuplex = true;
1864 return true;
1865 }
1866 }
1867
1868
1870 MIRef.setDesc(HII->get(Opcode));
1872 }
1873 }
1874
1875 return true;
1876}
1877
1878
1880
1881
1882
1883
1884
1885
1886
1887 if (!OldPacketMIs.empty()) {
1888 auto *OldBB = OldPacketMIs.front()->getParent();
1889 auto *ThisBB = I.getParent();
1891 return 0;
1892 }
1893
1895 if (!SUI)
1896 return 0;
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1921 for (auto &Pred : SUI->Preds)
1922 if (Pred.getSUnit() == SUJ)
1923 if ((Pred.getLatency() == 0 && Pred.isAssignedRegDep()) ||
1924 HII->isNewValueJump(I) || HII->isToBeScheduledASAP(*J, I))
1925 return 0;
1926 }
1927
1928
1929
1930 for (auto *J : OldPacketMIs) {
1932 for (auto &Pred : SUI->Preds)
1933 if (Pred.getSUnit() == SUJ && Pred.getLatency() > 1)
1934 return Pred.getLatency();
1935 }
1936
1937 return 0;
1938}
1939
1943 return false;
1944
1945 if (PacketStalls)
1946 return Latency > PacketStallCycles;
1947 return true;
1948}
1949
1950
1951
1952
1953
1955 return new HexagonPacketizer(Minimal);
1956}
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines the DenseSet and SmallDenseSet classes.
cl::opt< bool > ScheduleInlineAsm("hexagon-sched-inline-asm", cl::Hidden, cl::init(false), cl::desc("Do not consider inline-asm a scheduling/" "packetization boundary."))
#define HEXAGON_LRFP_SIZE
static bool cannotCoexistAsymm(const MachineInstr &MI, const MachineInstr &MJ, const HexagonInstrInfo &HII)
static bool isDirectJump(const MachineInstr &MI)
static MachineBasicBlock::iterator moveInstrOut(MachineInstr &MI, MachineBasicBlock::iterator BundleIt, bool Before)
static bool isRegDependence(const SDep::Kind DepType)
static const MachineOperand & getStoreValueOperand(const MachineInstr &MI)
static cl::opt< bool > EnableGenAllInsnClass("enable-gen-insn", cl::Hidden, cl::desc("Generate all instruction with TC"))
static bool isControlFlow(const MachineInstr &MI)
hexagon Hexagon Packetizer
static cl::opt< bool > DisableVecDblNVStores("disable-vecdbl-nv-stores", cl::Hidden, cl::desc("Disable vector double new-value-stores"))
static PredicateKind getPredicateSense(const MachineInstr &MI, const HexagonInstrInfo *HII)
Returns true if an instruction is predicated on p0 and false if it's predicated on !...
static unsigned getPredicatedRegister(MachineInstr &MI, const HexagonInstrInfo *QII)
Gets the predicate register of a predicated instruction.
static cl::opt< bool > DisablePacketizer("disable-packetizer", cl::Hidden, cl::desc("Disable Hexagon packetizer pass"))
static cl::opt< bool > Slot1Store("slot1-store-slot0-load", cl::Hidden, cl::init(true), cl::desc("Allow slot1 store and slot0 load"))
static cl::opt< bool > PacketizeVolatiles("hexagon-packetize-volatiles", cl::Hidden, cl::init(true), cl::desc("Allow non-solo packetization of volatile memory references"))
cl::opt< bool > ScheduleInlineAsm
static bool hasWriteToReadDep(const MachineInstr &FirstI, const MachineInstr &SecondI, const TargetRegisterInfo *TRI)
static bool doesModifyCalleeSavedReg(const MachineInstr &MI, const TargetRegisterInfo *TRI)
Returns true if the instruction modifies a callee-saved register.
static bool isLoadAbsSet(const MachineInstr &MI)
static const MachineOperand & getAbsSetOperand(const MachineInstr &MI)
static const MachineOperand & getPostIncrementOperand(const MachineInstr &MI, const HexagonInstrInfo *HII)
static bool isImplicitDependency(const MachineInstr &I, bool CheckDef, unsigned DepReg)
static bool isSchedBarrier(const MachineInstr &MI)
static bool isSystemInstr(const MachineInstr &MI)
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const InstrItineraryData * getInstrItins() const
bool canReserveResources(const MCInstrDesc *MID)
void reserveResources(const MCInstrDesc *MID)
This class represents an Operation in the Expression.
Implements a dense probed hash-table based set.
Dependence - This class represents a dependence between two memory memory references in a function.
FunctionPass class - This class is used to implement most global optimizations.
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
bool isHVXMemWithAIndirect(const MachineInstr &I, const MachineInstr &J) const
bool isRestrictNoSlot1Store(const MachineInstr &MI) const
bool isPureSlot0(const MachineInstr &MI) const
bool isPostIncrement(const MachineInstr &MI) const override
Return true for post-incremented instructions.
uint64_t getType(const MachineInstr &MI) const
bool isPredicatedTrue(const MachineInstr &MI) const
bool isNewValueStore(const MachineInstr &MI) const
bool arePredicatesComplements(MachineInstr &MI1, MachineInstr &MI2)
bool updateOffset(SUnit *SUI, SUnit *SUJ)
Return true if we can update the offset in MI so that MI and MJ can be packetized together.
void endPacket(MachineBasicBlock *MBB, MachineBasicBlock::iterator MI) override
bool isCallDependent(const MachineInstr &MI, SDep::Kind DepType, unsigned DepReg)
bool promoteToDotCur(MachineInstr &MI, SDep::Kind DepType, MachineBasicBlock::iterator &MII, const TargetRegisterClass *RC)
bool promoteToDotNew(MachineInstr &MI, SDep::Kind DepType, MachineBasicBlock::iterator &MII, const TargetRegisterClass *RC)
bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override
bool canPromoteToDotCur(const MachineInstr &MI, const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII, const TargetRegisterClass *RC)
void useCalleesSP(MachineInstr &MI)
bool demoteToDotOld(MachineInstr &MI)
bool cannotCoexist(const MachineInstr &MI, const MachineInstr &MJ)
const MachineLoopInfo * MLI
bool isSoloInstruction(const MachineInstr &MI) override
bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override
void initPacketizerState() override
bool hasControlDependence(const MachineInstr &I, const MachineInstr &J)
bool restrictingDepExistInPacket(MachineInstr &, unsigned)
bool producesStall(const MachineInstr &MI)
void undoChangedOffset(MachineInstr &MI)
Undo the changed offset.
bool hasDualStoreDependence(const MachineInstr &I, const MachineInstr &J)
unsigned int calcStall(const MachineInstr &MI)
bool canPromoteToDotNew(const MachineInstr &MI, const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII, const TargetRegisterClass *RC)
bool canPromoteToNewValue(const MachineInstr &MI, const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII)
bool ignorePseudoInstruction(const MachineInstr &MI, const MachineBasicBlock *MBB) override
void unpacketizeSoloInstrs(MachineFunction &MF)
const MachineBranchProbabilityInfo * MBPI
A handle to the branch probability pass.
bool shouldAddToPacket(const MachineInstr &MI) override
bool canReserveResourcesForConstExt()
bool useCallersSP(MachineInstr &MI)
bool canPromoteToNewValueStore(const MachineInstr &MI, const MachineInstr &PacketMI, unsigned DepReg)
bool tryAllocateResourcesForConstExt(bool Reserve)
void setmemShufDisabled(bool val)
void reserveResourcesForConstExt()
MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override
bool hasDeadDependence(const MachineInstr &I, const MachineInstr &J)
bool isNewifiable(const MachineInstr &MI, const TargetRegisterClass *NewRC)
bool hasRegMaskDependence(const MachineInstr &I, const MachineInstr &J)
Register getStackRegister() const
Register getFrameRegister(const MachineFunction &MF) const override
const HexagonInstrInfo * getInstrInfo() const override
bool hasV60OpsOnly() const
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Describe properties that are true of each instruction in the target description file.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Instructions::iterator instr_iterator
Instructions::const_iterator const_instr_iterator
Analysis pass which computes a MachineDominatorTree.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
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.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void deleteMachineInstr(MachineInstr *MI)
DeleteMachineInstr - Delete the given MachineInstr.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
instr_iterator getInstrIterator() const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
bool isImplicitDef() const
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool isBarrier(QueryType Type=AnyInBundle) const
Returns true if the specified instruction stops control flow from executing the instruction immediate...
bool isCall(QueryType Type=AnyInBundle) const
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
void unbundleFromPred()
Break bundle above this instruction.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
iterator_range< mop_iterator > operands()
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
bool isBundledWithSucc() const
Return true if this instruction is part of a bundle, and it is not the last instruction in the bundle...
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
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.
Kind
These are the different kinds of scheduling dependencies.
@ Output
A register output-dependence (aka WAW).
@ Order
Any other ordering dependency.
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
Scheduling unit. This is a node in the scheduling DAG.
bool isSucc(const SUnit *N) const
Tests if node N is a successor of this node.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
StringRef - Represent a constant reference to a string, i.e.
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.
bool alias(const MachineInstr &MI1, const MachineInstr &MI2, bool UseTBAA=true) const
std::vector< MachineInstr * > CurrentPacketMIs
std::map< MachineInstr *, SUnit * > MIToSUnit
DFAPacketizer * ResourceTracker
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
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...
void initializeHexagonPacketizerPass(PassRegistry &)
FunctionPass * createHexagonPacketizer(bool Minimal)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FuncUnits getUnits() const
Returns the choice of FUs.