LLVM: lib/Target/ARM/ARMBaseInstrInfo.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
63#include
64#include
65#include
66#include
67#include
68#include
69#include
70
71using namespace llvm;
72
73#define DEBUG_TYPE "arm-instrinfo"
74
75#define GET_INSTRINFO_CTOR_DTOR
76#include "ARMGenInstrInfo.inc"
77
78
86
88
89
90 { ARM::VMLAS, ARM::VMULS, ARM::VADDS, false, false },
91 { ARM::VMLSS, ARM::VMULS, ARM::VSUBS, false, false },
92 { ARM::VMLAD, ARM::VMULD, ARM::VADDD, false, false },
93 { ARM::VMLSD, ARM::VMULD, ARM::VSUBD, false, false },
94 { ARM::VNMLAS, ARM::VNMULS, ARM::VSUBS, true, false },
95 { ARM::VNMLSS, ARM::VMULS, ARM::VSUBS, true, false },
96 { ARM::VNMLAD, ARM::VNMULD, ARM::VSUBD, true, false },
97 { ARM::VNMLSD, ARM::VMULD, ARM::VSUBD, true, false },
98
99
100 { ARM::VMLAfd, ARM::VMULfd, ARM::VADDfd, false, false },
101 { ARM::VMLSfd, ARM::VMULfd, ARM::VSUBfd, false, false },
102 { ARM::VMLAfq, ARM::VMULfq, ARM::VADDfq, false, false },
103 { ARM::VMLSfq, ARM::VMULfq, ARM::VSUBfq, false, false },
104 { ARM::VMLAslfd, ARM::VMULslfd, ARM::VADDfd, false, true },
105 { ARM::VMLSslfd, ARM::VMULslfd, ARM::VSUBfd, false, true },
106 { ARM::VMLAslfq, ARM::VMULslfq, ARM::VADDfq, false, true },
107 { ARM::VMLSslfq, ARM::VMULslfq, ARM::VSUBfq, false, true },
108};
109
113 Subtarget(STI) {
114 for (unsigned i = 0, e = std::size(ARM_MLxTable); i != e; ++i) {
115 if (!MLxEntryMap.insert(std::make_pair(ARM_MLxTable[i].MLxOpc, i)).second)
117 MLxHazardOpcodes.insert(ARM_MLxTable[i].AddSubOpc);
118 MLxHazardOpcodes.insert(ARM_MLxTable[i].MulOpc);
119 }
120}
121
122
123
127 if (usePreRAHazardRecognizer()) {
129 static_cast<const ARMSubtarget *>(STI)->getInstrItineraryData();
131 }
133}
134
135
136
137
141
142
143
144
145
146
149 std::make_unique(DAG, 0x4, true));
150
151
152
153
155 MHR->AddHazardRecognizer(std::unique_ptr(BHR));
156 return MHR;
157}
158
159
164
165 if (Subtarget.isThumb2() || Subtarget.hasVFP2Base())
167
169 if (BHR)
170 MHR->AddHazardRecognizer(std::unique_ptr(BHR));
171 return MHR;
172}
173
174
175
176
177
178
179
180
181
186 bool AllowModify) const {
187 TBB = nullptr;
188 FBB = nullptr;
189
191 if (I == MBB.instr_begin())
192 return false;
193 --I;
194
195
196
197 while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
198
199
200
201 bool CantAnalyze = false;
202
203
204
205 while (I->isDebugInstr() || ->isTerminator() ||
207 I->getOpcode() == ARM::t2DoLoopStartTP){
208 if (I == MBB.instr_begin())
209 return false;
210 --I;
211 }
212
215
216
217 CantAnalyze = true;
219 TBB = I->getOperand(0).getMBB();
221
222 if (.empty())
223 return true;
224
225 assert(!FBB && "FBB should have been null.");
226 FBB = TBB;
227 TBB = I->getOperand(0).getMBB();
228 Cond.push_back(I->getOperand(1));
229 Cond.push_back(I->getOperand(2));
230 } else if (I->isReturn()) {
231
232 CantAnalyze = true;
233 } else if (I->getOpcode() == ARM::t2LoopEnd &&
234 MBB.getParent()
237 if (.empty())
238 return true;
239 FBB = TBB;
240 TBB = I->getOperand(1).getMBB();
242 Cond.push_back(I->getOperand(0));
244 } else {
245
246 return true;
247 }
248
249
250
255 I->isReturn())) {
256
257 Cond.clear();
258 FBB = nullptr;
259
260
261
262 if (AllowModify) {
264 while (DI != MBB.instr_end()) {
266 ++DI;
267
269 continue;
271 }
272 }
273 }
274
275 if (CantAnalyze) {
276
277
278
279
282 TBB && MBB.isLayoutSuccessor(TBB))
284 return true;
285 }
286
287 if (I == MBB.instr_begin())
288 return false;
289
290 --I;
291 }
292
293
294
295 return false;
296}
297
299 int *BytesRemoved) const {
300 assert(!BytesRemoved && "code size not handled");
301
304 return 0;
305
308 return 0;
309
310
311 I->eraseFromParent();
312
314
315 if (I == MBB.begin()) return 1;
316 --I;
318 return 1;
319
320
321 I->eraseFromParent();
322 return 2;
323}
324
330 int *BytesAdded) const {
331 assert(!BytesAdded && "code size not handled");
336 ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
338
339
340 assert(TBB && "insertBranch must not be told to insert a fallthrough");
342 "ARM branch conditions have two or three components!");
343
344
345
346 if (!FBB) {
347 if (Cond.empty()) {
350 else
352 } else if (Cond.size() == 2) {
357 } else
359 return 1;
360 }
361
362
363 if (Cond.size() == 2)
368 else if (Cond.size() == 3)
372 else
374 return 2;
375}
376
379 if (Cond.size() == 2) {
382 return false;
383 }
384 return true;
385}
386
388 if (MI.isBundle()) {
391 while (++I != E && I->isInsideBundle()) {
392 int PIdx = I->findFirstPredOperandIdx();
393 if (PIdx != -1 && I->getOperand(PIdx).getImm() != ARMCC::AL)
394 return true;
395 }
396 return false;
397 }
398
399 int PIdx = MI.findFirstPredOperandIdx();
400 return PIdx != -1 && MI.getOperand(PIdx).getImm() != ARMCC::AL;
401}
402
406
407
408 std::string GenericComment =
410 if (!GenericComment.empty())
411 return GenericComment;
412
413
414 if (.isImm())
415 return std::string();
416
417
418
419 int FirstPredOp = MI.findFirstPredOperandIdx();
420 if (FirstPredOp != (int) OpIdx)
421 return std::string();
422
423 std::string CC = "CC::";
425 return CC;
426}
427
430 unsigned Opc = MI.getOpcode();
436 return true;
437 }
438
439 int PIdx = MI.findFirstPredOperandIdx();
440 if (PIdx != -1) {
443 MI.getOperand(PIdx+1).setReg(Pred[1].getReg());
444
445
446
449 assert(MCID.operands()[1].isOptionalDef() &&
450 "CPSR def isn't expected operand");
451 assert((MI.getOperand(1).isDead() ||
452 MI.getOperand(1).getReg() != ARM::CPSR) &&
453 "if conversion tried to stop defining used CPSR");
454 MI.getOperand(1).setReg(ARM::NoRegister);
455 }
456
457 return true;
458 }
459 return false;
460}
461
464 if (Pred1.size() > 2 || Pred2.size() > 2)
465 return false;
466
469 if (CC1 == CC2)
470 return true;
471
472 switch (CC1) {
473 default:
474 return false;
476 return true;
485 }
486}
487
489 std::vector &Pred,
490 bool SkipDead) const {
491 bool Found = false;
493 bool ClobbersCPSR = MO.isRegMask() && MO.clobbersPhysReg(ARM::CPSR);
494 bool IsCPSR = MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR;
495 if (ClobbersCPSR || IsCPSR) {
496
497
498
501 SkipDead)
502 continue;
503
504 Pred.push_back(MO);
505 Found = true;
506 }
507 }
508
509 return Found;
510}
511
513 for (const auto &MO : MI.operands())
514 if (MO.isReg() && MO.getReg() == ARM::CPSR && MO.isDef() && !MO.isDead())
515 return true;
516 return false;
517}
518
520 switch (MI->getOpcode()) {
521 default: return true;
522 case ARM::tADC:
523 case ARM::tADDi3:
524 case ARM::tADDi8:
525 case ARM::tADDrr:
526 case ARM::tAND:
527 case ARM::tASRri:
528 case ARM::tASRrr:
529 case ARM::tBIC:
530 case ARM::tEOR:
531 case ARM::tLSLri:
532 case ARM::tLSLrr:
533 case ARM::tLSRri:
534 case ARM::tLSRrr:
535 case ARM::tMUL:
536 case ARM::tMVN:
537 case ARM::tORR:
538 case ARM::tROR:
539 case ARM::tRSB:
540 case ARM::tSBC:
541 case ARM::tSUBi3:
542 case ARM::tSUBi8:
543 case ARM::tSUBrr:
545 }
546}
547
548
549
550
552 if (.isPredicable())
553 return false;
554
555 if (MI.isBundle())
556 return false;
557
559 return false;
560
564
565
566
568 return false;
569
570
571
574 return false;
576 return false;
577
581 }
582
583 return true;
584}
585
586namespace llvm {
587
590 if (!MO.isReg() || MO.isUndef() || MO.isUse())
591 continue;
592 if (MO.getReg() != ARM::CPSR)
593 continue;
594 if (!MO.isDead())
595 return false;
596 }
597
598 return true;
599}
600
601}
602
603
604
609
611
612 switch (MI.getOpcode()) {
613 default:
614
615
616
617
618
619 return MCID.getSize();
620 case TargetOpcode::BUNDLE:
621 return getInstBundleLength(MI);
622 case ARM::CONSTPOOL_ENTRY:
623 case ARM::JUMPTABLE_INSTS:
624 case ARM::JUMPTABLE_ADDRS:
625 case ARM::JUMPTABLE_TBB:
626 case ARM::JUMPTABLE_TBH:
627
628
629 return MI.getOperand(2).getImm();
630 case ARM::SPACE:
631 return MI.getOperand(1).getImm();
632 case ARM::INLINEASM:
633 case ARM::INLINEASM_BR: {
634
635 unsigned Size = getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
639 }
640 }
641}
642
643unsigned ARMBaseInstrInfo::getInstBundleLength(const MachineInstr &MI) const {
644 unsigned Size = 0;
647 while (++I != E && I->isInsideBundle()) {
648 assert(->isBundle() && "No nested bundle!");
650 }
652}
653
658 unsigned Opc = Subtarget.isThumb()
659 ? (Subtarget.isMClass() ? ARM::t2MRS_M : ARM::t2MRS_AR)
660 : ARM::MRS;
661
664
665
666
667 if (Subtarget.isMClass())
669
672}
673
678 unsigned Opc = Subtarget.isThumb()
679 ? (Subtarget.isMClass() ? ARM::t2MSR_M : ARM::t2MSR_AR)
680 : ARM::MSR;
681
683
684 if (Subtarget.isMClass())
686 else
688
692}
693
699
705
711
713 unsigned Cond, unsigned Inactive) {
715 MIB.addReg(Inactive);
716}
717
721 Register SrcReg, bool KillSrc,
722 bool RenamableDest,
723 bool RenamableSrc) const {
724 bool GPRDest = ARM::GPRRegClass.contains(DestReg);
725 bool GPRSrc = ARM::GPRRegClass.contains(SrcReg);
726
727 if (GPRDest && GPRSrc) {
732 return;
733 }
734
735 bool SPRDest = ARM::SPRRegClass.contains(DestReg);
736 bool SPRSrc = ARM::SPRRegClass.contains(SrcReg);
737
738 unsigned Opc = 0;
739 if (SPRDest && SPRSrc)
740 Opc = ARM::VMOVS;
741 else if (GPRDest && SPRSrc)
742 Opc = ARM::VMOVRS;
743 else if (SPRDest && GPRSrc)
744 Opc = ARM::VMOVSR;
745 else if (ARM::DPRRegClass.contains(DestReg, SrcReg) && Subtarget.hasFP64())
746 Opc = ARM::VMOVD;
747 else if (ARM::QPRRegClass.contains(DestReg, SrcReg))
748 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MQPRCopy;
749
750 if (Opc) {
753 if (Opc == ARM::VORRq || Opc == ARM::MVE_VORR)
755 if (Opc == ARM::MVE_VORR)
757 else if (Opc != ARM::MQPRCopy)
759 return;
760 }
761
762
763 unsigned BeginIdx = 0;
764 unsigned SubRegs = 0;
765 int Spacing = 1;
766
767
768 if (ARM::QQPRRegClass.contains(DestReg, SrcReg)) {
769 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
770 BeginIdx = ARM::qsub_0;
771 SubRegs = 2;
772 } else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) {
773 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;
774 BeginIdx = ARM::qsub_0;
775 SubRegs = 4;
776
777 } else if (ARM::DPairRegClass.contains(DestReg, SrcReg)) {
778 Opc = ARM::VMOVD;
779 BeginIdx = ARM::dsub_0;
780 SubRegs = 2;
781 } else if (ARM::DTripleRegClass.contains(DestReg, SrcReg)) {
782 Opc = ARM::VMOVD;
783 BeginIdx = ARM::dsub_0;
784 SubRegs = 3;
785 } else if (ARM::DQuadRegClass.contains(DestReg, SrcReg)) {
786 Opc = ARM::VMOVD;
787 BeginIdx = ARM::dsub_0;
788 SubRegs = 4;
789 } else if (ARM::GPRPairRegClass.contains(DestReg, SrcReg)) {
790 Opc = Subtarget.isThumb2() ? ARM::tMOVr : ARM::MOVr;
791 BeginIdx = ARM::gsub_0;
792 SubRegs = 2;
793 } else if (ARM::DPairSpcRegClass.contains(DestReg, SrcReg)) {
794 Opc = ARM::VMOVD;
795 BeginIdx = ARM::dsub_0;
796 SubRegs = 2;
797 Spacing = 2;
798 } else if (ARM::DTripleSpcRegClass.contains(DestReg, SrcReg)) {
799 Opc = ARM::VMOVD;
800 BeginIdx = ARM::dsub_0;
801 SubRegs = 3;
802 Spacing = 2;
803 } else if (ARM::DQuadSpcRegClass.contains(DestReg, SrcReg)) {
804 Opc = ARM::VMOVD;
805 BeginIdx = ARM::dsub_0;
806 SubRegs = 4;
807 Spacing = 2;
808 } else if (ARM::DPRRegClass.contains(DestReg, SrcReg) &&
809 !Subtarget.hasFP64()) {
810 Opc = ARM::VMOVS;
811 BeginIdx = ARM::ssub_0;
812 SubRegs = 2;
813 } else if (SrcReg == ARM::CPSR) {
815 return;
816 } else if (DestReg == ARM::CPSR) {
818 return;
819 } else if (DestReg == ARM::VPR) {
821 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMSR_P0), DestReg)
824 return;
825 } else if (SrcReg == ARM::VPR) {
827 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMRS_P0), DestReg)
830 return;
831 } else if (DestReg == ARM::FPSCR_NZCV) {
833 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMSR_FPSCR_NZCVQC), DestReg)
836 return;
837 } else if (SrcReg == ARM::FPSCR_NZCV) {
839 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMRS_FPSCR_NZCVQC), DestReg)
842 return;
843 }
844
845 assert(Opc && "Impossible reg-to-reg copy");
846
849
850
851 if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) {
852 BeginIdx = BeginIdx + ((SubRegs - 1) * Spacing);
853 Spacing = -Spacing;
854 }
855#ifndef NDEBUG
857#endif
858 for (unsigned i = 0; i != SubRegs; ++i) {
859 Register Dst = TRI->getSubReg(DestReg, BeginIdx + i * Spacing);
860 Register Src = TRI->getSubReg(SrcReg, BeginIdx + i * Spacing);
861 assert(Dst && Src && "Bad sub-register");
862#ifndef NDEBUG
863 assert(!DstRegs.count(Src) && "destructive vector copy");
865#endif
867
868 if (Opc == ARM::VORRq || Opc == ARM::MVE_VORR) {
870 }
871
872 if (Opc == ARM::MVE_VORR)
874 else
876
877 if (Opc == ARM::MOVr)
879 }
880
882 if (KillSrc)
884}
885
886std::optional
888
889
890
891
892
893
894
895 if (.isMoveReg() ||
896 (MI.getOpcode() == ARM::VORRq &&
897 MI.getOperand(1).getReg() != MI.getOperand(2).getReg()))
898 return std::nullopt;
900}
901
902std::optional
906 Register DstReg = DstSrcPair->Destination->getReg();
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926 if (DstReg != Reg)
927 return std::nullopt;
928 }
930}
931
933 unsigned Reg,
934 unsigned SubIdx,
935 unsigned State) const {
936 if (!SubIdx)
937 return MIB.addReg(Reg, State);
938
941 return MIB.addReg(Reg, State, SubIdx);
942}
943
946 Register SrcReg, bool isKill, int FI,
954
958
959 switch (TRI.getSpillSize(*RC)) {
960 case 2:
961 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
968 } else
970 break;
971 case 4:
972 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
979 } else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
986 } else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
993 } else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1000 } else
1002 break;
1003 case 8:
1004 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1011 } else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1012 if (Subtarget.hasV5TEOps()) {
1015 AddDReg(MIB, SrcReg, ARM::gsub_1, 0);
1018 } else {
1019
1020
1026 AddDReg(MIB, SrcReg, ARM::gsub_1, 0);
1027 }
1028 } else
1030 break;
1031 case 16:
1032 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1033
1034 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF)) {
1041 } else {
1047 }
1048 } else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1049 Subtarget.hasMVEIntegerOps()) {
1052 .addFrameIndex(FI)
1053 .addImm(0)
1054 .addMemOperand(MMO);
1056 } else
1058 break;
1059 case 24:
1060 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1061
1062 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&
1063 Subtarget.hasNEON()) {
1070 } else {
1072 get(ARM::VSTMDIA))
1077 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);
1078 AddDReg(MIB, SrcReg, ARM::dsub_2, 0);
1079 }
1080 } else
1082 break;
1083 case 32:
1084 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1085 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1086 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1087 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&
1088 Subtarget.hasNEON()) {
1089
1090
1097 } else if (Subtarget.hasMVEIntegerOps()) {
1102 } else {
1104 get(ARM::VSTMDIA))
1109 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);
1110 MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0);
1111 AddDReg(MIB, SrcReg, ARM::dsub_3, 0);
1112 }
1113 } else
1115 break;
1116 case 64:
1117 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1118 Subtarget.hasMVEIntegerOps()) {
1123 } else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1129 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);
1130 MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0);
1131 MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0);
1132 MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0);
1133 MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0);
1134 MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0);
1135 AddDReg(MIB, SrcReg, ARM::dsub_7, 0);
1136 } else
1138 break;
1139 default:
1141 }
1142}
1143
1145 int &FrameIndex) const {
1146 switch (MI.getOpcode()) {
1147 default: break;
1148 case ARM::STRrs:
1149 case ARM::t2STRs:
1150 if (MI.getOperand(1).isFI() && MI.getOperand(2).isReg() &&
1151 MI.getOperand(3).isImm() && MI.getOperand(2).getReg() == 0 &&
1152 MI.getOperand(3).getImm() == 0) {
1153 FrameIndex = MI.getOperand(1).getIndex();
1154 return MI.getOperand(0).getReg();
1155 }
1156 break;
1157 case ARM::STRi12:
1158 case ARM::t2STRi12:
1159 case ARM::tSTRspi:
1160 case ARM::VSTRD:
1161 case ARM::VSTRS:
1162 case ARM::VSTRH:
1163 case ARM::VSTR_P0_off:
1164 case ARM::VSTR_FPSCR_NZCVQC_off:
1165 case ARM::MVE_VSTRWU32:
1166 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
1167 MI.getOperand(2).getImm() == 0) {
1168 FrameIndex = MI.getOperand(1).getIndex();
1169 return MI.getOperand(0).getReg();
1170 }
1171 break;
1172 case ARM::VST1q64:
1173 case ARM::VST1d64TPseudo:
1174 case ARM::VST1d64QPseudo:
1175 if (MI.getOperand(0).isFI() && MI.getOperand(2).getSubReg() == 0) {
1176 FrameIndex = MI.getOperand(0).getIndex();
1177 return MI.getOperand(2).getReg();
1178 }
1179 break;
1180 case ARM::VSTMQIA:
1181 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {
1182 FrameIndex = MI.getOperand(1).getIndex();
1183 return MI.getOperand(0).getReg();
1184 }
1185 break;
1186 case ARM::MQQPRStore:
1187 case ARM::MQQQQPRStore:
1188 if (MI.getOperand(1).isFI()) {
1189 FrameIndex = MI.getOperand(1).getIndex();
1190 return MI.getOperand(0).getReg();
1191 }
1192 break;
1193 }
1194
1195 return 0;
1196}
1197
1199 int &FrameIndex) const {
1201 if (MI.mayStore() && hasStoreToStackSlot(MI, Accesses) &&
1203 FrameIndex =
1205 ->getFrameIndex();
1206 return true;
1207 }
1208 return false;
1209}
1210
1218 if (I != MBB.end()) DL = I->getDebugLoc();
1225
1227 switch (TRI.getSpillSize(*RC)) {
1228 case 2:
1229 if (ARM::HPRRegClass.hasSubClassEq(RC)) {
1235 } else
1237 break;
1238 case 4:
1239 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
1245 } else if (ARM::SPRRegClass.hasSubClassEq(RC)) {
1251 } else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {
1257 } else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {
1258 BuildMI(MBB, I, DL, get(ARM::VLDR_FPSCR_NZCVQC_off), DestReg)
1263 } else
1265 break;
1266 case 8:
1267 if (ARM::DPRRegClass.hasSubClassEq(RC)) {
1273 } else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
1275
1276 if (Subtarget.hasV5TEOps()) {
1282 } else {
1283
1284
1291 }
1292
1295 } else
1297 break;
1298 case 16:
1299 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {
1300 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF)) {
1306 } else {
1311 }
1312 } else if (ARM::QPRRegClass.hasSubClassEq(RC) &&
1313 Subtarget.hasMVEIntegerOps()) {
1314 auto MIB = BuildMI(MBB, I, DL, get(ARM::MVE_VLDRWU32), DestReg);
1315 MIB.addFrameIndex(FI)
1316 .addImm(0)
1317 .addMemOperand(MMO);
1319 } else
1321 break;
1322 case 24:
1323 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {
1324 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&
1325 Subtarget.hasNEON()) {
1331 } else {
1341 }
1342 } else
1344 break;
1345 case 32:
1346 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||
1347 ARM::MQQPRRegClass.hasSubClassEq(RC) ||
1348 ARM::DQuadRegClass.hasSubClassEq(RC)) {
1349 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&
1350 Subtarget.hasNEON()) {
1356 } else if (Subtarget.hasMVEIntegerOps()) {
1360 } else {
1371 }
1372 } else
1374 break;
1375 case 64:
1376 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&
1377 Subtarget.hasMVEIntegerOps()) {
1381 } else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {
1396 } else
1398 break;
1399 default:
1401 }
1402}
1403
1405 int &FrameIndex) const {
1406 switch (MI.getOpcode()) {
1407 default: break;
1408 case ARM::LDRrs:
1409 case ARM::t2LDRs:
1410 if (MI.getOperand(1).isFI() && MI.getOperand(2).isReg() &&
1411 MI.getOperand(3).isImm() && MI.getOperand(2).getReg() == 0 &&
1412 MI.getOperand(3).getImm() == 0) {
1413 FrameIndex = MI.getOperand(1).getIndex();
1414 return MI.getOperand(0).getReg();
1415 }
1416 break;
1417 case ARM::LDRi12:
1418 case ARM::t2LDRi12:
1419 case ARM::tLDRspi:
1420 case ARM::VLDRD:
1421 case ARM::VLDRS:
1422 case ARM::VLDRH:
1423 case ARM::VLDR_P0_off:
1424 case ARM::VLDR_FPSCR_NZCVQC_off:
1425 case ARM::MVE_VLDRWU32:
1426 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
1427 MI.getOperand(2).getImm() == 0) {
1428 FrameIndex = MI.getOperand(1).getIndex();
1429 return MI.getOperand(0).getReg();
1430 }
1431 break;
1432 case ARM::VLD1q64:
1433 case ARM::VLD1d8TPseudo:
1434 case ARM::VLD1d16TPseudo:
1435 case ARM::VLD1d32TPseudo:
1436 case ARM::VLD1d64TPseudo:
1437 case ARM::VLD1d8QPseudo:
1438 case ARM::VLD1d16QPseudo:
1439 case ARM::VLD1d32QPseudo:
1440 case ARM::VLD1d64QPseudo:
1441 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {
1442 FrameIndex = MI.getOperand(1).getIndex();
1443 return MI.getOperand(0).getReg();
1444 }
1445 break;
1446 case ARM::VLDMQIA:
1447 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {
1448 FrameIndex = MI.getOperand(1).getIndex();
1449 return MI.getOperand(0).getReg();
1450 }
1451 break;
1452 case ARM::MQQPRLoad:
1453 case ARM::MQQQQPRLoad:
1454 if (MI.getOperand(1).isFI()) {
1455 FrameIndex = MI.getOperand(1).getIndex();
1456 return MI.getOperand(0).getReg();
1457 }
1458 break;
1459 }
1460
1461 return 0;
1462}
1463
1465 int &FrameIndex) const {
1467 if (MI.mayLoad() && hasLoadFromStackSlot(MI, Accesses) &&
1469 FrameIndex =
1471 ->getFrameIndex();
1472 return true;
1473 }
1474 return false;
1475}
1476
1477
1478
1481 bool isThumb2 = Subtarget.isThumb2();
1483
1486
1488 if (isThumb1 || ->getOperand(1).isDead()) {
1490 LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA_UPD
1491 : isThumb1 ? ARM::tLDMIA_UPD
1492 : ARM::LDMIA_UPD))
1493 .add(LDWb);
1494 } else {
1495 LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));
1496 }
1497
1498 if (isThumb1 || ->getOperand(0).isDead()) {
1499 MachineOperand STWb(MI->getOperand(0));
1500 STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA_UPD
1501 : isThumb1 ? ARM::tSTMIA_UPD
1502 : ARM::STMIA_UPD))
1503 .add(STWb);
1504 } else {
1505 STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));
1506 }
1507
1508 MachineOperand LDBase(MI->getOperand(3));
1510
1511 MachineOperand STBase(MI->getOperand(2));
1513
1514
1518 ScratchRegs.push_back(MO.getReg());
1520 [&TRI](const unsigned &Reg1, const unsigned &Reg2) -> bool {
1521 return TRI.getEncodingValue(Reg1) <
1522 TRI.getEncodingValue(Reg2);
1523 });
1524
1525 for (const auto &Reg : ScratchRegs) {
1528 }
1529
1531}
1532
1534 if (MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) {
1535 expandLoadStackGuard(MI);
1536 MI.getParent()->erase(MI);
1537 return true;
1538 }
1539
1540 if (MI.getOpcode() == ARM::MEMCPY) {
1541 expandMEMCPY(MI);
1542 return true;
1543 }
1544
1545
1546
1547
1548
1549 if (.isCopy() || Subtarget.dontWidenVMOVS() || !Subtarget.hasFP64())
1550 return false;
1551
1552
1553
1554 Register DstRegS = MI.getOperand(0).getReg();
1555 Register SrcRegS = MI.getOperand(1).getReg();
1556 if (!ARM::SPRRegClass.contains(DstRegS, SrcRegS))
1557 return false;
1558
1561 TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, &ARM::DPRRegClass);
1563 TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, &ARM::DPRRegClass);
1564 if (!DstRegD || !SrcRegD)
1565 return false;
1566
1567
1568
1569
1570 if (.definesRegister(DstRegD, TRI) || MI.readsRegister(DstRegD, TRI))
1571 return false;
1572
1573
1574 if (MI.getOperand(0).isDead())
1575 return false;
1576
1577
1580
1581
1582
1583 int ImpDefIdx = MI.findRegisterDefOperandIdx(DstRegD, nullptr);
1584 if (ImpDefIdx != -1)
1585 MI.removeOperand(ImpDefIdx);
1586
1587
1588 MI.setDesc(get(ARM::VMOVD));
1589 MI.getOperand(0).setReg(DstRegD);
1590 MI.getOperand(1).setReg(SrcRegD);
1592
1593
1594
1595
1596
1597 MI.getOperand(1).setIsUndef();
1599
1600
1601
1602 if (MI.getOperand(1).isKill()) {
1603 MI.getOperand(1).setIsKill(false);
1604 MI.addRegisterKilled(SrcRegS, TRI, true);
1605 }
1606
1608 return true;
1609}
1610
1611
1612
1616
1618 assert(MCPE.isMachineConstantPoolEntry() &&
1619 "Expecting a machine constantpool entry!");
1622
1625
1626
1627
1628
1629
1630
1643 else if (ACPV->isLSDA())
1650 else
1651 llvm_unreachable("Unexpected ARM constantpool value type!!");
1653 return PCLabelId;
1654}
1655
1658 Register DestReg, unsigned SubIdx,
1660 unsigned Opcode = Orig.getOpcode();
1661 switch (Opcode) {
1662 default: {
1666 break;
1667 }
1668 case ARM::tLDRpci_pic:
1669 case ARM::t2LDRpci_pic: {
1677 break;
1678 }
1679 }
1680}
1681
1688 for (;;) {
1689 switch (I->getOpcode()) {
1690 case ARM::tLDRpci_pic:
1691 case ARM::t2LDRpci_pic: {
1693 unsigned CPI = I->getOperand(1).getIndex();
1695 I->getOperand(1).setIndex(CPI);
1696 I->getOperand(2).setImm(PCLabelId);
1697 break;
1698 }
1699 }
1700 if (->isBundledWithSucc())
1701 break;
1702 ++I;
1703 }
1704 return Cloned;
1705}
1706
1710 unsigned Opcode = MI0.getOpcode();
1711 if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic ||
1712 Opcode == ARM::tLDRpci || Opcode == ARM::tLDRpci_pic ||
1713 Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1714 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1715 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1716 Opcode == ARM::t2MOV_ga_pcrel) {
1718 return false;
1720 return false;
1721
1725 return false;
1726
1727 if (Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||
1728 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||
1729 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||
1730 Opcode == ARM::t2MOV_ga_pcrel)
1731
1733
1742 if (isARMCP0 && isARMCP1) {
1748 } else if (!isARMCP0 && !isARMCP1) {
1750 }
1751 return false;
1752 } else if (Opcode == ARM::PICLDR) {
1754 return false;
1756 return false;
1757
1760 if (Addr0 != Addr1) {
1762 return false;
1763
1764
1767
1768
1770 return false;
1771 }
1772
1773 for (unsigned i = 3, e = MI0.getNumOperands(); i != e; ++i) {
1774
1778 return false;
1779 }
1780 return true;
1781 }
1782
1784}
1785
1786
1787
1788
1789
1790
1791
1792
1793
1795 int64_t &Offset1,
1796 int64_t &Offset2) const {
1797
1798 if (Subtarget.isThumb1Only()) return false;
1799
1801 return false;
1802
1803 auto IsLoadOpcode = [&](unsigned Opcode) {
1804 switch (Opcode) {
1805 default:
1806 return false;
1807 case ARM::LDRi12:
1808 case ARM::LDRBi12:
1809 case ARM::LDRD:
1810 case ARM::LDRH:
1811 case ARM::LDRSB:
1812 case ARM::LDRSH:
1813 case ARM::VLDRD:
1814 case ARM::VLDRS:
1815 case ARM::t2LDRi8:
1816 case ARM::t2LDRBi8:
1817 case ARM::t2LDRDi8:
1818 case ARM::t2LDRSHi8:
1819 case ARM::t2LDRi12:
1820 case ARM::t2LDRBi12:
1821 case ARM::t2LDRSHi12:
1822 return true;
1823 }
1824 };
1825
1828 return false;
1829
1830
1833 return false;
1834
1835
1837 return false;
1838
1839
1844 return true;
1845 }
1846
1847 return false;
1848}
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1862 int64_t Offset1, int64_t Offset2,
1863 unsigned NumLoads) const {
1864
1865 if (Subtarget.isThumb1Only()) return false;
1866
1867 assert(Offset2 > Offset1);
1868
1869 if ((Offset2 - Offset1) / 8 > 64)
1870 return false;
1871
1872
1873
1874
1875
1876
1882 return false;
1883
1884
1885 if (NumLoads >= 3)
1886 return false;
1887
1888 return true;
1889}
1890
1894
1895
1896
1897
1898
1899
1900 if (MI.isDebugInstr())
1901 return false;
1902
1903
1904 if (MI.isTerminator() || MI.isPosition())
1905 return true;
1906
1907
1908 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
1909 return true;
1910
1912 return true;
1913
1914
1915
1916
1917
1918
1919
1921
1922 while (++I != MBB->end() && I->isDebugInstr())
1923 ;
1924 if (I != MBB->end() && I->getOpcode() == ARM::t2IT)
1925 return true;
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935 if (.isCall() && MI.definesRegister(ARM::SP, nullptr))
1936 return true;
1937
1938 return false;
1939}
1940
1943 unsigned NumCycles, unsigned ExtraPredCycles,
1945 if (!NumCycles)
1946 return false;
1947
1948
1949
1950
1951 if (MBB.getParent()->getFunction().hasOptSize()) {
1953 if (!Pred->empty()) {
1955 if (LastMI->getOpcode() == ARM::t2Bcc) {
1958 if (CmpMI)
1959 return false;
1960 }
1961 }
1962 }
1964 MBB, 0, 0, Probability);
1965}
1966
1969 unsigned TCycles, unsigned TExtra,
1971 unsigned FCycles, unsigned FExtra,
1973 if (!TCycles)
1974 return false;
1975
1976
1977
1978
1979
1980 if (Subtarget.isThumb2() && TBB.getParent()->getFunction().hasMinSize()) {
1981 if (TBB.pred_size() != 1 || FBB.pred_size() != 1)
1982 return false;
1983 }
1984
1985
1986
1987
1988 const unsigned ScalingUpFactor = 1024;
1989
1990 unsigned PredCost = (TCycles + FCycles + TExtra + FExtra) * ScalingUpFactor;
1991 unsigned UnpredCost;
1992 if (!Subtarget.hasBranchPredictor()) {
1993
1994
1995 unsigned NotTakenBranchCost = 1;
1996 unsigned TakenBranchCost = Subtarget.getMispredictionPenalty();
1997 unsigned TUnpredCycles, FUnpredCycles;
1998 if (!FCycles) {
1999
2000 TUnpredCycles = TCycles + NotTakenBranchCost;
2001 FUnpredCycles = TakenBranchCost;
2002 } else {
2003
2004 TUnpredCycles = TCycles + TakenBranchCost;
2005 FUnpredCycles = FCycles + NotTakenBranchCost;
2006
2007
2008 PredCost -= 1 * ScalingUpFactor;
2009 }
2010
2011 unsigned TUnpredCost = Probability.scale(TUnpredCycles * ScalingUpFactor);
2012 unsigned FUnpredCost = Probability.getCompl().scale(FUnpredCycles * ScalingUpFactor);
2013 UnpredCost = TUnpredCost + FUnpredCost;
2014
2015
2016 if (Subtarget.isThumb2() && TCycles + FCycles > 4) {
2017 PredCost += ((TCycles + FCycles - 4) / 4) * ScalingUpFactor;
2018 }
2019 } else {
2020 unsigned TUnpredCost = Probability.scale(TCycles * ScalingUpFactor);
2021 unsigned FUnpredCost =
2022 Probability.getCompl().scale(FCycles * ScalingUpFactor);
2023 UnpredCost = TUnpredCost + FUnpredCost;
2024 UnpredCost += 1 * ScalingUpFactor;
2025 UnpredCost += Subtarget.getMispredictionPenalty() * ScalingUpFactor / 10;
2026 }
2027
2028 return PredCost <= UnpredCost;
2029}
2030
2031unsigned
2033 unsigned NumInsts) const {
2034
2035
2036
2037 if (!Subtarget.isThumb2())
2038 return 0;
2039
2040
2041 unsigned MaxInsts = Subtarget.restrictIT() ? 1 : 4;
2042 return divideCeil(NumInsts, MaxInsts) * 2;
2043}
2044
2045unsigned
2047
2048
2049
2050 if (MI.getOpcode() == ARM::t2Bcc &&
2052 return 0;
2053
2055
2056
2057
2058
2059
2060
2061
2062 if (Subtarget.isThumb2())
2064
2065 return Size;
2066}
2067
2068bool
2071
2072
2073 return Subtarget.isProfitableToUnpredicate();
2074}
2075
2076
2077
2078
2081 int PIdx = MI.findFirstPredOperandIdx();
2082 if (PIdx == -1) {
2083 PredReg = 0;
2085 }
2086
2087 PredReg = MI.getOperand(PIdx+1).getReg();
2089}
2090
2092 if (Opc == ARM::B)
2093 return ARM::Bcc;
2094 if (Opc == ARM::tB)
2095 return ARM::tBcc;
2096 if (Opc == ARM::t2B)
2097 return ARM::t2Bcc;
2098
2100}
2101
2103 bool NewMI,
2104 unsigned OpIdx1,
2105 unsigned OpIdx2) const {
2106 switch (MI.getOpcode()) {
2107 case ARM::MOVCCr:
2108 case ARM::t2MOVCCr: {
2109
2112
2113 if (CC == ARMCC::AL || PredReg != ARM::CPSR)
2114 return nullptr;
2117 if (!CommutedMI)
2118 return nullptr;
2119
2122 return CommutedMI;
2123 }
2124 }
2126}
2127
2128
2129
2133 if (!Reg.isVirtual())
2134 return nullptr;
2135 if (.hasOneNonDBGUse(Reg))
2136 return nullptr;
2138 if ()
2139 return nullptr;
2140
2142 return nullptr;
2143
2144
2146
2147 if (MO.isFI() || MO.isCPI() || MO.isJTI())
2148 return nullptr;
2149 if (!MO.isReg())
2150 continue;
2151
2152 if (MO.isTied())
2153 return nullptr;
2154 if (MO.getReg().isPhysical())
2155 return nullptr;
2156 if (MO.isDef() && !MO.isDead())
2157 return nullptr;
2158 }
2159 bool DontMoveAcrossStores = true;
2160 if (->isSafeToMove(DontMoveAcrossStores))
2161 return nullptr;
2162 return MI;
2163}
2164
2167 unsigned &TrueOp, unsigned &FalseOp,
2168 bool &Optimizable) const {
2169 assert((MI.getOpcode() == ARM::MOVCCr || MI.getOpcode() == ARM::t2MOVCCr) &&
2170 "Unknown select instruction");
2171
2172
2173
2174
2175
2176
2177 TrueOp = 1;
2178 FalseOp = 2;
2179 Cond.push_back(MI.getOperand(3));
2180 Cond.push_back(MI.getOperand(4));
2181
2182 Optimizable = true;
2183 return false;
2184}
2185
2189 bool PreferFalse) const {
2190 assert((MI.getOpcode() == ARM::MOVCCr || MI.getOpcode() == ARM::t2MOVCCr) &&
2191 "Unknown select instruction");
2194 bool Invert = ;
2196 DefMI = canFoldIntoMOVCC(MI.getOperand(1).getReg(), MRI, this);
2198 return nullptr;
2199
2200
2203 Register DestReg = MI.getOperand(0).getReg();
2206 if (.constrainRegClass(DestReg, FalseClass))
2207 return nullptr;
2208 if (.constrainRegClass(DestReg, TrueClass))
2209 return nullptr;
2210
2211
2212
2214 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), DefMI->getDesc(), DestReg);
2215
2216
2219 i != e && !DefDesc.operands()[i].isPredicate(); ++i)
2220 NewMI.add(DefMI->getOperand(i));
2221
2222 unsigned CondCode = MI.getOperand(3).getImm();
2223 if (Invert)
2225 else
2226 NewMI.addImm(CondCode);
2227 NewMI.add(MI.getOperand(4));
2228
2229
2232
2233
2234
2235
2236
2238 NewMI.add(FalseReg);
2240
2241
2242 SeenMIs.insert(NewMI);
2244
2245
2246
2247
2248
2249 if (DefMI->getParent() != MI.getParent())
2251
2252
2253 DefMI->eraseFromParent();
2254 return NewMI;
2255}
2256
2257
2258
2259
2260
2261
2262
2267
2269 {ARM::ADDSri, ARM::ADDri},
2270 {ARM::ADDSrr, ARM::ADDrr},
2271 {ARM::ADDSrsi, ARM::ADDrsi},
2272 {ARM::ADDSrsr, ARM::ADDrsr},
2273
2274 {ARM::SUBSri, ARM::SUBri},
2275 {ARM::SUBSrr, ARM::SUBrr},
2276 {ARM::SUBSrsi, ARM::SUBrsi},
2277 {ARM::SUBSrsr, ARM::SUBrsr},
2278
2279 {ARM::RSBSri, ARM::RSBri},
2280 {ARM::RSBSrsi, ARM::RSBrsi},
2281 {ARM::RSBSrsr, ARM::RSBrsr},
2282
2283 {ARM::tADDSi3, ARM::tADDi3},
2284 {ARM::tADDSi8, ARM::tADDi8},
2285 {ARM::tADDSrr, ARM::tADDrr},
2286 {ARM::tADCS, ARM::tADC},
2287
2288 {ARM::tSUBSi3, ARM::tSUBi3},
2289 {ARM::tSUBSi8, ARM::tSUBi8},
2290 {ARM::tSUBSrr, ARM::tSUBrr},
2291 {ARM::tSBCS, ARM::tSBC},
2292 {ARM::tRSBS, ARM::tRSB},
2293 {ARM::tLSLSri, ARM::tLSLri},
2294
2295 {ARM::t2ADDSri, ARM::t2ADDri},
2296 {ARM::t2ADDSrr, ARM::t2ADDrr},
2297 {ARM::t2ADDSrs, ARM::t2ADDrs},
2298
2299 {ARM::t2SUBSri, ARM::t2SUBri},
2300 {ARM::t2SUBSrr, ARM::t2SUBrr},
2301 {ARM::t2SUBSrs, ARM::t2SUBrs},
2302
2303 {ARM::t2RSBSri, ARM::t2RSBri},
2304 {ARM::t2RSBSrs, ARM::t2RSBrs},
2305};
2306
2309 if (OldOpc == Entry.PseudoOpc)
2310 return Entry.MachineOpc;
2311 return 0;
2312}
2313
2317 Register BaseReg, int NumBytes,
2320 unsigned MIFlags) {
2321 if (NumBytes == 0 && DestReg != BaseReg) {
2327 return;
2328 }
2329
2330 bool isSub = NumBytes < 0;
2331 if (isSub) NumBytes = -NumBytes;
2332
2333 while (NumBytes) {
2336 assert(ThisVal && "Didn't extract field correctly");
2337
2338
2339 NumBytes &= ~ThisVal;
2340
2342
2343
2344 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;
2351 BaseReg = DestReg;
2352 }
2353}
2354
2357 unsigned NumBytes) {
2358
2359
2361 return false;
2362
2363
2364
2365
2368 if (!IsPush && !IsPop)
2369 return false;
2370
2371 bool IsVFPPushPop = MI->getOpcode() == ARM::VSTMDDB_UPD ||
2372 MI->getOpcode() == ARM::VLDMDIA_UPD;
2373 bool IsT1PushPop = MI->getOpcode() == ARM::tPUSH ||
2374 MI->getOpcode() == ARM::tPOP ||
2375 MI->getOpcode() == ARM::tPOP_RET;
2376
2377 assert((IsT1PushPop || (MI->getOperand(0).getReg() == ARM::SP &&
2378 MI->getOperand(1).getReg() == ARM::SP)) &&
2379 "trying to fold sp update into non-sp-updating push/pop");
2380
2381
2382
2383
2384 if (NumBytes % (IsVFPPushPop ? 8 : 4) != 0)
2385 return false;
2386
2387
2388
2389 int RegListIdx = IsT1PushPop ? 2 : 4;
2390
2391
2392 unsigned RegsNeeded;
2394 if (IsVFPPushPop) {
2395 RegsNeeded = NumBytes / 8;
2396 RegClass = &ARM::DPRRegClass;
2397 } else {
2398 RegsNeeded = NumBytes / 4;
2399 RegClass = &ARM::GPRRegClass;
2400 }
2401
2402
2403
2404
2406
2407
2408
2409 unsigned FirstRegEnc = -1;
2410
2412 for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) {
2415
2417 TRI->getEncodingValue(MO.getReg()) < FirstRegEnc)
2418 FirstRegEnc = TRI->getEncodingValue(MO.getReg());
2419 }
2420
2421 const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
2422
2423
2424 for (int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
2425 --CurRegEnc) {
2427 if (IsT1PushPop && CurRegEnc > TRI->getEncodingValue(ARM::R7))
2428 continue;
2429 if (!IsPop) {
2430
2431
2432
2434 false, false, true));
2435 --RegsNeeded;
2436 continue;
2437 }
2438
2439
2440
2441
2442
2444 MI->getParent()->computeRegisterLiveness(TRI, CurReg, MI) !=
2446
2447
2448 if (IsVFPPushPop)
2449 return false;
2450 else
2451 continue;
2452 }
2453
2454
2456 true));
2457 --RegsNeeded;
2458 }
2459
2460 if (RegsNeeded > 0)
2461 return false;
2462
2463
2464
2465
2466 for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i)
2467 MI->removeOperand(i);
2468
2469
2472 MIB.add(MO);
2473
2474 return true;
2475}
2476
2480 unsigned Opcode = MI.getOpcode();
2483 bool isSub = false;
2484
2485
2486 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
2488
2489 if (Opcode == ARM::ADDri) {
2490 Offset += MI.getOperand(FrameRegIdx+1).getImm();
2492
2493 MI.setDesc(TII.get(ARM::MOVr));
2494 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
2495 MI.removeOperand(FrameRegIdx+1);
2497 return true;
2498 } else if (Offset < 0) {
2500 isSub = true;
2501 MI.setDesc(TII.get(ARM::SUBri));
2502 }
2503
2504
2506
2507 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
2508 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
2510 return true;
2511 }
2512
2513
2514
2517
2518
2519 Offset &= ~ThisImmVal;
2520
2521
2523 "Bit extraction didn't work?");
2524 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
2525 } else {
2526 unsigned ImmIdx = 0;
2527 int InstrOffs = 0;
2528 unsigned NumBits = 0;
2529 unsigned Scale = 1;
2532 ImmIdx = FrameRegIdx + 1;
2533 InstrOffs = MI.getOperand(ImmIdx).getImm();
2534 NumBits = 12;
2535 break;
2537 ImmIdx = FrameRegIdx+2;
2540 InstrOffs *= -1;
2541 NumBits = 12;
2542 break;
2544 ImmIdx = FrameRegIdx+2;
2547 InstrOffs *= -1;
2548 NumBits = 8;
2549 break;
2552
2553 return false;
2555 ImmIdx = FrameRegIdx+1;
2558 InstrOffs *= -1;
2559 NumBits = 8;
2560 Scale = 4;
2561 break;
2563 ImmIdx = FrameRegIdx+1;
2566 InstrOffs *= -1;
2567 NumBits = 8;
2568 Scale = 2;
2569 break;
2573 ImmIdx = FrameRegIdx+1;
2574 InstrOffs = MI.getOperand(ImmIdx).getImm();
2575 NumBits = 7;
2578 break;
2579 default:
2581 }
2582
2583 Offset += InstrOffs * Scale;
2584 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
2587 isSub = true;
2588 }
2589
2590
2591 if (NumBits > 0) {
2592
2594 int ImmedOffset = Offset / Scale;
2595 unsigned Mask = (1 << NumBits) - 1;
2596 if ((unsigned)Offset <= Mask * Scale) {
2597
2598 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
2599
2600
2601
2602 if (isSub) {
2604 ImmedOffset = -ImmedOffset;
2605 else
2606 ImmedOffset |= 1 << NumBits;
2607 }
2610 return true;
2611 }
2612
2613
2614 ImmedOffset = ImmedOffset & Mask;
2615 if (isSub) {
2617 ImmedOffset = -ImmedOffset;
2618 else
2619 ImmedOffset |= 1 << NumBits;
2620 }
2622 Offset &= ~(Mask*Scale);
2623 }
2624 }
2625
2628}
2629
2630
2631
2632
2633
2635 Register &SrcReg2, int64_t &CmpMask,
2636 int64_t &CmpValue) const {
2637 switch (MI.getOpcode()) {
2638 default: break;
2639 case ARM::CMPri:
2640 case ARM::t2CMPri:
2641 case ARM::tCMPi8:
2642 SrcReg = MI.getOperand(0).getReg();
2643 SrcReg2 = 0;
2644 CmpMask = ~0;
2645 CmpValue = MI.getOperand(1).getImm();
2646 return true;
2647 case ARM::CMPrr:
2648 case ARM::t2CMPrr:
2649 case ARM::tCMPr:
2650 SrcReg = MI.getOperand(0).getReg();
2651 SrcReg2 = MI.getOperand(1).getReg();
2652 CmpMask = ~0;
2653 CmpValue = 0;
2654 return true;
2655 case ARM::TSTri:
2656 case ARM::t2TSTri:
2657 SrcReg = MI.getOperand(0).getReg();
2658 SrcReg2 = 0;
2659 CmpMask = MI.getOperand(1).getImm();
2660 CmpValue = 0;
2661 return true;
2662 }
2663
2664 return false;
2665}
2666
2667
2668
2669
2670
2672 int CmpMask, bool CommonUse) {
2673 switch (MI->getOpcode()) {
2674 case ARM::ANDri:
2675 case ARM::t2ANDri:
2676 if (CmpMask != MI->getOperand(2).getImm())
2677 return false;
2678 if (SrcReg == MI->getOperand(CommonUse ? 1 : 0).getReg())
2679 return true;
2680 break;
2681 }
2682
2683 return false;
2684}
2685
2686
2687
2688
2690 switch (CC) {
2696 }
2697}
2698
2699
2700
2701
2702
2703
2704
2707 int64_t ImmValue,
2709 bool &IsThumb1) {
2710 if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&
2711 (OI->getOpcode() == ARM::SUBrr || OI->getOpcode() == ARM::t2SUBrr) &&
2716 IsThumb1 = false;
2717 return true;
2718 }
2719
2720 if (CmpI->getOpcode() == ARM::tCMPr && OI->getOpcode() == ARM::tSUBrr &&
2725 IsThumb1 = true;
2726 return true;
2727 }
2728
2729 if ((CmpI->getOpcode() == ARM::CMPri || CmpI->getOpcode() == ARM::t2CMPri) &&
2730 (OI->getOpcode() == ARM::SUBri || OI->getOpcode() == ARM::t2SUBri) &&
2733 IsThumb1 = false;
2734 return true;
2735 }
2736
2737 if (CmpI->getOpcode() == ARM::tCMPi8 &&
2738 (OI->getOpcode() == ARM::tSUBi8 || OI->getOpcode() == ARM::tSUBi3) &&
2741 IsThumb1 = true;
2742 return true;
2743 }
2744
2745 if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&
2746 (OI->getOpcode() == ARM::ADDrr || OI->getOpcode() == ARM::t2ADDrr ||
2747 OI->getOpcode() == ARM::ADDri || OI->getOpcode() == ARM::t2ADDri) &&
2751 IsThumb1 = false;
2752 return true;
2753 }
2754
2755 if (CmpI->getOpcode() == ARM::tCMPr &&
2756 (OI->getOpcode() == ARM::tADDi3 || OI->getOpcode() == ARM::tADDi8 ||
2757 OI->getOpcode() == ARM::tADDrr) &&
2760 IsThumb1 = true;
2761 return true;
2762 }
2763
2764 return false;
2765}
2766
2768 switch (MI->getOpcode()) {
2769 default: return false;
2770 case ARM::tLSLri:
2771 case ARM::tLSRri:
2772 case ARM::tLSLrr:
2773 case ARM::tLSRrr:
2774 case ARM::tSUBrr:
2775 case ARM::tADDrr:
2776 case ARM::tADDi3:
2777 case ARM::tADDi8:
2778 case ARM::tSUBi3:
2779 case ARM::tSUBi8:
2780 case ARM::tMUL:
2781 case ARM::tADC:
2782 case ARM::tSBC:
2783 case ARM::tRSB:
2784 case ARM::tAND:
2785 case ARM::tORR:
2786 case ARM::tEOR:
2787 case ARM::tBIC:
2788 case ARM::tMVN:
2789 case ARM::tASRri:
2790 case ARM::tASRrr:
2791 case ARM::tROR:
2792 IsThumb1 = true;
2793 [[fallthrough]];
2794 case ARM::RSBrr:
2795 case ARM::RSBri:
2796 case ARM::RSCrr:
2797 case ARM::RSCri:
2798 case ARM::ADDrr:
2799 case ARM::ADDri:
2800 case ARM::ADCrr:
2801 case ARM::ADCri:
2802 case ARM::SUBrr:
2803 case ARM::SUBri:
2804 case ARM::SBCrr:
2805 case ARM::SBCri:
2806 case ARM::t2RSBri:
2807 case ARM::t2ADDrr:
2808 case ARM::t2ADDri:
2809 case ARM::t2ADCrr:
2810 case ARM::t2ADCri:
2811 case ARM::t2SUBrr:
2812 case ARM::t2SUBri:
2813 case ARM::t2SBCrr:
2814 case ARM::t2SBCri:
2815 case ARM::ANDrr:
2816 case ARM::ANDri:
2817 case ARM::ANDrsr:
2818 case ARM::ANDrsi:
2819 case ARM::t2ANDrr:
2820 case ARM::t2ANDri:
2821 case ARM::t2ANDrs:
2822 case ARM::ORRrr:
2823 case ARM::ORRri:
2824 case ARM::ORRrsr:
2825 case ARM::ORRrsi:
2826 case ARM::t2ORRrr:
2827 case ARM::t2ORRri:
2828 case ARM::t2ORRrs:
2829 case ARM::EORrr:
2830 case ARM::EORri:
2831 case ARM::EORrsr:
2832 case ARM::EORrsi:
2833 case ARM::t2EORrr:
2834 case ARM::t2EORri:
2835 case ARM::t2EORrs:
2836 case ARM::BICri:
2837 case ARM::BICrr:
2838 case ARM::BICrsi:
2839 case ARM::BICrsr:
2840 case ARM::t2BICri:
2841 case ARM::t2BICrr:
2842 case ARM::t2BICrs:
2843 case ARM::t2LSRri:
2844 case ARM::t2LSRrr:
2845 case ARM::t2LSLri:
2846 case ARM::t2LSLrr:
2847 case ARM::MOVsr:
2848 case ARM::MOVsi:
2849 return true;
2850 }
2851}
2852
2853
2854
2855
2856
2857
2858
2859
2863
2865 if () return false;
2866
2867
2868 if (CmpMask != ~0) {
2870 MI = nullptr;
2872 UI = MRI->use_instr_begin(SrcReg), UE = MRI->use_instr_end();
2873 UI != UE; ++UI) {
2874 if (UI->getParent() != CmpInstr.getParent())
2875 continue;
2879 continue;
2880 MI = PotentialAND;
2881 break;
2882 }
2883 if () return false;
2884 }
2885 }
2886
2887
2890
2891
2892 if (I == B) return false;
2893
2894
2895
2896
2897
2898
2900 if (SrcReg2 != 0)
2901
2902 MI = nullptr;
2903 else if (MI->getParent() != CmpInstr.getParent() || CmpValue != 0) {
2904
2905
2906
2907
2908 if (CmpInstr.getOpcode() == ARM::CMPri ||
2909 CmpInstr.getOpcode() == ARM::t2CMPri ||
2910 CmpInstr.getOpcode() == ARM::tCMPi8)
2911 MI = nullptr;
2912 else
2913 return false;
2914 }
2915
2916 bool IsThumb1 = false;
2918 return false;
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2933 if (MI && IsThumb1) {
2934 --I;
2935 if (I != E && ->readsRegister(ARM::CPSR, TRI)) {
2936 bool CanReorder = true;
2938 if (I->getOpcode() != ARM::tMOVi8) {
2939 CanReorder = false;
2940 break;
2941 }
2942 }
2943 if (CanReorder) {
2944 MI = MI->removeFromParent();
2945 E = CmpInstr;
2947 }
2948 }
2949 I = CmpInstr;
2950 E = MI;
2951 }
2952
2953
2954
2955 bool SubAddIsThumb1 = false;
2956 do {
2958
2959
2961 SubAddIsThumb1)) {
2962 SubAdd = &*I;
2963 break;
2964 }
2965
2966
2967 if (I == E)
2968 break;
2969
2970 if (Instr.modifiesRegister(ARM::CPSR, TRI) ||
2971 Instr.readsRegister(ARM::CPSR, TRI))
2972
2973
2974 return false;
2975
2977
2978
2979
2980
2981
2982 return false;
2983 }
2984 } while (true);
2985
2986
2987 if ( && !SubAdd)
2988 return false;
2989
2990
2991 if (SubAdd) {
2992 MI = SubAdd;
2993 IsThumb1 = SubAddIsThumb1;
2994 }
2995
2996
2998 return false;
2999
3000
3001
3002
3003
3004
3005
3007 OperandsToUpdate;
3008 bool isSafe = false;
3009 I = CmpInstr;
3011 while (!isSafe && ++I != E) {
3013 for (unsigned IO = 0, EO = Instr.getNumOperands();
3014 !isSafe && IO != EO; ++IO) {
3017 isSafe = true;
3018 break;
3019 }
3020 if (!MO.isReg() || MO.getReg() != ARM::CPSR)
3021 continue;
3022 if (MO.isDef()) {
3023 isSafe = true;
3024 break;
3025 }
3026
3028 bool IsInstrVSel = true;
3029 switch (Instr.getOpcode()) {
3030 default:
3031 IsInstrVSel = false;
3033 break;
3034 case ARM::VSELEQD:
3035 case ARM::VSELEQS:
3036 case ARM::VSELEQH:
3038 break;
3039 case ARM::VSELGTD:
3040 case ARM::VSELGTS:
3041 case ARM::VSELGTH:
3043 break;
3044 case ARM::VSELGED:
3045 case ARM::VSELGES:
3046 case ARM::VSELGEH:
3048 break;
3049 case ARM::VSELVSD:
3050 case ARM::VSELVSS:
3051 case ARM::VSELVSH:
3053 break;
3054 }
3055
3056 if (SubAdd) {
3057
3058
3059
3060
3061
3062
3063
3065 bool IsSub = Opc == ARM::SUBrr || Opc == ARM::t2SUBrr ||
3066 Opc == ARM::SUBri || Opc == ARM::t2SUBri ||
3067 Opc == ARM::tSUBrr || Opc == ARM::tSUBi3 ||
3068 Opc == ARM::tSUBi8;
3069 unsigned OpI = Opc != ARM::tSUBrr ? 1 : 2;
3070 if (!IsSub ||
3071 (SrcReg2 != 0 && SubAdd->getOperand(OpI).getReg() == SrcReg2 &&
3073
3074 if (IsInstrVSel)
3075 return false;
3076
3079 return false;
3081 std::make_pair(&((*I).getOperand(IO - 1)), NewCC));
3082 }
3083 } else {
3084
3085 switch (CC) {
3091
3092 break;
3103
3104 return false;
3105 }
3106 }
3107 }
3108 }
3109
3110
3111
3112 if (!isSafe) {
3115 if (Succ->isLiveIn(ARM::CPSR))
3116 return false;
3117 }
3118
3119
3120
3121 if (!IsThumb1) {
3122 unsigned CPSRRegNum = MI->getNumExplicitOperands() - 1;
3123 MI->getOperand(CPSRRegNum).setReg(ARM::CPSR);
3124 MI->getOperand(CPSRRegNum).setIsDef(true);
3125 }
3126 assert((*MI) && "Can't use flags from predicated instruction");
3128
3129
3130
3131
3132 for (auto &[MO, Cond] : OperandsToUpdate)
3133 MO->setImm(Cond);
3134
3135 MI->clearRegisterDeads(ARM::CPSR);
3136
3137 return true;
3138}
3139
3141
3142
3143
3145 return true;
3149 int64_t CmpMask, CmpValue;
3150 bool IsThumb1;
3151 if (Next != MI.getParent()->end() &&
3154 return false;
3155 return true;
3156}
3157
3161
3162 unsigned DefOpc = DefMI.getOpcode();
3163 if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm &&
3164 DefOpc != ARM::tMOVi32imm)
3165 return false;
3166 if (.getOperand(1).isImm())
3167
3168 return false;
3169
3170 if (->hasOneNonDBGUse(Reg))
3171 return false;
3172
3177 if (MO.getReg() == ARM::CPSR && !MO.isDead())
3178
3179
3180 return false;
3181 }
3182
3186 if (UseMI.getOperand(NumOps - 1).getReg() == ARM::CPSR)
3187
3188
3189 return false;
3190 }
3191
3192 unsigned UseOpc = UseMI.getOpcode();
3193 unsigned NewUseOpc = 0;
3195 uint32_t SOImmValV1 = 0, SOImmValV2 = 0;
3196 bool Commute = false;
3197 switch (UseOpc) {
3198 default: return false;
3199 case ARM::SUBrr:
3200 case ARM::ADDrr:
3201 case ARM::ORRrr:
3202 case ARM::EORrr:
3203 case ARM::t2SUBrr:
3204 case ARM::t2ADDrr:
3205 case ARM::t2ORRrr:
3206 case ARM::t2EORrr: {
3207 Commute = UseMI.getOperand(2).getReg() != Reg;
3208 switch (UseOpc) {
3209 default: break;
3210 case ARM::ADDrr:
3211 case ARM::SUBrr:
3212 if (UseOpc == ARM::SUBrr && Commute)
3213 return false;
3214
3215
3216
3218 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::ADDri : ARM::SUBri;
3220 ImmVal = -ImmVal;
3221 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::SUBri : ARM::ADDri;
3222 } else
3223 return false;
3226 break;
3227 case ARM::ORRrr:
3228 case ARM::EORrr:
3230 return false;
3233 switch (UseOpc) {
3234 default: break;
3235 case ARM::ORRrr: NewUseOpc = ARM::ORRri; break;
3236 case ARM::EORrr: NewUseOpc = ARM::EORri; break;
3237 }
3238 break;
3239 case ARM::t2ADDrr:
3240 case ARM::t2SUBrr: {
3241 if (UseOpc == ARM::t2SUBrr && Commute)
3242 return false;
3243
3244
3245
3246 const bool ToSP = DefMI.getOperand(0).getReg() == ARM::SP;
3247 const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
3248 const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
3250 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB;
3252 ImmVal = -ImmVal;
3253 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD;
3254 } else
3255 return false;
3258 break;
3259 }
3260 case ARM::t2ORRrr:
3261 case ARM::t2EORrr:
3263 return false;
3266 switch (UseOpc) {
3267 default: break;
3268 case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri; break;
3269 case ARM::t2EORrr: NewUseOpc = ARM::t2EORri; break;
3270 }
3271 break;
3272 }
3273 }
3274 }
3275
3276 unsigned OpIdx = Commute ? 2 : 1;
3278 bool isKill = UseMI.getOperand(OpIdx).isKill();
3280 Register NewReg = MRI->createVirtualRegister(TRC);
3282 NewReg)
3287 UseMI.setDesc(get(NewUseOpc));
3288 UseMI.getOperand(1).setReg(NewReg);
3289 UseMI.getOperand(1).setIsKill();
3290 UseMI.getOperand(2).ChangeToImmediate(SOImmValV2);
3291 DefMI.eraseFromParent();
3292
3293
3294
3295
3296
3297 switch(NewUseOpc){
3298 case ARM::t2ADDspImm:
3299 case ARM::t2SUBspImm:
3300 case ARM::t2ADDri:
3301 case ARM::t2SUBri:
3302 MRI->constrainRegClass(UseMI.getOperand(0).getReg(), TRC);
3303 }
3304 return true;
3305}
3306
3309 switch (MI.getOpcode()) {
3310 default: {
3313 assert(UOps >= 0 && "bad # UOps");
3314 return UOps;
3315 }
3316
3317 case ARM::LDRrs:
3318 case ARM::LDRBrs:
3319 case ARM::STRrs:
3320 case ARM::STRBrs: {
3321 unsigned ShOpVal = MI.getOperand(3).getImm();
3324 if (!isSub &&
3325 (ShImm == 0 ||
3326 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3328 return 1;
3329 return 2;
3330 }
3331
3332 case ARM::LDRH:
3333 case ARM::STRH: {
3334 if (.getOperand(2).getReg())
3335 return 1;
3336
3337 unsigned ShOpVal = MI.getOperand(3).getImm();
3340 if (!isSub &&
3341 (ShImm == 0 ||
3342 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3344 return 1;
3345 return 2;
3346 }
3347
3348 case ARM::LDRSB:
3349 case ARM::LDRSH:
3351
3352 case ARM::LDRSB_POST:
3353 case ARM::LDRSH_POST: {
3354 Register Rt = MI.getOperand(0).getReg();
3355 Register Rm = MI.getOperand(3).getReg();
3356 return (Rt == Rm) ? 4 : 3;
3357 }
3358
3359 case ARM::LDR_PRE_REG:
3360 case ARM::LDRB_PRE_REG: {
3361 Register Rt = MI.getOperand(0).getReg();
3362 Register Rm = MI.getOperand(3).getReg();
3363 if (Rt == Rm)
3364 return 3;
3365 unsigned ShOpVal = MI.getOperand(4).getImm();
3368 if (!isSub &&
3369 (ShImm == 0 ||
3370 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3372 return 2;
3373 return 3;
3374 }
3375
3376 case ARM::STR_PRE_REG:
3377 case ARM::STRB_PRE_REG: {
3378 unsigned ShOpVal = MI.getOperand(4).getImm();
3381 if (!isSub &&
3382 (ShImm == 0 ||
3383 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3385 return 2;
3386 return 3;
3387 }
3388
3389 case ARM::LDRH_PRE:
3390 case ARM::STRH_PRE: {
3391 Register Rt = MI.getOperand(0).getReg();
3392 Register Rm = MI.getOperand(3).getReg();
3393 if (!Rm)
3394 return 2;
3395 if (Rt == Rm)
3396 return 3;
3398 }
3399
3400 case ARM::LDR_POST_REG:
3401 case ARM::LDRB_POST_REG:
3402 case ARM::LDRH_POST: {
3403 Register Rt = MI.getOperand(0).getReg();
3404 Register Rm = MI.getOperand(3).getReg();
3405 return (Rt == Rm) ? 3 : 2;
3406 }
3407
3408 case ARM::LDR_PRE_IMM:
3409 case ARM::LDRB_PRE_IMM:
3410 case ARM::LDR_POST_IMM:
3411 case ARM::LDRB_POST_IMM:
3412 case ARM::STRB_POST_IMM:
3413 case ARM::STRB_POST_REG:
3414 case ARM::STRB_PRE_IMM:
3415 case ARM::STRH_POST:
3416 case ARM::STR_POST_IMM:
3417 case ARM::STR_POST_REG:
3418 case ARM::STR_PRE_IMM:
3419 return 2;
3420
3421 case ARM::LDRSB_PRE:
3422 case ARM::LDRSH_PRE: {
3423 Register Rm = MI.getOperand(3).getReg();
3424 if (Rm == 0)
3425 return 3;
3426 Register Rt = MI.getOperand(0).getReg();
3427 if (Rt == Rm)
3428 return 4;
3429 unsigned ShOpVal = MI.getOperand(4).getImm();
3432 if (!isSub &&
3433 (ShImm == 0 ||
3434 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
3436 return 3;
3437 return 4;
3438 }
3439
3440 case ARM::LDRD: {
3441 Register Rt = MI.getOperand(0).getReg();
3442 Register Rn = MI.getOperand(2).getReg();
3443 Register Rm = MI.getOperand(3).getReg();
3444 if (Rm)
3446 : 3;
3447 return (Rt == Rn) ? 3 : 2;
3448 }
3449
3450 case ARM::STRD: {
3451 Register Rm = MI.getOperand(3).getReg();
3452 if (Rm)
3454 : 3;
3455 return 2;
3456 }
3457
3458 case ARM::LDRD_POST:
3459 case ARM::t2LDRD_POST:
3460 return 3;
3461
3462 case ARM::STRD_POST:
3463 case ARM::t2STRD_POST:
3464 return 4;
3465
3466 case ARM::LDRD_PRE: {
3467 Register Rt = MI.getOperand(0).getReg();
3468 Register Rn = MI.getOperand(3).getReg();
3469 Register Rm = MI.getOperand(4).getReg();
3470 if (Rm)
3472 : 4;
3473 return (Rt == Rn) ? 4 : 3;
3474 }
3475
3476 case ARM::t2LDRD_PRE: {
3477 Register Rt = MI.getOperand(0).getReg();
3478 Register Rn = MI.getOperand(3).getReg();
3479 return (Rt == Rn) ? 4 : 3;
3480 }
3481
3482 case ARM::STRD_PRE: {
3483 Register Rm = MI.getOperand(4).getReg();
3484 if (Rm)
3486 : 4;
3487 return 3;
3488 }
3489
3490 case ARM::t2STRD_PRE:
3491 return 3;
3492
3493 case ARM::t2LDR_POST:
3494 case ARM::t2LDRB_POST:
3495 case ARM::t2LDRB_PRE:
3496 case ARM::t2LDRSBi12:
3497 case ARM::t2LDRSBi8:
3498 case ARM::t2LDRSBpci:
3499 case ARM::t2LDRSBs:
3500 case ARM::t2LDRH_POST:
3501 case ARM::t2LDRH_PRE:
3502 case ARM::t2LDRSBT:
3503 case ARM::t2LDRSB_POST:
3504 case ARM::t2LDRSB_PRE:
3505 case ARM::t2LDRSH_POST:
3506 case ARM::t2LDRSH_PRE:
3507 case ARM::t2LDRSHi12:
3508 case ARM::t2LDRSHi8:
3509 case ARM::t2LDRSHpci:
3510 case ARM::t2LDRSHs:
3511 return 2;
3512
3513 case ARM::t2LDRDi8: {
3514 Register Rt = MI.getOperand(0).getReg();
3515 Register Rn = MI.getOperand(2).getReg();
3516 return (Rt == Rn) ? 3 : 2;
3517 }
3518
3519 case ARM::t2STRB_POST:
3520 case ARM::t2STRB_PRE:
3521 case ARM::t2STRBs:
3522 case ARM::t2STRDi8:
3523 case ARM::t2STRH_POST:
3524 case ARM::t2STRH_PRE:
3525 case ARM::t2STRHs:
3526 case ARM::t2STR_POST:
3527 case ARM::t2STR_PRE:
3528 case ARM::t2STRs:
3529 return 2;
3530 }
3531}
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3556 unsigned Size = 0;
3558 E = MI.memoperands_end();
3560 Size += (*I)->getSize().getValue();
3561 }
3562
3563
3564
3565
3566
3567 return std::min(Size / 4, 16U);
3568}
3569
3571 unsigned NumRegs) {
3572 unsigned UOps = 1 + NumRegs;
3573 switch (Opc) {
3574 default:
3575 break;
3576 case ARM::VLDMDIA_UPD:
3577 case ARM::VLDMDDB_UPD:
3578 case ARM::VLDMSIA_UPD:
3579 case ARM::VLDMSDB_UPD:
3580 case ARM::VSTMDIA_UPD:
3581 case ARM::VSTMDDB_UPD:
3582 case ARM::VSTMSIA_UPD:
3583 case ARM::VSTMSDB_UPD:
3584 case ARM::LDMIA_UPD:
3585 case ARM::LDMDA_UPD:
3586 case ARM::LDMDB_UPD:
3587 case ARM::LDMIB_UPD:
3588 case ARM::STMIA_UPD:
3589 case ARM::STMDA_UPD:
3590 case ARM::STMDB_UPD:
3591 case ARM::STMIB_UPD:
3592 case ARM::tLDMIA_UPD:
3593 case ARM::tSTMIA_UPD:
3594 case ARM::t2LDMIA_UPD:
3595 case ARM::t2LDMDB_UPD:
3596 case ARM::t2STMIA_UPD:
3597 case ARM::t2STMDB_UPD:
3598 ++UOps;
3599 break;
3600 case ARM::LDMIA_RET:
3601 case ARM::tPOP_RET:
3602 case ARM::t2LDMIA_RET:
3603 UOps += 2;
3604 break;
3605 }
3606 return UOps;
3607}
3608
3611 if (!ItinData || ItinData->isEmpty())
3612 return 1;
3613
3615 unsigned Class = Desc.getSchedClass();
3617 if (ItinUOps >= 0) {
3618 if (Subtarget.isSwift() && (Desc.mayLoad() || Desc.mayStore()))
3620
3621 return ItinUOps;
3622 }
3623
3624 unsigned Opc = MI.getOpcode();
3625 switch (Opc) {
3626 default:
3628 case ARM::VLDMQIA:
3629 case ARM::VSTMQIA:
3630 return 2;
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642 case ARM::VLDMDIA:
3643 case ARM::VLDMDIA_UPD:
3644 case ARM::VLDMDDB_UPD:
3645 case ARM::VLDMSIA:
3646 case ARM::VLDMSIA_UPD:
3647 case ARM::VLDMSDB_UPD:
3648 case ARM::VSTMDIA:
3649 case ARM::VSTMDIA_UPD:
3650 case ARM::VSTMDDB_UPD:
3651 case ARM::VSTMSIA:
3652 case ARM::VSTMSIA_UPD:
3653 case ARM::VSTMSDB_UPD: {
3654 unsigned NumRegs = MI.getNumOperands() - Desc.getNumOperands();
3655 return (NumRegs / 2) + (NumRegs % 2) + 1;
3656 }
3657
3658 case ARM::LDMIA_RET:
3659 case ARM::LDMIA:
3660 case ARM::LDMDA:
3661 case ARM::LDMDB:
3662 case ARM::LDMIB:
3663 case ARM::LDMIA_UPD:
3664 case ARM::LDMDA_UPD:
3665 case ARM::LDMDB_UPD:
3666 case ARM::LDMIB_UPD:
3667 case ARM::STMIA:
3668 case ARM::STMDA:
3669 case ARM::STMDB:
3670 case ARM::STMIB:
3671 case ARM::STMIA_UPD:
3672 case ARM::STMDA_UPD:
3673 case ARM::STMDB_UPD:
3674 case ARM::STMIB_UPD:
3675 case ARM::tLDMIA:
3676 case ARM::tLDMIA_UPD:
3677 case ARM::tSTMIA_UPD:
3678 case ARM::tPOP_RET:
3679 case ARM::tPOP:
3680 case ARM::tPUSH:
3681 case ARM::t2LDMIA_RET:
3682 case ARM::t2LDMIA:
3683 case ARM::t2LDMDB:
3684 case ARM::t2LDMIA_UPD:
3685 case ARM::t2LDMDB_UPD:
3686 case ARM::t2STMIA:
3687 case ARM::t2STMDB:
3688 case ARM::t2STMIA_UPD:
3689 case ARM::t2STMDB_UPD: {
3690 unsigned NumRegs = MI.getNumOperands() - Desc.getNumOperands() + 1;
3691 switch (Subtarget.getLdStMultipleTiming()) {
3695
3696 return NumRegs;
3698 if (NumRegs < 4)
3699 return 2;
3700
3701
3702 unsigned UOps = (NumRegs / 2);
3703 if (NumRegs % 2)
3704 ++UOps;
3705 return UOps;
3706 }
3708 unsigned UOps = (NumRegs / 2);
3709
3710
3711 if ((NumRegs % 2) || .hasOneMemOperand() ||
3712 (*MI.memoperands_begin())->getAlign() < Align(8))
3713 ++UOps;
3714 return UOps;
3715 }
3716 }
3717 }
3718 }
3720}
3721
3722std::optional
3723ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData,
3724 const MCInstrDesc &DefMCID, unsigned DefClass,
3725 unsigned DefIdx, unsigned DefAlign) const {
3726 int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1;
3727 if (RegNo <= 0)
3728
3730
3731 unsigned DefCycle;
3733
3734 DefCycle = RegNo / 2 + 1;
3735 if (RegNo % 2)
3736 ++DefCycle;
3737 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3738 DefCycle = RegNo;
3739 bool isSLoad = false;
3740
3742 default: break;
3743 case ARM::VLDMSIA:
3744 case ARM::VLDMSIA_UPD:
3745 case ARM::VLDMSDB_UPD:
3746 isSLoad = true;
3747 break;
3748 }
3749
3750
3751
3752 if ((isSLoad && (RegNo % 2)) || DefAlign < 8)
3753 ++DefCycle;
3754 } else {
3755
3756 DefCycle = RegNo + 2;
3757 }
3758
3759 return DefCycle;
3760}
3761
3762std::optional
3764 const MCInstrDesc &DefMCID, unsigned DefClass,
3765 unsigned DefIdx, unsigned DefAlign) const {
3766 int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1;
3767 if (RegNo <= 0)
3768
3770
3771 unsigned DefCycle;
3772 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3773
3774
3775 DefCycle = RegNo / 2;
3776 if (DefCycle < 1)
3777 DefCycle = 1;
3778
3779 DefCycle += 2;
3780 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3781 DefCycle = (RegNo / 2);
3782
3783
3784 if ((RegNo % 2) || DefAlign < 8)
3785 ++DefCycle;
3786
3787 DefCycle += 2;
3788 } else {
3789
3790 DefCycle = RegNo + 2;
3791 }
3792
3793 return DefCycle;
3794}
3795
3796std::optional
3797ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData,
3798 const MCInstrDesc &UseMCID, unsigned UseClass,
3799 unsigned UseIdx, unsigned UseAlign) const {
3800 int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1;
3801 if (RegNo <= 0)
3803
3804 unsigned UseCycle;
3805 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3806
3807 UseCycle = RegNo / 2 + 1;
3808 if (RegNo % 2)
3809 ++UseCycle;
3810 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3811 UseCycle = RegNo;
3812 bool isSStore = false;
3813
3815 default: break;
3816 case ARM::VSTMSIA:
3817 case ARM::VSTMSIA_UPD:
3818 case ARM::VSTMSDB_UPD:
3819 isSStore = true;
3820 break;
3821 }
3822
3823
3824
3825 if ((isSStore && (RegNo % 2)) || UseAlign < 8)
3826 ++UseCycle;
3827 } else {
3828
3829 UseCycle = RegNo + 2;
3830 }
3831
3832 return UseCycle;
3833}
3834
3835std::optional
3837 const MCInstrDesc &UseMCID, unsigned UseClass,
3838 unsigned UseIdx, unsigned UseAlign) const {
3839 int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1;
3840 if (RegNo <= 0)
3842
3843 unsigned UseCycle;
3844 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {
3845 UseCycle = RegNo / 2;
3846 if (UseCycle < 2)
3847 UseCycle = 2;
3848
3849 UseCycle += 2;
3850 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {
3851 UseCycle = (RegNo / 2);
3852
3853
3854 if ((RegNo % 2) || UseAlign < 8)
3855 ++UseCycle;
3856 } else {
3857
3858 UseCycle = 1;
3859 }
3860 return UseCycle;
3861}
3862
3865 unsigned DefIdx, unsigned DefAlign, const MCInstrDesc &UseMCID,
3866 unsigned UseIdx, unsigned UseAlign) const {
3869
3871 return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx);
3872
3873
3874
3875
3876 std::optional DefCycle;
3877 bool LdmBypass = false;
3879 default:
3881 break;
3882
3883 case ARM::VLDMDIA:
3884 case ARM::VLDMDIA_UPD:
3885 case ARM::VLDMDDB_UPD:
3886 case ARM::VLDMSIA:
3887 case ARM::VLDMSIA_UPD:
3888 case ARM::VLDMSDB_UPD:
3889 DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3890 break;
3891
3892 case ARM::LDMIA_RET:
3893 case ARM::LDMIA:
3894 case ARM::LDMDA:
3895 case ARM::LDMDB:
3896 case ARM::LDMIB:
3897 case ARM::LDMIA_UPD:
3898 case ARM::LDMDA_UPD:
3899 case ARM::LDMDB_UPD:
3900 case ARM::LDMIB_UPD:
3901 case ARM::tLDMIA:
3902 case ARM::tLDMIA_UPD:
3903 case ARM::tPUSH:
3904 case ARM::t2LDMIA_RET:
3905 case ARM::t2LDMIA:
3906 case ARM::t2LDMDB:
3907 case ARM::t2LDMIA_UPD:
3908 case ARM::t2LDMDB_UPD:
3909 LdmBypass = true;
3910 DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);
3911 break;
3912 }
3913
3914 if (!DefCycle)
3915
3916 DefCycle = 2;
3917
3918 std::optional UseCycle;
3920 default:
3922 break;
3923
3924 case ARM::VSTMDIA:
3925 case ARM::VSTMDIA_UPD:
3926 case ARM::VSTMDDB_UPD:
3927 case ARM::VSTMSIA:
3928 case ARM::VSTMSIA_UPD:
3929 case ARM::VSTMSDB_UPD:
3930 UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3931 break;
3932
3933 case ARM::STMIA:
3934 case ARM::STMDA:
3935 case ARM::STMDB:
3936 case ARM::STMIB:
3937 case ARM::STMIA_UPD:
3938 case ARM::STMDA_UPD:
3939 case ARM::STMDB_UPD:
3940 case ARM::STMIB_UPD:
3941 case ARM::tSTMIA_UPD:
3942 case ARM::tPOP_RET:
3943 case ARM::tPOP:
3944 case ARM::t2STMIA:
3945 case ARM::t2STMDB:
3946 case ARM::t2STMIA_UPD:
3947 case ARM::t2STMDB_UPD:
3948 UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);
3949 break;
3950 }
3951
3952 if (!UseCycle)
3953
3954 UseCycle = 1;
3955
3956 if (UseCycle > *DefCycle + 1)
3957 return std::nullopt;
3958
3959 UseCycle = *DefCycle - *UseCycle + 1;
3960 if (UseCycle > 0u) {
3961 if (LdmBypass) {
3962
3963
3965 UseClass, UseIdx))
3966 UseCycle = *UseCycle - 1;
3968 UseClass, UseIdx)) {
3969 UseCycle = *UseCycle - 1;
3970 }
3971 }
3972
3973 return UseCycle;
3974}
3975
3978 unsigned &DefIdx, unsigned &Dist) {
3979 Dist = 0;
3980
3983 assert(II->isInsideBundle() && "Empty bundle?");
3984
3985 int Idx = -1;
3986 while (II->isInsideBundle()) {
3987 Idx = II->findRegisterDefOperandIdx(Reg, TRI, false, true);
3988 if (Idx != -1)
3989 break;
3990 --II;
3991 ++Dist;
3992 }
3993
3994 assert(Idx != -1 && "Cannot find bundled definition!");
3995 DefIdx = Idx;
3996 return &*II;
3997}
3998
4001 unsigned &UseIdx, unsigned &Dist) {
4002 Dist = 0;
4003
4005 assert(II->isInsideBundle() && "Empty bundle?");
4007
4008
4009 int Idx = -1;
4010 while (II != E && II->isInsideBundle()) {
4011 Idx = II->findRegisterUseOperandIdx(Reg, TRI, false);
4012 if (Idx != -1)
4013 break;
4014 if (II->getOpcode() != ARM::t2IT)
4015 ++Dist;
4016 ++II;
4017 }
4018
4019 if (Idx == -1) {
4020 Dist = 0;
4021 return nullptr;
4022 }
4023
4024 UseIdx = Idx;
4025 return &*II;
4026}
4027
4028
4029
4030
4033 const MCInstrDesc &DefMCID, unsigned DefAlign) {
4034 int Adjust = 0;
4036
4037
4039 default: break;
4040 case ARM::LDRrs:
4041 case ARM::LDRBrs: {
4042 unsigned ShOpVal = DefMI.getOperand(3).getImm();
4044 if (ShImm == 0 ||
4046 --Adjust;
4047 break;
4048 }
4049 case ARM::t2LDRs:
4050 case ARM::t2LDRBs:
4051 case ARM::t2LDRHs:
4052 case ARM::t2LDRSHs: {
4053
4054 unsigned ShAmt = DefMI.getOperand(3).getImm();
4055 if (ShAmt == 0 || ShAmt == 2)
4056 --Adjust;
4057 break;
4058 }
4059 }
4060 } else if (Subtarget.isSwift()) {
4061
4062
4064 default: break;
4065 case ARM::LDRrs:
4066 case ARM::LDRBrs: {
4067 unsigned ShOpVal = DefMI.getOperand(3).getImm();
4070 if (!isSub &&
4071 (ShImm == 0 ||
4072 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4074 Adjust -= 2;
4075 else if (!isSub &&
4077 --Adjust;
4078 break;
4079 }
4080 case ARM::t2LDRs:
4081 case ARM::t2LDRBs:
4082 case ARM::t2LDRHs:
4083 case ARM::t2LDRSHs: {
4084
4085 unsigned ShAmt = DefMI.getOperand(3).getImm();
4086 if (ShAmt == 0 || ShAmt == 1 || ShAmt == 2 || ShAmt == 3)
4087 Adjust -= 2;
4088 break;
4089 }
4090 }
4091 }
4092
4093 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment()) {
4095 default: break;
4096 case ARM::VLD1q8:
4097 case ARM::VLD1q16:
4098 case ARM::VLD1q32:
4099 case ARM::VLD1q64:
4100 case ARM::VLD1q8wb_fixed:
4101 case ARM::VLD1q16wb_fixed:
4102 case ARM::VLD1q32wb_fixed:
4103 case ARM::VLD1q64wb_fixed:
4104 case ARM::VLD1q8wb_register:
4105 case ARM::VLD1q16wb_register:
4106 case ARM::VLD1q32wb_register:
4107 case ARM::VLD1q64wb_register:
4108 case ARM::VLD2d8:
4109 case ARM::VLD2d16:
4110 case ARM::VLD2d32:
4111 case ARM::VLD2q8:
4112 case ARM::VLD2q16:
4113 case ARM::VLD2q32:
4114 case ARM::VLD2d8wb_fixed:
4115 case ARM::VLD2d16wb_fixed:
4116 case ARM::VLD2d32wb_fixed:
4117 case ARM::VLD2q8wb_fixed:
4118 case ARM::VLD2q16wb_fixed:
4119 case ARM::VLD2q32wb_fixed:
4120 case ARM::VLD2d8wb_register:
4121 case ARM::VLD2d16wb_register:
4122 case ARM::VLD2d32wb_register:
4123 case ARM::VLD2q8wb_register:
4124 case ARM::VLD2q16wb_register:
4125 case ARM::VLD2q32wb_register:
4126 case ARM::VLD3d8:
4127 case ARM::VLD3d16:
4128 case ARM::VLD3d32:
4129 case ARM::VLD1d64T:
4130 case ARM::VLD3d8_UPD:
4131 case ARM::VLD3d16_UPD:
4132 case ARM::VLD3d32_UPD:
4133 case ARM::VLD1d64Twb_fixed:
4134 case ARM::VLD1d64Twb_register:
4135 case ARM::VLD3q8_UPD:
4136 case ARM::VLD3q16_UPD:
4137 case ARM::VLD3q32_UPD:
4138 case ARM::VLD4d8:
4139 case ARM::VLD4d16:
4140 case ARM::VLD4d32:
4141 case ARM::VLD1d64Q:
4142 case ARM::VLD4d8_UPD:
4143 case ARM::VLD4d16_UPD:
4144 case ARM::VLD4d32_UPD:
4145 case ARM::VLD1d64Qwb_fixed:
4146 case ARM::VLD1d64Qwb_register:
4147 case ARM::VLD4q8_UPD:
4148 case ARM::VLD4q16_UPD:
4149 case ARM::VLD4q32_UPD:
4150 case ARM::VLD1DUPq8:
4151 case ARM::VLD1DUPq16:
4152 case ARM::VLD1DUPq32:
4153 case ARM::VLD1DUPq8wb_fixed:
4154 case ARM::VLD1DUPq16wb_fixed:
4155 case ARM::VLD1DUPq32wb_fixed:
4156 case ARM::VLD1DUPq8wb_register:
4157 case ARM::VLD1DUPq16wb_register:
4158 case ARM::VLD1DUPq32wb_register:
4159 case ARM::VLD2DUPd8:
4160 case ARM::VLD2DUPd16:
4161 case ARM::VLD2DUPd32:
4162 case ARM::VLD2DUPd8wb_fixed:
4163 case ARM::VLD2DUPd16wb_fixed:
4164 case ARM::VLD2DUPd32wb_fixed:
4165 case ARM::VLD2DUPd8wb_register:
4166 case ARM::VLD2DUPd16wb_register:
4167 case ARM::VLD2DUPd32wb_register:
4168 case ARM::VLD4DUPd8:
4169 case ARM::VLD4DUPd16:
4170 case ARM::VLD4DUPd32:
4171 case ARM::VLD4DUPd8_UPD:
4172 case ARM::VLD4DUPd16_UPD:
4173 case ARM::VLD4DUPd32_UPD:
4174 case ARM::VLD1LNd8:
4175 case ARM::VLD1LNd16:
4176 case ARM::VLD1LNd32:
4177 case ARM::VLD1LNd8_UPD:
4178 case ARM::VLD1LNd16_UPD:
4179 case ARM::VLD1LNd32_UPD:
4180 case ARM::VLD2LNd8:
4181 case ARM::VLD2LNd16:
4182 case ARM::VLD2LNd32:
4183 case ARM::VLD2LNq16:
4184 case ARM::VLD2LNq32:
4185 case ARM::VLD2LNd8_UPD:
4186 case ARM::VLD2LNd16_UPD:
4187 case ARM::VLD2LNd32_UPD:
4188 case ARM::VLD2LNq16_UPD:
4189 case ARM::VLD2LNq32_UPD:
4190 case ARM::VLD4LNd8:
4191 case ARM::VLD4LNd16:
4192 case ARM::VLD4LNd32:
4193 case ARM::VLD4LNq16:
4194 case ARM::VLD4LNq32:
4195 case ARM::VLD4LNd8_UPD:
4196 case ARM::VLD4LNd16_UPD:
4197 case ARM::VLD4LNd32_UPD:
4198 case ARM::VLD4LNq16_UPD:
4199 case ARM::VLD4LNq32_UPD:
4200
4201
4202 ++Adjust;
4203 break;
4204 }
4205 }
4206 return Adjust;
4207}
4208
4211 unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const {
4212
4213 if (!ItinData || ItinData->isEmpty())
4214 return std::nullopt;
4215
4218
4220 unsigned DefAdj = 0;
4221 if (DefMI.isBundle())
4222 ResolvedDefMI =
4226 return 1;
4227 }
4228
4230 unsigned UseAdj = 0;
4231 if (UseMI.isBundle()) {
4232 ResolvedUseMI =
4234 if (!ResolvedUseMI)
4235 return std::nullopt;
4236 }
4237
4238 return getOperandLatencyImpl(
4239 ItinData, *ResolvedDefMI, DefIdx, ResolvedDefMI->getDesc(), DefAdj, DefMO,
4240 Reg, *ResolvedUseMI, UseIdx, ResolvedUseMI->getDesc(), UseAdj);
4241}
4242
4243std::optional ARMBaseInstrInfo::getOperandLatencyImpl(
4245 unsigned DefIdx, const MCInstrDesc &DefMCID, unsigned DefAdj,
4247 unsigned UseIdx, const MCInstrDesc &UseMCID, unsigned UseAdj) const {
4248 if (Reg == ARM::CPSR) {
4249 if (DefMI.getOpcode() == ARM::FMSTAT) {
4250
4251 return Subtarget.isLikeA9() ? 1 : 20;
4252 }
4253
4254
4255 if (UseMI.isBranch())
4256 return 0;
4257
4258
4259 unsigned Latency = getInstrLatency(ItinData, DefMI);
4260
4261
4262
4263
4264
4269 }
4271 }
4272
4273 if (DefMO.isImplicit() || UseMI.getOperand(UseIdx).isImplicit())
4274 return std::nullopt;
4275
4276 unsigned DefAlign = DefMI.hasOneMemOperand()
4277 ? (*DefMI.memoperands_begin())->getAlign().value()
4278 : 0;
4279 unsigned UseAlign = UseMI.hasOneMemOperand()
4280 ? (*UseMI.memoperands_begin())->getAlign().value()
4281 : 0;
4282
4283
4285 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4286
4288 return std::nullopt;
4289
4290
4291 int Adj = DefAdj + UseAdj;
4292
4293
4295 if (Adj >= 0 || (int)*Latency > -Adj) {
4297 }
4298
4300}
4301
4302std::optional
4304 SDNode *DefNode, unsigned DefIdx,
4305 SDNode *UseNode, unsigned UseIdx) const {
4307 return 1;
4308
4310
4311 if (isZeroCost(DefMCID.Opcode))
4312 return 0;
4313
4314 if (!ItinData || ItinData->isEmpty())
4315 return DefMCID.mayLoad() ? 3 : 1;
4316
4318 std::optional Latency =
4320 int Adj = Subtarget.getPreISelOperandLatencyAdjustment();
4321 int Threshold = 1 + Adj;
4323 }
4324
4327 unsigned DefAlign = !DefMN->memoperands_empty()
4328 ? (*DefMN->memoperands_begin())->getAlign().value()
4329 : 0;
4331 unsigned UseAlign = !UseMN->memoperands_empty()
4332 ? (*UseMN->memoperands_begin())->getAlign().value()
4333 : 0;
4335 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);
4337 return std::nullopt;
4338
4340 (Subtarget.isCortexA8() || Subtarget.isLikeA9() ||
4341 Subtarget.isCortexA7())) {
4342
4343
4345 default: break;
4346 case ARM::LDRrs:
4347 case ARM::LDRBrs: {
4350 if (ShImm == 0 ||
4353 break;
4354 }
4355 case ARM::t2LDRs:
4356 case ARM::t2LDRBs:
4357 case ARM::t2LDRHs:
4358 case ARM::t2LDRSHs: {
4359
4361 if (ShAmt == 0 || ShAmt == 2)
4363 break;
4364 }
4365 }
4366 } else if (DefIdx == 0 && Latency > 2U && Subtarget.isSwift()) {
4367
4368
4370 default: break;
4371 case ARM::LDRrs:
4372 case ARM::LDRBrs: {
4375 if (ShImm == 0 ||
4376 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&
4381 break;
4382 }
4383 case ARM::t2LDRs:
4384 case ARM::t2LDRBs:
4385 case ARM::t2LDRHs:
4386 case ARM::t2LDRSHs:
4387
4389 break;
4390 }
4391 }
4392
4393 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment())
4395 default: break;
4396 case ARM::VLD1q8:
4397 case ARM::VLD1q16:
4398 case ARM::VLD1q32:
4399 case ARM::VLD1q64:
4400 case ARM::VLD1q8wb_register:
4401 case ARM::VLD1q16wb_register:
4402 case ARM::VLD1q32wb_register:
4403 case ARM::VLD1q64wb_register:
4404 case ARM::VLD1q8wb_fixed:
4405 case ARM::VLD1q16wb_fixed:
4406 case ARM::VLD1q32wb_fixed:
4407 case ARM::VLD1q64wb_fixed:
4408 case ARM::VLD2d8:
4409 case ARM::VLD2d16:
4410 case ARM::VLD2d32:
4411 case ARM::VLD2q8Pseudo:
4412 case ARM::VLD2q16Pseudo:
4413 case ARM::VLD2q32Pseudo:
4414 case ARM::VLD2d8wb_fixed:
4415 case ARM::VLD2d16wb_fixed:
4416 case ARM::VLD2d32wb_fixed:
4417 case ARM::VLD2q8PseudoWB_fixed:
4418 case ARM::VLD2q16PseudoWB_fixed:
4419 case ARM::VLD2q32PseudoWB_fixed:
4420 case ARM::VLD2d8wb_register:
4421 case ARM::VLD2d16wb_register:
4422 case ARM::VLD2d32wb_register:
4423 case ARM::VLD2q8PseudoWB_register:
4424 case ARM::VLD2q16PseudoWB_register:
4425 case ARM::VLD2q32PseudoWB_register:
4426 case ARM::VLD3d8Pseudo:
4427 case ARM::VLD3d16Pseudo:
4428 case ARM::VLD3d32Pseudo:
4429 case ARM::VLD1d8TPseudo:
4430 case ARM::VLD1d16TPseudo:
4431 case ARM::VLD1d32TPseudo:
4432 case ARM::VLD1d64TPseudo:
4433 case ARM::VLD1d64TPseudoWB_fixed:
4434 case ARM::VLD1d64TPseudoWB_register:
4435 case ARM::VLD3d8Pseudo_UPD:
4436 case ARM::VLD3d16Pseudo_UPD:
4437 case ARM::VLD3d32Pseudo_UPD:
4438 case ARM::VLD3q8Pseudo_UPD:
4439 case ARM::VLD3q16Pseudo_UPD:
4440 case ARM::VLD3q32Pseudo_UPD:
4441 case ARM::VLD3q8oddPseudo:
4442 case ARM::VLD3q16oddPseudo:
4443 case ARM::VLD3q32oddPseudo:
4444 case ARM::VLD3q8oddPseudo_UPD:
4445 case ARM::VLD3q16oddPseudo_UPD:
4446 case ARM::VLD3q32oddPseudo_UPD:
4447 case ARM::VLD4d8Pseudo:
4448 case ARM::VLD4d16Pseudo:
4449 case ARM::VLD4d32Pseudo:
4450 case ARM::VLD1d8QPseudo:
4451 case ARM::VLD1d16QPseudo:
4452 case ARM::VLD1d32QPseudo:
4453 case ARM::VLD1d64QPseudo:
4454 case ARM::VLD1d64QPseudoWB_fixed:
4455 case ARM::VLD1d64QPseudoWB_register:
4456 case ARM::VLD1q8HighQPseudo:
4457 case ARM::VLD1q8LowQPseudo_UPD:
4458 case ARM::VLD1q8HighTPseudo:
4459 case ARM::VLD1q8LowTPseudo_UPD:
4460 case ARM::VLD1q16HighQPseudo:
4461 case ARM::VLD1q16LowQPseudo_UPD:
4462 case ARM::VLD1q16HighTPseudo:
4463 case ARM::VLD1q16LowTPseudo_UPD:
4464 case ARM::VLD1q32HighQPseudo:
4465 case ARM::VLD1q32LowQPseudo_UPD:
4466 case ARM::VLD1q32HighTPseudo:
4467 case ARM::VLD1q32LowTPseudo_UPD:
4468 case ARM::VLD1q64HighQPseudo:
4469 case ARM::VLD1q64LowQPseudo_UPD:
4470 case ARM::VLD1q64HighTPseudo:
4471 case ARM::VLD1q64LowTPseudo_UPD:
4472 case ARM::VLD4d8Pseudo_UPD:
4473 case ARM::VLD4d16Pseudo_UPD:
4474 case ARM::VLD4d32Pseudo_UPD:
4475 case ARM::VLD4q8Pseudo_UPD:
4476 case ARM::VLD4q16Pseudo_UPD:
4477 case ARM::VLD4q32Pseudo_UPD:
4478 case ARM::VLD4q8oddPseudo:
4479 case ARM::VLD4q16oddPseudo:
4480 case ARM::VLD4q32oddPseudo:
4481 case ARM::VLD4q8oddPseudo_UPD:
4482 case ARM::VLD4q16oddPseudo_UPD:
4483 case ARM::VLD4q32oddPseudo_UPD:
4484 case ARM::VLD1DUPq8:
4485 case ARM::VLD1DUPq16:
4486 case ARM::VLD1DUPq32:
4487 case ARM::VLD1DUPq8wb_fixed:
4488 case ARM::VLD1DUPq16wb_fixed:
4489 case ARM::VLD1DUPq32wb_fixed:
4490 case ARM::VLD1DUPq8wb_register:
4491 case ARM::VLD1DUPq16wb_register:
4492 case ARM::VLD1DUPq32wb_register:
4493 case ARM::VLD2DUPd8:
4494 case ARM::VLD2DUPd16:
4495 case ARM::VLD2DUPd32:
4496 case ARM::VLD2DUPd8wb_fixed:
4497 case ARM::VLD2DUPd16wb_fixed:
4498 case ARM::VLD2DUPd32wb_fixed:
4499 case ARM::VLD2DUPd8wb_register:
4500 case ARM::VLD2DUPd16wb_register:
4501 case ARM::VLD2DUPd32wb_register:
4502 case ARM::VLD2DUPq8EvenPseudo:
4503 case ARM::VLD2DUPq8OddPseudo:
4504 case ARM::VLD2DUPq16EvenPseudo:
4505 case ARM::VLD2DUPq16OddPseudo:
4506 case ARM::VLD2DUPq32EvenPseudo:
4507 case ARM::VLD2DUPq32OddPseudo:
4508 case ARM::VLD3DUPq8EvenPseudo:
4509 case ARM::VLD3DUPq8OddPseudo:
4510 case ARM::VLD3DUPq16EvenPseudo:
4511 case ARM::VLD3DUPq16OddPseudo:
4512 case ARM::VLD3DUPq32EvenPseudo:
4513 case ARM::VLD3DUPq32OddPseudo:
4514 case ARM::VLD4DUPd8Pseudo:
4515 case ARM::VLD4DUPd16Pseudo:
4516 case ARM::VLD4DUPd32Pseudo:
4517 case ARM::VLD4DUPd8Pseudo_UPD:
4518 case ARM::VLD4DUPd16Pseudo_UPD:
4519 case ARM::VLD4DUPd32Pseudo_UPD:
4520 case ARM::VLD4DUPq8EvenPseudo:
4521 case ARM::VLD4DUPq8OddPseudo:
4522 case ARM::VLD4DUPq16EvenPseudo:
4523 case ARM::VLD4DUPq16OddPseudo:
4524 case ARM::VLD4DUPq32EvenPseudo:
4525 case ARM::VLD4DUPq32OddPseudo:
4526 case ARM::VLD1LNq8Pseudo:
4527 case ARM::VLD1LNq16Pseudo:
4528 case ARM::VLD1LNq32Pseudo:
4529 case ARM::VLD1LNq8Pseudo_UPD:
4530 case ARM::VLD1LNq16Pseudo_UPD:
4531 case ARM::VLD1LNq32Pseudo_UPD:
4532 case ARM::VLD2LNd8Pseudo:
4533 case ARM::VLD2LNd16Pseudo:
4534 case ARM::VLD2LNd32Pseudo:
4535 case ARM::VLD2LNq16Pseudo:
4536 case ARM::VLD2LNq32Pseudo:
4537 case ARM::VLD2LNd8Pseudo_UPD:
4538 case ARM::VLD2LNd16Pseudo_UPD:
4539 case ARM::VLD2LNd32Pseudo_UPD:
4540 case ARM::VLD2LNq16Pseudo_UPD:
4541 case ARM::VLD2LNq32Pseudo_UPD:
4542 case ARM::VLD4LNd8Pseudo:
4543 case ARM::VLD4LNd16Pseudo:
4544 case ARM::VLD4LNd32Pseudo:
4545 case ARM::VLD4LNq16Pseudo:
4546 case ARM::VLD4LNq32Pseudo:
4547 case ARM::VLD4LNd8Pseudo_UPD:
4548 case ARM::VLD4LNd16Pseudo_UPD:
4549 case ARM::VLD4LNd32Pseudo_UPD:
4550 case ARM::VLD4LNq16Pseudo_UPD:
4551 case ARM::VLD4LNq32Pseudo_UPD:
4552
4553
4555 break;
4556 }
4557
4559}
4560
4561unsigned ARMBaseInstrInfo::getPredicationCost(const MachineInstr &MI) const {
4562 if (MI.isCopyLike() || MI.isInsertSubreg() || MI.isRegSequence() ||
4563 MI.isImplicitDef())
4564 return 0;
4565
4566 if (MI.isBundle())
4567 return 0;
4568
4570
4571 if (MCID.isCall() || (MCID.hasImplicitDefOfPhysReg(ARM::CPSR) &&
4572 !Subtarget.cheapPredicableCPSRDef())) {
4573
4574
4575 return 1;
4576 }
4577 return 0;
4578}
4579
4580unsigned ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
4582 unsigned *PredCost) const {
4583 if (MI.isCopyLike() || MI.isInsertSubreg() || MI.isRegSequence() ||
4584 MI.isImplicitDef())
4585 return 1;
4586
4587
4588
4589 if (MI.isBundle()) {
4593 while (++I != E && I->isInsideBundle()) {
4594 if (I->getOpcode() != ARM::t2IT)
4595 Latency += getInstrLatency(ItinData, *I, PredCost);
4596 }
4598 }
4599
4600 const MCInstrDesc &MCID = MI.getDesc();
4602 !Subtarget.cheapPredicableCPSRDef()))) {
4603
4604
4605 *PredCost = 1;
4606 }
4607
4608
4609 if (!ItinData)
4610 return MI.mayLoad() ? 3 : 1;
4611
4613
4614
4617
4618
4620
4621
4622 unsigned DefAlign =
4623 MI.hasOneMemOperand() ? (*MI.memoperands_begin())->getAlign().value() : 0;
4625 if (Adj >= 0 || (int)Latency > -Adj) {
4627 }
4629}
4630
4631unsigned ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
4632 SDNode *Node) const {
4633 if (->isMachineOpcode())
4634 return 1;
4635
4636 if (!ItinData || ItinData->isEmpty())
4637 return 1;
4638
4639 unsigned Opcode = Node->getMachineOpcode();
4640 switch (Opcode) {
4641 default:
4643 case ARM::VLDMQIA:
4644 case ARM::VSTMQIA:
4645 return 2;
4646 }
4647}
4648
4649bool ARMBaseInstrInfo::hasHighOperandLatency(const TargetSchedModel &SchedModel,
4652 unsigned DefIdx,
4654 unsigned UseIdx) const {
4657 if (Subtarget.nonpipelinedVFP() &&
4659 return true;
4660
4661
4665 return false;
4668}
4669
4670bool ARMBaseInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,
4672 unsigned DefIdx) const {
4674 if (!ItinData || ItinData->isEmpty())
4675 return false;
4676
4679 unsigned DefClass = DefMI.getDesc().getSchedClass();
4680 std::optional DefCycle =
4682 return DefCycle && DefCycle <= 2U;
4683 }
4684 return false;
4685}
4686
4687bool ARMBaseInstrInfo::verifyInstruction(const MachineInstr &MI,
4690 ErrInfo = "Pseudo flag setting opcodes only exist in Selection DAG";
4691 return false;
4692 }
4693 if (MI.getOpcode() == ARM::tMOVr && !Subtarget.hasV6Ops()) {
4694
4695 if (!ARM::hGPRRegClass.contains(MI.getOperand(0).getReg()) &&
4696 !ARM::hGPRRegClass.contains(MI.getOperand(1).getReg())) {
4697 ErrInfo = "Non-flag-setting Thumb1 mov is v6-only";
4698 return false;
4699 }
4700 }
4701 if (MI.getOpcode() == ARM::tPUSH ||
4702 MI.getOpcode() == ARM::tPOP ||
4703 MI.getOpcode() == ARM::tPOP_RET) {
4704 for (const MachineOperand &MO : llvm::drop_begin(MI.operands(), 2)) {
4705 if (MO.isImplicit() || !MO.isReg())
4706 continue;
4709 if (!(MI.getOpcode() == ARM::tPUSH && Reg == ARM::LR) &&
4710 !(MI.getOpcode() == ARM::tPOP_RET && Reg == ARM::PC)) {
4711 ErrInfo = "Unsupported register in Thumb1 push/pop";
4712 return false;
4713 }
4714 }
4715 }
4716 }
4717 if (MI.getOpcode() == ARM::MVE_VMOV_q_rr) {
4718 assert(MI.getOperand(4).isImm() && MI.getOperand(5).isImm());
4719 if ((MI.getOperand(4).getImm() != 2 && MI.getOperand(4).getImm() != 3) ||
4720 MI.getOperand(4).getImm() != MI.getOperand(5).getImm() + 2) {
4721 ErrInfo = "Incorrect array index for MVE_VMOV_q_rr";
4722 return false;
4723 }
4724 }
4725
4726
4727
4731 default:
4732 break;
4741 uint32_t Imm = 0;
4742 for (auto Op : MI.operands()) {
4743 if (Op.isImm()) {
4745 break;
4746 }
4747 }
4749 ErrInfo = "Incorrect AddrMode Imm for instruction";
4750 return false;
4751 }
4752 break;
4753 }
4754 }
4755 return true;
4756}
4757
4759 unsigned LoadImmOpc,
4760 unsigned LoadOpc) const {
4761 assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&
4762 "ROPI/RWPI not currently supported with stack guard");
4763
4766 Register Reg = MI->getOperand(0).getReg();
4768 unsigned int Offset = 0;
4769
4770 if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) {
4771 assert(!Subtarget.isReadTPSoft() &&
4772 "TLS stack protector requires hardware TLS register");
4773
4781
4782 Module &M = *MBB.getParent()->getFunction().getParent();
4783 Offset = M.getStackProtectorGuardOffset();
4784 if (Offset & ~0xfffU) {
4785
4786
4787
4788 unsigned AddOpc = (LoadImmOpc == ARM::MRC) ? ARM::ADDri : ARM::t2ADDri;
4795 }
4796 } else {
4799 bool IsIndirect = Subtarget.isGVIndirectSymbol(GV);
4800
4802 if (Subtarget.isTargetMachO()) {
4804 } else if (Subtarget.isTargetCOFF()) {
4807 else if (IsIndirect)
4809 } else if (IsIndirect) {
4811 }
4812
4813 if (LoadImmOpc == ARM::tMOVi32imm) {
4814 Register CPSRSaveReg = ARM::R12;
4815 auto APSREncoding =
4816 ARMSysReg::lookupMClassSysRegByName("apsr_nzcvq")->Encoding;
4818 .addImm(APSREncoding)
4823 .addImm(APSREncoding)
4826 } else {
4829 }
4830
4831 if (IsIndirect) {
4840 }
4841 }
4842
4848}
4849
4850bool
4852 unsigned &AddSubOpc,
4853 bool &NegAcc, bool &HasLane) const {
4855 if (I == MLxEntryMap.end())
4856 return false;
4857
4859 MulOpc = Entry.MulOpc;
4860 AddSubOpc = Entry.AddSubOpc;
4861 NegAcc = Entry.NegAcc;
4862 HasLane = Entry.HasLane;
4863 return true;
4864}
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4882
4883
4884
4885
4886std::pair<uint16_t, uint16_t>
4888
4889
4890 if (Subtarget.hasNEON()) {
4891
4892
4895
4896
4897
4898 if (Subtarget.useNEONForFPMovs() && (MI) &&
4899 (MI.getOpcode() == ARM::VMOVRS || MI.getOpcode() == ARM::VMOVSR ||
4900 MI.getOpcode() == ARM::VMOVS))
4902 }
4903
4905
4907 return std::make_pair(ExeNEON, 0);
4908
4909
4910
4912 return std::make_pair(ExeNEON, 0);
4913
4915 return std::make_pair(ExeVFP, 0);
4916
4917 return std::make_pair(ExeGeneric, 0);
4918}
4919
4921 unsigned SReg, unsigned &Lane) {
4923 TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);
4924 Lane = 0;
4925
4926 if (DReg)
4927 return DReg;
4928
4929 Lane = 1;
4930 DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);
4931
4932 assert(DReg && "S-register with no D super-register?");
4933 return DReg;
4934}
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4953 unsigned Lane,
4955
4956
4957 if (MI.definesRegister(DReg, TRI) || MI.readsRegister(DReg, TRI)) {
4959 return true;
4960 }
4961
4962
4963 ImplicitSReg = TRI->getSubReg(DReg,
4964 (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);
4966 MI.getParent()->computeRegisterLiveness(TRI, ImplicitSReg, MI);
4967
4969 return true;
4971 return false;
4972
4973
4974
4976 return true;
4977}
4978
4980 unsigned Domain) const {
4981 unsigned DstReg, SrcReg;
4983 unsigned Lane;
4986 switch (MI.getOpcode()) {
4987 default:
4989 break;
4990 case ARM::VMOVD:
4992 break;
4993
4994
4996
4997
4998 assert(Subtarget.hasNEON() && "VORRd requires NEON");
4999
5000
5001 DstReg = MI.getOperand(0).getReg();
5002 SrcReg = MI.getOperand(1).getReg();
5003
5004 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)
5005 MI.removeOperand(i - 1);
5006
5007
5008 MI.setDesc(get(ARM::VORRd));
5013 break;
5014 case ARM::VMOVRS:
5016 break;
5018
5019
5020 DstReg = MI.getOperand(0).getReg();
5021 SrcReg = MI.getOperand(1).getReg();
5022
5023 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)
5024 MI.removeOperand(i - 1);
5025
5027
5028
5029
5030
5031 MI.setDesc(get(ARM::VGETLNi32));
5036
5037
5038
5040 break;
5041 case ARM::VMOVSR: {
5043 break;
5045
5046
5047 DstReg = MI.getOperand(0).getReg();
5048 SrcReg = MI.getOperand(1).getReg();
5049
5051
5054 break;
5055
5056 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)
5057 MI.removeOperand(i - 1);
5058
5059
5060
5061 MI.setDesc(get(ARM::VSETLNi32));
5067
5068
5069
5071 if (ImplicitSReg)
5073 break;
5074 }
5075 case ARM::VMOVS: {
5077 break;
5078
5079
5080 DstReg = MI.getOperand(0).getReg();
5081 SrcReg = MI.getOperand(1).getReg();
5082
5083 unsigned DstLane = 0, SrcLane = 0;
5087
5090 break;
5091
5092 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)
5093 MI.removeOperand(i - 1);
5094
5095 if (DSrc == DDst) {
5096
5097
5098 MI.setDesc(get(ARM::VDUPLN32d));
5103
5104
5105
5108 if (ImplicitSReg)
5110 break;
5111 }
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5126 NewMIB = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(ARM::VEXTd32),
5127 DDst);
5128
5129
5130
5131
5132 MCRegister CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;
5133 bool CurUndef = .readsRegister(CurReg, TRI);
5135
5136 CurReg = SrcLane == 0 && DstLane == 0 ? DSrc : DDst;
5137 CurUndef = .readsRegister(CurReg, TRI);
5141
5142 if (SrcLane == DstLane)
5144
5145 MI.setDesc(get(ARM::VEXTd32));
5147
5148
5149
5150 CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;
5151 CurUndef = CurReg == DSrc && .readsRegister(CurReg, TRI);
5153
5154 CurReg = SrcLane == 0 && DstLane == 1 ? DSrc : DDst;
5155 CurUndef = CurReg == DSrc && .readsRegister(CurReg, TRI);
5159
5160 if (SrcLane != DstLane)
5162
5163
5164
5166 if (ImplicitSReg != 0)
5168 break;
5169 }
5170 }
5171}
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5192 auto PartialUpdateClearance = Subtarget.getPartialUpdateClearance();
5193 if (!PartialUpdateClearance)
5194 return 0;
5195
5196 assert(TRI && "Need TRI instance");
5197
5200 return 0;
5202 int UseOp = -1;
5203
5204 switch (MI.getOpcode()) {
5205
5206 case ARM::VLDRS:
5207 case ARM::FCONSTS:
5208 case ARM::VMOVSR:
5209 case ARM::VMOVv8i8:
5210 case ARM::VMOVv4i16:
5211 case ARM::VMOVv2i32:
5212 case ARM::VMOVv2f32:
5213 case ARM::VMOVv1i64:
5214 UseOp = MI.findRegisterUseOperandIdx(Reg, TRI, false);
5215 break;
5216
5217
5218 case ARM::VLD1LNd32:
5219 UseOp = 3;
5220 break;
5221 default:
5222 return 0;
5223 }
5224
5225
5226
5227 if (UseOp != -1 && MI.getOperand(UseOp).readsReg())
5228 return 0;
5229
5230
5231 if (Reg.isVirtual()) {
5232
5233 if (!MO.getSubReg() || MI.readsVirtualRegister(Reg))
5234 return 0;
5235 } else if (ARM::SPRRegClass.contains(Reg)) {
5236
5238 TRI->getMatchingSuperReg(Reg, ARM::ssub_0, &ARM::DPRRegClass);
5239 if (!DReg || .definesRegister(DReg, TRI))
5240 return 0;
5241 }
5242
5243
5244
5245 return PartialUpdateClearance;
5246}
5247
5248
5249
5252 assert(OpNum < MI.getDesc().getNumDefs() && "OpNum is not a def");
5253 assert(TRI && "Need TRI instance");
5254
5257 assert(Reg.isPhysical() && "Can't break virtual register dependencies.");
5258 unsigned DReg = Reg;
5259
5260
5261 if (ARM::SPRRegClass.contains(Reg)) {
5262 DReg = ARM::D0 + (Reg - ARM::S0) / 2;
5263 assert(TRI->isSuperRegister(Reg, DReg) && "Register enums broken");
5264 }
5265
5266 assert(ARM::DPRRegClass.contains(DReg) && "Can only break D-reg deps");
5267 assert(MI.definesRegister(DReg, TRI) && "MI doesn't clobber full D-reg");
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(ARM::FCONSTD), DReg)
5280 MI.addRegisterKilled(DReg, TRI, true);
5281}
5282
5284 return Subtarget.hasFeature(ARM::HasV6KOps);
5285}
5286
5288 if (MI->getNumOperands() < 4)
5289 return true;
5290 unsigned ShOpVal = MI->getOperand(3).getImm();
5292
5294 ((ShImm == 1 || ShImm == 2) &&
5296 return true;
5297
5298 return false;
5299}
5300
5304 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");
5305 assert(MI.isRegSequenceLike() && "Invalid kind of instruction");
5306
5307 switch (MI.getOpcode()) {
5308 case ARM::VMOVDRR:
5309
5310
5311
5312
5313
5317 MOReg->getSubReg(), ARM::ssub_0));
5318
5319 MOReg = &MI.getOperand(2);
5322 MOReg->getSubReg(), ARM::ssub_1));
5323 return true;
5324 }
5326}
5327
5331 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");
5332 assert(MI.isExtractSubregLike() && "Invalid kind of instruction");
5333
5334 switch (MI.getOpcode()) {
5335 case ARM::VMOVRRD:
5336
5337
5338
5339
5342 return false;
5345 InputReg.SubIdx = DefIdx == 0 ? ARM::ssub_0 : ARM::ssub_1;
5346 return true;
5347 }
5349}
5350
5354 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");
5355 assert(MI.isInsertSubregLike() && "Invalid kind of instruction");
5356
5357 switch (MI.getOpcode()) {
5358 case ARM::VSETLNi32:
5359 case ARM::MVE_VMOV_to_lane_32:
5360
5361
5364 if (MOInsertedReg.isUndef())
5365 return false;
5367 BaseReg.Reg = MOBaseReg.getReg();
5368 BaseReg.SubReg = MOBaseReg.getSubReg();
5369
5370 InsertedReg.Reg = MOInsertedReg.getReg();
5372 InsertedReg.SubIdx = ARM::ssub_0 + MOIndex.getImm();
5373 return true;
5374 }
5376}
5377
5378std::pair<unsigned, unsigned>
5381 return std::make_pair(TF & Mask, TF & ~Mask);
5382}
5383
5386 using namespace ARMII;
5387
5388 static const std::pair<unsigned, const char *> TargetFlags[] = {
5389 {MO_LO16, "arm-lo16"}, {MO_HI16, "arm-hi16"},
5390 {MO_LO_0_7, "arm-lo-0-7"}, {MO_HI_0_7, "arm-hi-0-7"},
5391 {MO_LO_8_15, "arm-lo-8-15"}, {MO_HI_8_15, "arm-hi-8-15"},
5392 };
5393 return ArrayRef(TargetFlags);
5394}
5395
5398 using namespace ARMII;
5399
5400 static const std::pair<unsigned, const char *> TargetFlags[] = {
5401 {MO_COFFSTUB, "arm-coffstub"},
5402 {MO_GOT, "arm-got"},
5403 {MO_SBREL, "arm-sbrel"},
5404 {MO_DLLIMPORT, "arm-dllimport"},
5405 {MO_SECREL, "arm-secrel"},
5406 {MO_NONLAZY, "arm-nonlazy"}};
5407 return ArrayRef(TargetFlags);
5408}
5409
5410std::optional
5412 int Sign = 1;
5413 unsigned Opcode = MI.getOpcode();
5415
5416
5417
5419 if (!Op0.isReg() || Reg != Op0.getReg())
5420 return std::nullopt;
5421
5422
5423 if (Opcode == ARM::SUBri)
5424 Sign = -1;
5425 else if (Opcode != ARM::ADDri)
5426 return std::nullopt;
5427
5428
5429
5430
5431 if (.getOperand(1).isReg() ||
.getOperand(2).isImm())
5432 return std::nullopt;
5433
5434 Offset = MI.getOperand(2).getImm() * Sign;
5436}
5437
5442 for (auto I = From; I != To; ++I)
5443 if (I->modifiesRegister(Reg, TRI))
5444 return true;
5445 return false;
5446}
5447
5450
5451
5452
5455 --CmpMI;
5456 if (CmpMI->modifiesRegister(ARM::CPSR, TRI))
5457 break;
5458 if (CmpMI->readsRegister(ARM::CPSR, TRI))
5459 break;
5460 }
5461
5462
5463
5464 if (CmpMI->getOpcode() != ARM::tCMPi8 && CmpMI->getOpcode() != ARM::t2CMPri)
5465 return nullptr;
5466 Register Reg = CmpMI->getOperand(0).getReg();
5469 if (Pred != ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)
5470 return nullptr;
5472 return nullptr;
5474 return nullptr;
5475
5476 return &*CmpMI;
5477}
5478
5481 bool ForCodesize) {
5482 if (Subtarget->isThumb()) {
5483 if (Val <= 255)
5484 return ForCodesize ? 2 : 1;
5485 if (Subtarget->hasV6T2Ops() && (Val <= 0xffff ||
5488 return ForCodesize ? 4 : 1;
5489 if (Val <= 510)
5490 return ForCodesize ? 4 : 2;
5491 if (~Val <= 255)
5492 return ForCodesize ? 4 : 2;
5494 return ForCodesize ? 4 : 2;
5495 } else {
5497 return ForCodesize ? 4 : 1;
5499 return ForCodesize ? 4 : 1;
5500 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)
5501 return ForCodesize ? 4 : 1;
5503 return ForCodesize ? 8 : 2;
5505 return ForCodesize ? 8 : 2;
5506 }
5507 if (Subtarget->useMovt())
5508 return ForCodesize ? 8 : 2;
5509 return ForCodesize ? 8 : 3;
5510}
5511
5514 bool ForCodesize) {
5515
5518 if (Cost1 < Cost2)
5519 return true;
5520 if (Cost1 > Cost2)
5521 return false;
5522
5523
5526}
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5637
5643
5670
5673 MachineFunction *MF = C.getMF();
5675 const ARMBaseRegisterInfo *ARI =
5676 static_cast<const ARMBaseRegisterInfo *>(&TRI);
5677
5679
5680
5681 for (Register Reg : ARM::rGPRRegClass) {
5682 if (!(Reg < regsReserved.size() && regsReserved.test(Reg)) &&
5683 Reg != ARM::LR &&
5684 Reg != ARM::R12 &&
5685 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
5686 C.isAvailableInsideSeq(Reg, TRI))
5687 return Reg;
5688 }
5690}
5691
5692
5693
5694
5698
5699 bool Live = false;
5702
5703
5704 if (MI.modifiesRegister(ARM::LR, &TRI))
5705 Live = false;
5706
5707
5708 unsigned Opcode = MI.getOpcode();
5709 if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR ||
5710 Opcode == ARM::SUBS_PC_LR || Opcode == ARM::tBX_RET ||
5711 Opcode == ARM::tBXNS_RET) {
5712
5713
5714 Live = true;
5715 continue;
5716 }
5717 if (MI.readsRegister(ARM::LR, &TRI))
5718 Live = true;
5719 }
5720 return !Live;
5721}
5722
5723std::optional<std::unique_ptroutliner::OutlinedFunction>
5726 std::vectoroutliner::Candidate &RepeatedSequenceLocs,
5727 unsigned MinRepeats) const {
5728 unsigned SequenceSize = 0;
5729 for (auto &MI : RepeatedSequenceLocs[0])
5731
5732
5733 unsigned FlagsSetInAll = 0xF;
5734
5735
5738 FlagsSetInAll &= C.Flags;
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5753
5754
5756 return false;
5757 return C.isAnyUnavailableAcrossOrOutOfSeq({ARM::R12, ARM::CPSR}, TRI);
5758 };
5759
5760
5762
5763
5764
5765 llvm::erase_if(RepeatedSequenceLocs, CantGuaranteeValueAcrossCall);
5766
5767
5768 if (RepeatedSequenceLocs.size() < MinRepeats)
5769 return std::nullopt;
5770 }
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783 auto NoBTI =
5787 });
5788 if (std::distance(RepeatedSequenceLocs.begin(), NoBTI) >
5789 std::distance(NoBTI, RepeatedSequenceLocs.end()))
5790 RepeatedSequenceLocs.erase(NoBTI, RepeatedSequenceLocs.end());
5791 else
5792 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoBTI);
5793
5794 if (RepeatedSequenceLocs.size() < MinRepeats)
5795 return std::nullopt;
5796
5797
5798 auto NoPAC =
5801
5802
5804 });
5805 if (std::distance(RepeatedSequenceLocs.begin(), NoPAC) >
5806 std::distance(NoPAC, RepeatedSequenceLocs.end()))
5807 RepeatedSequenceLocs.erase(NoPAC, RepeatedSequenceLocs.end());
5808 else
5809 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoPAC);
5810
5811 if (RepeatedSequenceLocs.size() < MinRepeats)
5812 return std::nullopt;
5813
5814
5815
5816
5817 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
5818
5819
5820 auto SetCandidateCallInfo =
5821 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
5823 C.setCallInfo(CallID, NumBytesForCall);
5824 };
5825
5827
5828 const auto &SomeMFI =
5829 *RepeatedSequenceLocs.front().getMF()->getInfo<ARMFunctionInfo>();
5830
5831 if (SomeMFI.branchTargetEnforcement()) {
5837 }
5838
5839
5840 if (SomeMFI.shouldSignReturnAddress(true)) {
5841 Costs.CallDefault += 8;
5843 }
5844
5846 unsigned NumBytesToCreateFrame = Costs.FrameDefault;
5847
5848
5849
5850 if (RepeatedSequenceLocs[0].back().isTerminator()) {
5854 } else if (LastInstrOpcode == ARM::BL || LastInstrOpcode == ARM::BLX ||
5855 LastInstrOpcode == ARM::BLX_noip || LastInstrOpcode == ARM::tBL ||
5856 LastInstrOpcode == ARM::tBLXr ||
5857 LastInstrOpcode == ARM::tBLXr_noip ||
5858 LastInstrOpcode == ARM::tBLXi) {
5860 NumBytesToCreateFrame = Costs.FrameThunk;
5862 } else {
5863
5864
5865
5866 unsigned NumBytesNoStackCalls = 0;
5867 std::vectoroutliner::Candidate CandidatesWithoutStackFixups;
5868
5870
5871
5872 const auto Last = C.getMBB()->rbegin();
5873 const bool LRIsAvailable =
5874 C.getMBB()->isReturnBlock() && ->isCall()
5877 : C.isAvailableAcrossAndOutOfSeq(ARM::LR, TRI);
5878 if (LRIsAvailable) {
5882 CandidatesWithoutStackFixups.push_back(C);
5883 }
5884
5885
5886
5887 else if (findRegisterToSaveLRTo(C)) {
5889 NumBytesNoStackCalls += Costs.CallRegSave;
5891 CandidatesWithoutStackFixups.push_back(C);
5892 }
5893
5894
5895
5896 else if (C.isAvailableInsideSeq(ARM::SP, TRI)) {
5897 NumBytesNoStackCalls += Costs.CallDefault;
5899 CandidatesWithoutStackFixups.push_back(C);
5900 }
5901
5902
5903
5904 else
5905 NumBytesNoStackCalls += SequenceSize;
5906 }
5907
5908
5909
5910
5911 if (NumBytesNoStackCalls <=
5912 RepeatedSequenceLocs.size() * Costs.CallDefault) {
5913 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
5915 if (RepeatedSequenceLocs.size() < MinRepeats)
5916 return std::nullopt;
5917 } else
5919 }
5920
5921
5922
5924
5925
5930
5931
5932
5933
5934
5935
5939 }
5940
5941 return std::make_uniqueoutliner::OutlinedFunction(
5942 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
5943}
5944
5945bool ARMBaseInstrInfo::checkAndUpdateStackOffset(MachineInstr *MI,
5947 bool Updt) const {
5948 int SPIdx = MI->findRegisterUseOperandIdx(ARM::SP, nullptr);
5950 if (SPIdx < 0)
5951
5952 return true;
5954
5955 return false;
5956
5957
5958
5971 return false;
5972
5973 unsigned NumOps = MI->getDesc().getNumOperands();
5974 unsigned ImmIdx = NumOps - 3;
5975
5977 assert(Offset.isImm() && "Is not an immediate");
5978 int64_t OffVal = Offset.getImm();
5979
5980 if (OffVal < 0)
5981
5982 return false;
5983
5984 unsigned NumBits = 0;
5985 unsigned Scale = 1;
5986
5990 return false;
5992 NumBits = 8;
5993 break;
5996 return false;
5998 NumBits = 8;
5999 Scale = 4;
6000 break;
6003 return false;
6005 NumBits = 8;
6006 Scale = 2;
6007 break;
6009 NumBits = 8;
6010 break;
6012
6013 assert((Fixup & 3) == 0 && "Can't encode this offset!");
6014 NumBits = 10;
6015 break;
6017 NumBits = 8;
6018 Scale = 4;
6019 break;
6022 NumBits = 12;
6023 break;
6025 NumBits = 8;
6026 Scale = 4;
6027 break;
6028 default:
6030 }
6031
6032
6033 assert(((OffVal * Scale + Fixup) & (Scale - 1)) == 0 &&
6034 "Can't encode this offset!");
6035 OffVal += Fixup / Scale;
6036
6037 unsigned Mask = (1 << NumBits) - 1;
6038
6039 if (OffVal <= Mask) {
6040 if (Updt)
6041 MI->getOperand(ImmIdx).setImm(OffVal);
6042 return true;
6043 }
6044
6045 return false;
6046}
6047
6049 Function &F, std::vectoroutliner::Candidate &Candidates) const {
6051
6052
6053 const Function &CFn = C.getMF()->getFunction();
6054 if (CFn.hasFnAttribute("branch-target-enforcement"))
6055 F.addFnAttr(CFn.getFnAttribute("branch-target-enforcement"));
6056
6059
6060 ARMGenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
6061}
6062
6064 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
6066
6067
6068 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
6069 return false;
6070
6071
6072
6073
6074
6075 if (F.hasSection())
6076 return false;
6077
6078
6080 return false;
6081
6082
6083 return true;
6084}
6085
6087 unsigned &Flags) const {
6088
6089
6090 assert(MBB.getParent()->getRegInfo().tracksLiveness() &&
6091 "Suitable Machine Function for outlining must track liveness");
6092
6094
6097
6098
6099 bool R12AvailableInBlock = LRU.available(ARM::R12);
6100 bool CPSRAvailableInBlock = LRU.available(ARM::CPSR);
6101
6102
6103
6104 if (R12AvailableInBlock && CPSRAvailableInBlock)
6106
6107
6109
6110
6111
6112 if (R12AvailableInBlock && !LRU.available(ARM::R12))
6113 return false;
6114 if (CPSRAvailableInBlock && !LRU.available(ARM::CPSR))
6115 return false;
6116
6117
6118
6121
6122
6123
6124 bool LRIsAvailable =
6125 MBB.isReturnBlock() && .back().isCall()
6128 if (!LRIsAvailable)
6130
6131 return true;
6132}
6133
6137 unsigned Flags) const {
6140
6141
6142
6143 unsigned Opc = MI.getOpcode();
6144 if (Opc == ARM::tPICADD || Opc == ARM::PICADD || Opc == ARM::PICSTR ||
6145 Opc == ARM::PICSTRB || Opc == ARM::PICSTRH || Opc == ARM::PICLDR ||
6146 Opc == ARM::PICLDRB || Opc == ARM::PICLDRH || Opc == ARM::PICLDRSB ||
6147 Opc == ARM::PICLDRSH || Opc == ARM::t2LDRpci_pic ||
6148 Opc == ARM::t2MOVi16_ga_pcrel || Opc == ARM::t2MOVTi16_ga_pcrel ||
6149 Opc == ARM::t2MOV_ga_pcrel)
6151
6152
6153 if (Opc == ARM::t2BF_LabelPseudo || Opc == ARM::t2DoLoopStart ||
6154 Opc == ARM::t2DoLoopStartTP || Opc == ARM::t2WhileLoopStart ||
6155 Opc == ARM::t2WhileLoopStartLR || Opc == ARM::t2WhileLoopStartTP ||
6156 Opc == ARM::t2LoopDec || Opc == ARM::t2LoopEnd ||
6157 Opc == ARM::t2LoopEndDec)
6159
6164
6165
6166 if (MI.isTerminator())
6167
6168
6170
6171
6172 if (MI.readsRegister(ARM::LR, TRI) || MI.readsRegister(ARM::PC, TRI))
6174
6175 if (MI.isCall()) {
6176
6177
6178 const Function *Callee = nullptr;
6180 if (MOP.isGlobal()) {
6182 break;
6183 }
6184 }
6185
6186
6187
6188 if (Callee &&
6189 (Callee->getName() == "\01__gnu_mcount_nc" ||
6190 Callee->getName() == "\01mcount" || Callee->getName() == "__mcount"))
6192
6193
6194
6195
6196
6198 if (Opc == ARM::BL || Opc == ARM::tBL || Opc == ARM::BLX ||
6199 Opc == ARM::BLX_noip || Opc == ARM::tBLXr || Opc == ARM::tBLXr_noip ||
6200 Opc == ARM::tBLXi)
6202
6203 if (!Callee)
6204 return UnknownCallOutlineType;
6205
6206
6207
6209
6210
6211 if (!CalleeMF)
6212 return UnknownCallOutlineType;
6213
6214
6215
6216
6220 return UnknownCallOutlineType;
6221
6222
6223
6225 }
6226
6227
6228 if (MI.modifiesRegister(ARM::LR, TRI) || MI.modifiesRegister(ARM::PC, TRI))
6230
6231
6232 if (MI.modifiesRegister(ARM::SP, TRI) || MI.readsRegister(ARM::SP, TRI)) {
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245 bool MightNeedStackFixUp =
6248
6249 if (!MightNeedStackFixUp)
6251
6252
6253
6254
6255 if (MI.modifiesRegister(ARM::SP, TRI))
6257
6258
6259
6260 if (checkAndUpdateStackOffset(&MI, Subtarget.getStackAlignment().value(),
6261 false))
6263
6264
6266 }
6267
6268
6269 if (MI.readsRegister(ARM::ITSTATE, TRI) ||
6270 MI.modifiesRegister(ARM::ITSTATE, TRI))
6272
6273
6274 if (MI.isCFIInstruction())
6276
6278}
6279
6283 }
6284}
6285
6288 bool Auth) const {
6289 int Align = std::max(Subtarget.getStackAlignment().value(), uint64_t(8));
6291 assert(Align >= 8 && Align <= 256);
6292 if (Auth) {
6293 assert(Subtarget.isThumb2());
6294
6295
6304 } else {
6305 unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
6312 }
6313
6314 if (!CFI)
6315 return;
6316
6317
6319 CFIBuilder.buildDefCFAOffset(Align);
6320
6321
6322
6323 int LROffset = Auth ? Align - 4 : Align;
6324 CFIBuilder.buildOffset(ARM::LR, -LROffset);
6325 if (Auth) {
6326
6327 CFIBuilder.buildOffset(ARM::RA_AUTH_CODE, -Align);
6328 }
6329}
6330
6333 bool CFI, bool Auth) const {
6334 int Align = Subtarget.getStackAlignment().value();
6336 if (Auth) {
6337 assert(Subtarget.isThumb2());
6338
6347
6348 } else {
6349 unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
6353 if (!Subtarget.isThumb())
6355 MIB.addImm(Subtarget.getStackAlignment().value())
6358 }
6359
6360 if (CFI) {
6361
6363 CFIBuilder.buildDefCFAOffset(0);
6364 CFIBuilder.buildRestore(ARM::LR);
6365 if (Auth)
6366 CFIBuilder.buildUndefined(ARM::RA_AUTH_CODE);
6367 }
6368
6369 if (Auth)
6371}
6372
6376
6377
6380 bool isThumb = Subtarget.isThumb();
6381 unsigned FuncOp = isThumb ? 2 : 0;
6382 unsigned Opc = Call->getOperand(FuncOp).isReg()
6383 ? isThumb ? ARM::tTAILJMPr : ARM::TAILJMPr
6384 : isThumb ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd
6385 : ARM::tTAILJMPdND
6386 : ARM::TAILJMPd;
6388 .add(Call->getOperand(FuncOp));
6389 if (isThumb && ->getOperand(FuncOp).isReg())
6391 Call->eraseFromParent();
6392 }
6393
6394
6396 return MI.isCall() && .isReturn();
6397 };
6401
6404 Et = std::prev(MBB.end());
6405
6406
6407
6408
6409 if (.isLiveIn(ARM::LR))
6410 MBB.addLiveIn(ARM::LR);
6411
6412
6414 saveLROnStack(MBB, It, true, Auth);
6415
6416
6417
6419 "Can only fix up stack references once");
6420 fixupPostOutline(MBB);
6421
6422
6423 restoreLRFromStack(MBB, Et, true, Auth);
6424 }
6425
6426
6429 return;
6430
6431
6432
6435
6436
6439 return;
6440
6441
6442
6443 fixupPostOutline(MBB);
6444}
6445
6451 unsigned Opc;
6452 bool isThumb = Subtarget.isThumb();
6453
6454
6456
6458 ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND
6459 : ARM::TAILJMPd;
6464 It = MBB.insert(It, MIB);
6465 return It;
6466 }
6467
6468
6474
6477
6478 It = MBB.insert(It, CallMIB);
6479 return It;
6480 }
6481
6483
6485 Register Reg = findRegisterToSaveLRTo(C);
6486 assert(Reg != 0 && "No callee-saved register available?");
6487
6488
6493 CallPt = MBB.insert(It, CallMIB);
6497 It--;
6498 return CallPt;
6499 }
6500
6501 if (.isLiveIn(ARM::LR))
6502 MBB.addLiveIn(ARM::LR);
6505 CallPt = MBB.insert(It, CallMIB);
6506 restoreLRFromStack(MBB, It, !AFI.isLRSpilled(), Auth);
6507 It--;
6508 return CallPt;
6509}
6510
6515
6516bool ARMBaseInstrInfo::isReMaterializableImpl(
6518
6519
6520
6521
6524}
6525
6530
6535
6538 : ARM::BLX_pred;
6539}
6540
6541namespace {
6546
6547
6548
6549
6550 static int constexpr MAX_STAGES = 30;
6551 static int constexpr LAST_IS_USE = MAX_STAGES;
6552 static int constexpr SEEN_AS_LIVE = MAX_STAGES + 1;
6553 typedef std::bitset<MAX_STAGES + 2> IterNeed;
6554 typedef std::map<Register, IterNeed> IterNeeds;
6555
6557 const IterNeeds &CIN);
6559
6560
6561
6562
6563
6564
6565
6566
6567public:
6569 : EndLoop(EndLoop), LoopCount(LoopCount),
6571 TII(MF->getSubtarget().getInstrInfo()) {}
6572
6573 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
6574
6575 return MI == EndLoop || MI == LoopCount;
6576 }
6577
6578 bool shouldUseSchedule(SwingSchedulerDAG &SSD, SMSchedule &SMS) override {
6579 if (tooMuchRegisterPressure(SSD, SMS))
6580 return false;
6581
6582 return true;
6583 }
6584
6585 std::optional createTripCountGreaterCondition(
6586 int TC, MachineBasicBlock &MBB,
6587 SmallVectorImpl &Cond) override {
6588
6594 }
6595 return {};
6596 } else if (EndLoop->getOpcode() == ARM::t2LoopEnd) {
6597
6598
6599 MachineInstr *LoopDec = nullptr;
6601 if (I.getOpcode() == ARM::t2LoopDec)
6602 LoopDec = &I;
6603 assert(LoopDec && "Unable to find copied LoopDec");
6604
6609 .addReg(ARM::NoRegister);
6612 return {};
6613 } else
6615 }
6616
6617 void setPreheader(MachineBasicBlock *NewPreheader) override {}
6618
6619 void adjustTripCount(int TripCountAdjust) override {}
6620};
6621
6622void ARMPipelinerLoopInfo::bumpCrossIterationPressure(RegPressureTracker &RPT,
6623 const IterNeeds &CIN) {
6624
6625 for (const auto &N : CIN) {
6626 int Cnt = N.second.count() - N.second[SEEN_AS_LIVE] * 2;
6627 for (int I = 0; I < Cnt; ++I)
6630 }
6631
6632 for (const auto &N : CIN) {
6633 int Cnt = N.second.count() - N.second[SEEN_AS_LIVE] * 2;
6634 for (int I = 0; I < Cnt; ++I)
6637 }
6638}
6639
6640bool ARMPipelinerLoopInfo::tooMuchRegisterPressure(SwingSchedulerDAG &SSD,
6642 IterNeeds CrossIterationNeeds;
6643
6644
6645
6646
6647 for (auto &SU : SSD.SUnits) {
6650 for (auto &S : SU.Succs)
6651 if (MI->isPHI() && S.getKind() == SDep::Anti) {
6654 CrossIterationNeeds[Reg.id()].set(0);
6655 } else if (S.isAssignedRegDep()) {
6657 if (OStg >= 0 && OStg != Stg) {
6660 CrossIterationNeeds[Reg.id()] |= ((1 << (OStg - Stg)) - 1);
6661 }
6662 }
6663 }
6664
6665
6666
6667
6668
6669 std::vector<SUnit *> ProposedSchedule;
6671 for (int Stage = 0, StageEnd = SMS.getMaxStageCount(); Stage <= StageEnd;
6672 ++Stage) {
6673 std::deque<SUnit *> Instrs =
6675 std::sort(Instrs.begin(), Instrs.end(),
6676 [](SUnit *A, SUnit *B) { return A->NodeNum > B->NodeNum; });
6678 }
6679
6680
6681
6682
6683 for (auto *SU : ProposedSchedule)
6685 ++OperI) {
6686 auto MO = *OperI;
6687 if (!MO.isReg() || !MO.getReg())
6688 continue;
6690 auto CIter = CrossIterationNeeds.find(Reg.id());
6691 if (CIter == CrossIterationNeeds.end() || CIter->second[LAST_IS_USE] ||
6692 CIter->second[SEEN_AS_LIVE])
6693 continue;
6694 if (MO.isDef() && !MO.isDead())
6695 CIter->second.set(SEEN_AS_LIVE);
6696 else if (MO.isUse())
6697 CIter->second.set(LAST_IS_USE);
6698 }
6699 for (auto &CI : CrossIterationNeeds)
6700 CI.second.reset(LAST_IS_USE);
6701
6706 RPTracker.init(MF, &RegClassInfo, nullptr, EndLoop->getParent(),
6708
6709 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6710
6711 for (auto *SU : ProposedSchedule) {
6713 RPTracker.setPos(std::next(CurInstI));
6714 RPTracker.recede();
6715
6716
6718 auto MO = *OperI;
6719 if (!MO.isReg() || !MO.getReg())
6720 continue;
6722 if (MO.isDef() && !MO.isDead()) {
6723 auto CIter = CrossIterationNeeds.find(Reg.id());
6724 if (CIter != CrossIterationNeeds.end()) {
6725 CIter->second.reset(0);
6726 CIter->second.reset(SEEN_AS_LIVE);
6727 }
6728 }
6729 }
6730 for (auto &S : SU->Preds) {
6732 if (S.isAssignedRegDep()) {
6734 auto CIter = CrossIterationNeeds.find(Reg.id());
6735 if (CIter != CrossIterationNeeds.end()) {
6737 assert(Stg2 <= Stg && "Data dependence upon earlier stage");
6738 if (Stg - Stg2 < MAX_STAGES)
6739 CIter->second.set(Stg - Stg2);
6740 CIter->second.set(SEEN_AS_LIVE);
6741 }
6742 }
6743 }
6744
6745 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);
6746 }
6747
6748 auto &P = RPTracker.getPressure().MaxSetPressure;
6749 for (unsigned I = 0, E = P.size(); I < E; ++I) {
6750
6751 if (I == ARM::DQuad_with_ssub_0 || I == ARM::DTripleSpc_with_ssub_0 ||
6752 I == ARM::DTriple_with_qsub_0_in_QPR)
6753 continue;
6754
6756 return true;
6757 }
6758 }
6759 return false;
6760}
6761
6762}
6763
6764std::unique_ptrTargetInstrInfo::PipelinerLoopInfo
6768 if (Preheader == LoopBB)
6769 Preheader = *std::next(LoopBB->pred_begin());
6770
6771 if (I != LoopBB->end() && I->getOpcode() == ARM::t2Bcc) {
6772
6773
6774
6775
6777 for (auto &L : LoopBB->instrs()) {
6778 if (L.isCall())
6779 return nullptr;
6781 CCSetter = &L;
6782 }
6783 if (CCSetter)
6784 return std::make_unique(&*I, CCSetter);
6785 else
6786 return nullptr;
6787
6788 }
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798 if (I != LoopBB->end() && I->getOpcode() == ARM::t2LoopEnd) {
6799 for (auto &L : LoopBB->instrs())
6800 if (L.isCall())
6801 return nullptr;
6802 else if (isVCTP(&L))
6803 return nullptr;
6804 Register LoopDecResult = I->getOperand(0).getReg();
6806 MachineInstr *LoopDec = MRI.getUniqueVRegDef(LoopDecResult);
6807 if (!LoopDec || LoopDec->getOpcode() != ARM::t2LoopDec)
6808 return nullptr;
6810 for (auto &J : Preheader->instrs())
6811 if (J.getOpcode() == ARM::t2DoLoopStart)
6812 LoopStart = &J;
6813 if (!LoopStart)
6814 return nullptr;
6815 return std::make_unique(&*I, LoopDec);
6816 }
6817 return nullptr;
6818}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isThumb(const MCSubtargetInfo &STI)
static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI, MachineInstr &MI, MCRegister DReg, unsigned Lane, MCRegister &ImplicitSReg)
getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane, set ImplicitSReg to a register n...
Definition ARMBaseInstrInfo.cpp:4951
static const MachineInstr * getBundledUseMI(const TargetRegisterInfo *TRI, const MachineInstr &MI, unsigned Reg, unsigned &UseIdx, unsigned &Dist)
Definition ARMBaseInstrInfo.cpp:3999
static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI)
Create a copy of a const pool value.
Definition ARMBaseInstrInfo.cpp:1613
static bool isSuitableForMask(MachineInstr *&MI, Register SrcReg, int CmpMask, bool CommonUse)
isSuitableForMask - Identify a suitable 'and' instruction that operates on the given source register ...
Definition ARMBaseInstrInfo.cpp:2671
static int adjustDefLatency(const ARMSubtarget &Subtarget, const MachineInstr &DefMI, const MCInstrDesc &DefMCID, unsigned DefAlign)
Return the number of cycles to add to (or subtract from) the static itinerary based on the def opcode...
Definition ARMBaseInstrInfo.cpp:4031
static unsigned getNumMicroOpsSwiftLdSt(const InstrItineraryData *ItinData, const MachineInstr &MI)
Definition ARMBaseInstrInfo.cpp:3307
static MCRegister getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI, unsigned SReg, unsigned &Lane)
Definition ARMBaseInstrInfo.cpp:4920
static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[]
Definition ARMBaseInstrInfo.cpp:2268
static bool isEligibleForITBlock(const MachineInstr *MI)
Definition ARMBaseInstrInfo.cpp:519
static ARMCC::CondCodes getCmpToAddCondition(ARMCC::CondCodes CC)
getCmpToAddCondition - assume the flags are set by CMP(a,b), return the condition code if we modify t...
Definition ARMBaseInstrInfo.cpp:2689
static bool isOptimizeCompareCandidate(MachineInstr *MI, bool &IsThumb1)
Definition ARMBaseInstrInfo.cpp:2767
static bool isLRAvailable(const TargetRegisterInfo &TRI, MachineBasicBlock::reverse_iterator I, MachineBasicBlock::reverse_iterator E)
Definition ARMBaseInstrInfo.cpp:5695
ARMExeDomain
Definition ARMBaseInstrInfo.cpp:4877
@ ExeVFP
Definition ARMBaseInstrInfo.cpp:4879
@ ExeNEON
Definition ARMBaseInstrInfo.cpp:4880
@ ExeGeneric
Definition ARMBaseInstrInfo.cpp:4878
static const ARM_MLxEntry ARM_MLxTable[]
Definition ARMBaseInstrInfo.cpp:87
static bool isRedundantFlagInstr(const MachineInstr *CmpI, Register SrcReg, Register SrcReg2, int64_t ImmValue, const MachineInstr *OI, bool &IsThumb1)
isRedundantFlagInstr - check whether the first instruction, whose only purpose is to update flags,...
Definition ARMBaseInstrInfo.cpp:2705
static unsigned getNumMicroOpsSingleIssuePlusExtras(unsigned Opc, unsigned NumRegs)
Definition ARMBaseInstrInfo.cpp:3570
static const MachineInstr * getBundledDefMI(const TargetRegisterInfo *TRI, const MachineInstr *MI, unsigned Reg, unsigned &DefIdx, unsigned &Dist)
Definition ARMBaseInstrInfo.cpp:3976
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
This file defines the DenseMap class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
PowerPC TLS Dynamic Call Fixup
TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallSet class.
This file defines the SmallVector class.
static X86::CondCode getSwappedCondition(X86::CondCode CC)
Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...
static bool isCPSRDefined(const MachineInstr &MI)
Definition ARMBaseInstrInfo.cpp:512
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction to set the zero flag so that we can remove a "comparis...
Definition ARMBaseInstrInfo.cpp:2860
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Definition ARMBaseInstrInfo.cpp:378
ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const override
Definition ARMBaseInstrInfo.cpp:125
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
Definition ARMBaseInstrInfo.cpp:718
bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const override
foldImmediate - 'Reg' is known to be defined by a move immediate instruction, try to fold the immedia...
Definition ARMBaseInstrInfo.cpp:3158
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
Definition ARMBaseInstrInfo.cpp:5379
bool hasNOP() const
Definition ARMBaseInstrInfo.cpp:5283
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
Definition ARMBaseInstrInfo.cpp:1942
bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) const override
Definition ARMBaseInstrInfo.cpp:488
void copyFromCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister DestReg, bool KillSrc, const ARMSubtarget &Subtarget) const
Definition ARMBaseInstrInfo.cpp:654
unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr &MI) const override
Definition ARMBaseInstrInfo.cpp:3609
std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override
Definition ARMBaseInstrInfo.cpp:5411
unsigned getPartialRegUpdateClearance(const MachineInstr &, unsigned, const TargetRegisterInfo *) const override
Definition ARMBaseInstrInfo.cpp:5189
unsigned getNumLDMAddresses(const MachineInstr &MI) const
Get the number of addresses by LDM or VLDM or zero for unknown.
Definition ARMBaseInstrInfo.cpp:3555
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
Definition ARMBaseInstrInfo.cpp:2187
const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, unsigned State) const
Definition ARMBaseInstrInfo.cpp:932
bool produceSameValue(const MachineInstr &MI0, const MachineInstr &MI1, const MachineRegisterInfo *MRI) const override
Definition ARMBaseInstrInfo.cpp:1707
void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override
Definition ARMBaseInstrInfo.cpp:4979
ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override
Definition ARMBaseInstrInfo.cpp:5397
ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override
Definition ARMBaseInstrInfo.cpp:161
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
Analyze loop L, which must be a single-basic-block loop, and if the conditions can be understood enou...
Definition ARMBaseInstrInfo.cpp:6765
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Returns the size of the specified MachineInstr.
Definition ARMBaseInstrInfo.cpp:605
void copyToCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister SrcReg, bool KillSrc, const ARMSubtarget &Subtarget) const
Definition ARMBaseInstrInfo.cpp:674
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Definition ARMBaseInstrInfo.cpp:1211
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
Definition ARMBaseInstrInfo.cpp:298
void mergeOutliningCandidateAttributes(Function &F, std::vector< outliner::Candidate > &Candidates) const override
Definition ARMBaseInstrInfo.cpp:6048
bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override
ARM supports the MachineOutliner.
Definition ARMBaseInstrInfo.cpp:6063
bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override
Enable outlining by default at -Oz.
Definition ARMBaseInstrInfo.cpp:6511
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
Definition ARMBaseInstrInfo.cpp:887
MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const override
Definition ARMBaseInstrInfo.cpp:1683
ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override
Definition ARMBaseInstrInfo.cpp:138
MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override
Definition ARMBaseInstrInfo.cpp:6446
std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override
Definition ARMBaseInstrInfo.cpp:403
bool isPredicated(const MachineInstr &MI) const override
Definition ARMBaseInstrInfo.cpp:387
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Definition ARMBaseInstrInfo.cpp:1891
void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const
Definition ARMBaseInstrInfo.cpp:4758
bool isPredicable(const MachineInstr &MI) const override
isPredicable - Return true if the specified instruction can be predicated.
Definition ARMBaseInstrInfo.cpp:551
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Definition ARMBaseInstrInfo.cpp:1464
std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const override
Specialization of TargetInstrInfo::describeLoadedValue, used to enhance debug entry value description...
Definition ARMBaseInstrInfo.cpp:903
std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override
Definition ARMBaseInstrInfo.cpp:5724
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
Definition ARMBaseInstrInfo.cpp:182
unsigned extraSizeToPredicateInstructions(const MachineFunction &MF, unsigned NumInsts) const override
Definition ARMBaseInstrInfo.cpp:2032
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Definition ARMBaseInstrInfo.cpp:325
const ARMBaseRegisterInfo & getRegisterInfo() const
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig) const override
Definition ARMBaseInstrInfo.cpp:1656
bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const override
areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are lo...
Definition ARMBaseInstrInfo.cpp:1794
std::optional< unsigned > getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr &DefMI, unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const override
Definition ARMBaseInstrInfo.cpp:4209
bool getRegSequenceLikeInputs(const MachineInstr &MI, unsigned DefIdx, SmallVectorImpl< RegSubRegPairAndIdx > &InputRegs) const override
Build the equivalent inputs of a REG_SEQUENCE for the given MI and DefIdx.
Definition ARMBaseInstrInfo.cpp:5301
unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const override
Definition ARMBaseInstrInfo.cpp:2046
bool getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPair &BaseReg, RegSubRegPairAndIdx &InsertedReg) const override
Build the equivalent inputs of a INSERT_SUBREG for the given MI and DefIdx.
Definition ARMBaseInstrInfo.cpp:5351
bool expandPostRAPseudo(MachineInstr &MI) const override
Definition ARMBaseInstrInfo.cpp:1533
outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MIT, unsigned Flags) const override
Definition ARMBaseInstrInfo.cpp:6135
bool SubsumesPredicate(ArrayRef< MachineOperand > Pred1, ArrayRef< MachineOperand > Pred2) const override
Definition ARMBaseInstrInfo.cpp:462
bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, int64_t Offset2, unsigned NumLoads) const override
shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to determine (in conjunction w...
Definition ARMBaseInstrInfo.cpp:1861
bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Pred) const override
Definition ARMBaseInstrInfo.cpp:428
std::pair< uint16_t, uint16_t > getExecutionDomain(const MachineInstr &MI) const override
VFP/NEON execution domains.
Definition ARMBaseInstrInfo.cpp:4887
bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, MachineBasicBlock &FMBB) const override
Definition ARMBaseInstrInfo.cpp:2069
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Definition ARMBaseInstrInfo.cpp:944
bool isFpMLxInstruction(unsigned Opcode) const
isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS instruction.
bool isSwiftFastImmShift(const MachineInstr *MI) const
Returns true if the instruction has a shift by immediate that can be executed in one cycle less.
Definition ARMBaseInstrInfo.cpp:5287
ARMBaseInstrInfo(const ARMSubtarget &STI, const ARMBaseRegisterInfo &TRI)
Definition ARMBaseInstrInfo.cpp:110
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
Definition ARMBaseInstrInfo.cpp:5385
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Definition ARMBaseInstrInfo.cpp:1198
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2 if h...
Definition ARMBaseInstrInfo.cpp:2634
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
Definition ARMBaseInstrInfo.cpp:1144
void breakPartialRegDependency(MachineInstr &, unsigned, const TargetRegisterInfo *TRI) const override
Definition ARMBaseInstrInfo.cpp:5250
bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override
Definition ARMBaseInstrInfo.cpp:6086
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override
Definition ARMBaseInstrInfo.cpp:6373
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
Definition ARMBaseInstrInfo.cpp:1404
const ARMSubtarget & getSubtarget() const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
Commutes the operands in the given instruction.
Definition ARMBaseInstrInfo.cpp:2102
bool analyzeSelect(const MachineInstr &MI, SmallVectorImpl< MachineOperand > &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const override
Definition ARMBaseInstrInfo.cpp:2165
bool getExtractSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPairAndIdx &InputReg) const override
Build the equivalent inputs of a EXTRACT_SUBREG for the given MI and DefIdx.
Definition ARMBaseInstrInfo.cpp:5328
bool shouldSink(const MachineInstr &MI) const override
Definition ARMBaseInstrInfo.cpp:3140
BitVector getReservedRegs(const MachineFunction &MF) const override
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
bool isMachineBasicBlock() const
bool isGlobalValue() const
ARMCP::ARMCPModifier getModifier() const
bool mustAddCurrentAddress() const
virtual bool hasSameValue(ARMConstantPoolValue *ACPV)
hasSameValue - Return true if this ARM constpool value can share the same constantpool entry as anoth...
bool isBlockAddress() const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool isThumb2Function() const
bool branchTargetEnforcement() const
unsigned createPICLabelUId()
bool isThumb1OnlyFunction() const
bool isThumbFunction() const
bool shouldSignReturnAddress() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
Align getStackAlignment() const
getStackAlignment - Returns the minimum alignment known to hold of the stack frame on entry to the fu...
bool enableMachinePipeliner() const override
Returns true if machine pipeliner should be enabled.
@ DoubleIssueCheckUnalignedAccess
Can load/store 2 registers/cycle, but needs an extra cycle if the access is not 64-bit aligned.
@ SingleIssue
Can load/store 1 register/cycle.
@ DoubleIssue
Can load/store 2 registers/cycle.
@ SingleIssuePlusExtras
Can load/store 1 register/cycle, but needs an extra cycle for address computation and potentially als...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool test(unsigned Idx) const
size_type size() const
size - Returns the number of bits in this bitvector.
LLVM_ABI uint64_t scale(uint64_t Num) const
Scale a large integer.
BranchProbability getCompl() const
Helper class for creating CFI instructions and inserting them into MIR.
void buildRegister(MCRegister Reg1, MCRegister Reg2) const
void buildRestore(MCRegister Reg) const
ConstMIBundleOperands - Iterate over all operands in a const bundle of machine instructions.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool hasDLLImportStorageClass() const
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Reverses the branch condition of the specified condition list, returning false on success and true if...
Itinerary data supplied by a subtarget to be used by a target.
int getNumMicroOps(unsigned ItinClassIndx) const
Return the number of micro-ops that the given class decodes to.
std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
unsigned getStageLatency(unsigned ItinClassIndx) const
Return the total stage latency of the given class.
std::optional< unsigned > getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Compute and return the use operand latency of a given itinerary class and operand index if the value ...
bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const
Return true if there is a pipeline forwarding between instructions of itinerary classes DefClass and ...
bool isEmpty() const
Returns true if there are no itineraries.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)
Adds registers living out of block MBB.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Describe properties that are true of each instruction in the target description file.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool hasOptionalDef() const
Set if this instruction has an optional definition, e.g.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool isCall() const
Return true if the instruction is a call.
unsigned getOpcode() const
Return the opcode number for this descriptor.
LLVM_ABI bool hasImplicitDefOfPhysReg(MCRegister Reg, const MCRegisterInfo *MRI=nullptr) const
Return true if this instruction implicitly defines the specified physical register.
Wrapper class representing physical registers. Should be passed by value.
bool isValid() const
isValid - Returns true until all the operands have been visited.
unsigned pred_size() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
Instructions::iterator instr_iterator
pred_iterator pred_begin()
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
Instructions::const_iterator const_instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
LivenessQueryResult
Possible outcome of a register liveness query to computeRegisterLiveness()
@ LQR_Dead
Register is known to be fully dead.
@ LQR_Live
Register is known to be (at least partially) live.
@ LQR_Unknown
Register liveness not decidable from local neighborhood.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
const Constant * ConstVal
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
const std::vector< MachineConstantPoolEntry > & getConstants() const
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
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
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
ArrayRef< MachineMemOperand * >::iterator mmo_iterator
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isImplicitDef() const
const MachineBasicBlock * getParent() const
bool isCopyLike() const
Return true if the instruction behaves like a copy.
bool isCall(QueryType Type=AnyInBundle) const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI int findFirstPredOperandIdx() const
Find the index of the first operand in the operand list that is used to represent the predicate.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
bool isRegSequence() const
bool isInsertSubreg() const
LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.
LLVM_ABI bool isIdenticalTo(const MachineInstr &Other, MICheckType Check=CheckDefs) const
Return true if this instruction is identical to Other.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
bool hasOptionalDef(QueryType Type=IgnoreBundle) const
Set if this instruction has an optional definition, e.g.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void clearKillInfo()
Clears kill flags on all operands.
A description of a memory reference used in the backend.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MOLoad
The memory access reads data.
@ MOInvariant
The memory access always returns the same value (or traps).
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
void setImplicit(bool Val=true)
void setImm(int64_t immVal)
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
MachineBasicBlock * getMBB() const
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)
clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.
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)
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
const TargetRegisterInfo * getTargetRegisterInfo() const
A Module instance is used to store all the information related to an LLVM module.
void AddHazardRecognizer(std::unique_ptr< ScheduleHazardRecognizer > &&)
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void increaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
LLVM_ABI void decreaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)
unsigned getRegPressureSetLimit(unsigned Idx) const
Get the register unit limit for the given pressure set index.
LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)
runOnFunction - Prepare to answer questions about MF.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
@ Anti
A register anti-dependence (aka WAR).
This class represents the scheduled code.
unsigned getMaxStageCount()
Return the maximum stage count needed for this schedule.
int stageScheduled(SUnit *SU) const
Return the stage for a scheduled instruction.
int getInitiationInterval() const
Return the initiation interval for this schedule.
std::deque< SUnit * > & getInstructions(int cycle)
Return the instructions that are scheduled at the specified cycle.
int getFirstCycle() const
Return the first cycle in the completed schedule.
int getFinalCycle() const
Return the last cycle in the finalized schedule.
Scheduling unit. This is a node in the scheduling DAG.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
std::vector< SUnit > SUnits
The scheduling units.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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.
This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
virtual bool isReMaterializableImpl(const MachineInstr &MI) const
For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...
virtual MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const
Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore.
virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const
This method commutes the operands of the given machine instruction MI.
virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const
Compute operand latency based on the available machine model.
const InstrItineraryData * getInstrItineraries() const
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Wrapper class representing a virtual register or register unit.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static CondCodes getOppositeCondition(CondCodes CC)
ARMII - This namespace holds all of the target specific flags that instruction info tracks.
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
AddrMode
ARM Addressing Modes.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned char getAM5FP16Offset(unsigned AM5Opc)
unsigned getSORegOffset(unsigned Op)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
unsigned getAM2Offset(unsigned AM2Opc)
unsigned getSOImmValRotate(unsigned Imm)
getSOImmValRotate - Try to handle Imm with an immediate shifter operand, computing the rotate amount ...
bool isThumbImmShiftedVal(unsigned V)
isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
ShiftOpc getSORegShOp(unsigned Op)
AddrOpc getAM5Op(unsigned AM5Opc)
bool isSOImmTwoPartValNeg(unsigned V)
isSOImmTwoPartValNeg - Return true if the specified value can be obtained by two SOImmVal,...
unsigned getSOImmTwoPartSecond(unsigned V)
getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...
bool isSOImmTwoPartVal(unsigned V)
isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned getT2SOImmTwoPartSecond(unsigned Imm)
unsigned getT2SOImmTwoPartFirst(unsigned Imm)
bool isT2SOImmTwoPartVal(unsigned Imm)
unsigned char getAM5Offset(unsigned AM5Opc)
unsigned getSOImmTwoPartFirst(unsigned V)
getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...
AddrOpc getAM2Op(unsigned AM2Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
Define some predicates that are used for node matching.
@ C
The default llvm calling convention, compatible with C.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< NodeBase * > Node
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.
constexpr T rotr(T V, int R)
static bool isIndirectCall(const MachineInstr &MI)
MachineInstr * findCMPToFoldIntoCBZ(MachineInstr *Br, const TargetRegisterInfo *TRI)
Search backwards from a tBcc to find a tCMPi8 against 0, meaning we can convert them to a tCBZ or tCB...
Definition ARMBaseInstrInfo.cpp:5448
static bool isCondBranchOpcode(int Opc)
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
Definition ARMBaseInstrInfo.cpp:5512
static bool isPushOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond)
Definition ARMBaseInstrInfo.cpp:706
static bool isVCTP(const MachineInstr *MI)
bool IsCPSRDead< MachineInstr >(const MachineInstr *MI)
Definition ARMBaseInstrInfo.cpp:588
unsigned getBLXpredOpcode(const MachineFunction &MF)
Definition ARMBaseInstrInfo.cpp:6536
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
static bool isIndirectBranchOpcode(int Opc)
bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI)
Return true if Reg is defd between From and To.
Definition ARMBaseInstrInfo.cpp:5438
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
static bool isSEHInstruction(const MachineInstr &MI)
static bool isCalleeSavedRegister(MCRegister Reg, const MCPhysReg *CSRegs)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)
Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...
Definition ARMBaseInstrInfo.cpp:2355
auto reverse(ContainerTy &&C)
static bool isJumpTableBranchOpcode(int Opc)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static bool isPopOpcode(int Opc)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond, unsigned Inactive)
Definition ARMBaseInstrInfo.cpp:712
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
unsigned getUndefRegState(bool B)
void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg)
Definition ARMBaseInstrInfo.cpp:700
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
Definition ARMBaseInstrInfo.cpp:5479
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII)
rewriteARMFrameIndex / rewriteT2FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
Definition ARMBaseInstrInfo.cpp:2477
static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
Definition ARMBaseInstrInfo.cpp:2079
unsigned getMatchingCondBranchOpcode(unsigned Opc)
Definition ARMBaseInstrInfo.cpp:2091
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
static const char * ARMCondCodeToString(ARMCC::CondCodes CC)
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
unsigned gettBLXrOpcode(const MachineFunction &MF)
Definition ARMBaseInstrInfo.cpp:6531
static bool isSpeculationBarrierEndBBOpcode(int Opc)
unsigned getBLXOpcode(const MachineFunction &MF)
Definition ARMBaseInstrInfo.cpp:6526
void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB)
Definition ARMBaseInstrInfo.cpp:694
bool isV8EligibleForIT(const InstrType *Instr)
void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)
emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...
Definition ARMBaseInstrInfo.cpp:2314
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
Definition ARMBaseInstrInfo.cpp:2307
ARM_MLxEntry - Record information about MLA / MLS instructions.
Definition ARMBaseInstrInfo.cpp:79
bool NegAcc
Definition ARMBaseInstrInfo.cpp:83
uint16_t MulOpc
Definition ARMBaseInstrInfo.cpp:81
uint16_t AddSubOpc
Definition ARMBaseInstrInfo.cpp:82
uint16_t MLxOpc
Definition ARMBaseInstrInfo.cpp:80
bool HasLane
Definition ARMBaseInstrInfo.cpp:84
Map pseudo instructions that imply an 'S' bit onto real opcodes.
Definition ARMBaseInstrInfo.cpp:2263
uint16_t MachineOpc
Definition ARMBaseInstrInfo.cpp:2265
uint16_t PseudoOpc
Definition ARMBaseInstrInfo.cpp:2264
int CallDefault
Definition ARMBaseInstrInfo.cpp:5653
int CallTailCall
Definition ARMBaseInstrInfo.cpp:5645
int FrameTailCall
Definition ARMBaseInstrInfo.cpp:5646
int FrameThunk
Definition ARMBaseInstrInfo.cpp:5648
int CallRegSave
Definition ARMBaseInstrInfo.cpp:5651
int FrameDefault
Definition ARMBaseInstrInfo.cpp:5654
int CallNoLRSave
Definition ARMBaseInstrInfo.cpp:5649
int FrameNoLRSave
Definition ARMBaseInstrInfo.cpp:5650
int SaveRestoreLROnStack
Definition ARMBaseInstrInfo.cpp:5655
int CallThunk
Definition ARMBaseInstrInfo.cpp:5647
int FrameRegSave
Definition ARMBaseInstrInfo.cpp:5652
OutlinerCosts(const ARMSubtarget &target)
Definition ARMBaseInstrInfo.cpp:5657
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr LaneBitmask getAll()
static constexpr LaneBitmask getNone()
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
Used to describe a register and immediate addition.
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
An individual sequence of instructions to be replaced with a call to an outlined function.
The information necessary to create an outlined function for some class of candidate.