LLVM: lib/Target/ARM/ARMFrameLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
152#include
153#include
154#include
155#include
156#include
157#include
158#include
159
160#define DEBUG_TYPE "arm-frame-lowering"
161
162using namespace llvm;
163
166 cl::desc("Align ARM NEON spills in prolog and epilog"));
167
170 unsigned NumAlignedDPRCS2Regs);
171
181
182
185 unsigned NumAlignedDPRCS2Regs,
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 switch (Reg) {
213 default:
216 break;
217
218 case ARM::FPCXTNS:
220
221 case ARM::FPSCR:
222 case ARM::FPEXC:
224
225 case ARM::R0:
226 case ARM::R1:
227 case ARM::R2:
228 case ARM::R3:
229 case ARM::R4:
230 case ARM::R5:
231 case ARM::R6:
232 case ARM::R7:
234
235 case ARM::R8:
236 case ARM::R9:
237 case ARM::R10:
240 else
242
243 case ARM::R11:
249
251
252 case ARM::R12:
255 else
257
258 case ARM::LR:
263
265
266 case ARM::D0:
267 case ARM::D1:
268 case ARM::D2:
269 case ARM::D3:
270 case ARM::D4:
271 case ARM::D5:
272 case ARM::D6:
273 case ARM::D7:
275
276 case ARM::D8:
277 case ARM::D9:
278 case ARM::D10:
279 case ARM::D11:
280 case ARM::D12:
281 case ARM::D13:
282 case ARM::D14:
283 case ARM::D15:
284 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
286 else
288
290 case ARM::D17:
291 case ARM::D18:
292 case ARM::D19:
293 case ARM::D20:
294 case ARM::D21:
295 case ARM::D22:
296 case ARM::D23:
297 case ARM::D24:
298 case ARM::D25:
299 case ARM::D26:
300 case ARM::D27:
301 case ARM::D28:
302 case ARM::D29:
303 case ARM::D30:
304 case ARM::D31:
306 }
307}
308
312
319
320
321
326
327
328
329 return true;
330}
331
332
333
334
338
339
341 return true;
342
343
345 return true;
346
347
348 return (RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
350}
351
352
353
357
358
359
360
361
362
366
367
368
369
370 if (CFSize >= ((1 << 12) - 1) / 2)
371 return false;
372
374}
375
376
377
378
379
380bool
384
385
386
387
388
389
393 bool IsTailCallReturn = false;
395 unsigned RetOpcode = MBBI->getOpcode();
396 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||
397 RetOpcode == ARM::TCRETURNri ||
398 RetOpcode == ARM::TCRETURNrinotr12;
399 }
401
402 int ArgumentPopSize = 0;
403 if (IsTailCallReturn) {
405
406
407
408
409 ArgumentPopSize = StackAdjust.getImm();
410 } else {
411
412
413
414
416 }
417
418 return ArgumentPopSize;
419}
420
424 F.needsUnwindTableEntry();
425}
426
427
428
431 unsigned Flags) {
432 unsigned Opc = MBBI->getOpcode();
439
441
442 switch (Opc) {
443 default:
445 break;
446 case ARM::t2ADDri:
447 case ARM::t2ADDri12:
448 case ARM::t2MOVTi16:
449 case ARM::tBL:
450
451
452
456 break;
457
458 case ARM::t2MOVi16: {
459 bool Wide = MBBI->getOperand(1).getImm() >= 256;
460 if (!Wide) {
463 NewInstr.add(MBBI->getOperand(0));
466 NewInstr.add(MO);
469 MBBI = NewMBBI;
470 }
472 break;
473 }
474
475 case ARM::tBLXr:
479 break;
480
481 case ARM::t2MOVi32imm:
482
483
484
485
486
487
488
492 MBB->insertAfter(MBBI, MIB);
496 break;
497
498 case ARM::t2STR_PRE:
499 if (MBBI->getOperand(0).getReg() == ARM::SP &&
500 MBBI->getOperand(2).getReg() == ARM::SP &&
501 MBBI->getOperand(3).getImm() == -4) {
502 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
503 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
507 } else {
509 }
510 break;
511
512 case ARM::t2LDR_POST:
513 if (MBBI->getOperand(1).getReg() == ARM::SP &&
514 MBBI->getOperand(2).getReg() == ARM::SP &&
515 MBBI->getOperand(3).getImm() == 4) {
516 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
517 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))
521 } else {
523 }
524 break;
525
526 case ARM::t2LDMIA_RET:
527 case ARM::t2LDMIA_UPD:
528 case ARM::t2STMDB_UPD: {
529 unsigned Mask = 0;
530 bool Wide = false;
531 for (unsigned i = 4, NumOps = MBBI->getNumOperands(); i != NumOps; ++i) {
534 continue;
536 if (Reg == 15)
537 Reg = 14;
538 if (Reg >= 8 && Reg <= 13)
539 Wide = true;
540 else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)
541 Wide = true;
542 Mask |= 1 << Reg;
543 }
544 if (!Wide) {
545 unsigned NewOpc;
546 switch (Opc) {
547 case ARM::t2LDMIA_RET:
548 NewOpc = ARM::tPOP_RET;
549 break;
550 case ARM::t2LDMIA_UPD:
551 NewOpc = ARM::tPOP;
552 break;
553 case ARM::t2STMDB_UPD:
554 NewOpc = ARM::tPUSH;
555 break;
556 default:
558 }
561 for (unsigned i = 2, NumOps = MBBI->getNumOperands(); i != NumOps; ++i)
562 NewInstr.add(MBBI->getOperand(i));
565 MBBI = NewMBBI;
566 }
567 unsigned SEHOpc =
568 (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;
571 .addImm(Wide ? 1 : 0)
573 break;
574 }
575 case ARM::VSTMDDB_UPD:
576 case ARM::VLDMDIA_UPD: {
579 unsigned Reg = RegInfo->getSEHRegNum(MO.getReg());
583 }
584 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveFRegs))
588 break;
589 }
590 case ARM::tSUBspi:
591 case ARM::tADDspi:
592 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))
593 .addImm(MBBI->getOperand(2).getImm() * 4)
596 break;
597 case ARM::t2SUBspImm:
598 case ARM::t2SUBspImm12:
599 case ARM::t2ADDspImm:
600 case ARM::t2ADDspImm12:
601 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))
602 .addImm(MBBI->getOperand(2).getImm())
605 break;
606
607 case ARM::tMOVr:
608 if (MBBI->getOperand(1).getReg() == ARM::SP &&
610 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());
611 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))
614 } else if (MBBI->getOperand(0).getReg() == ARM::SP &&
616 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());
617 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))
620 } else {
622 }
623 break;
624
625 case ARM::tBX_RET:
626 case ARM::TCRETURNri:
627 case ARM::TCRETURNrinotr12:
628 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))
631 break;
632
633 case ARM::TCRETURNdi:
634 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))
637 break;
638 }
639 return MBB->insertAfter(MBBI, MIB);
640}
641
646 return std::prev(MBBI);
647}
648
653 if (Start.isValid())
654 Start = std::next(Start);
655 else
656 Start = MBB.begin();
657
658 for (auto MI = Start; MI != End;) {
659 auto Next = std::next(MI);
660
661
665 ++MI;
666 continue;
667 }
670 }
671}
672
678 if (isARM)
680 Pred, PredReg, TII, MIFlags);
681 else
683 Pred, PredReg, TII, MIFlags);
684}
685
691 unsigned PredReg = 0) {
693 MIFlags, Pred, PredReg);
694}
695
698 switch (MI.getOpcode()) {
699 case ARM::VSTMDDB_UPD:
701 break;
702 case ARM::STMDB_UPD:
703 case ARM::t2STMDB_UPD:
705 break;
706 case ARM::t2STR_PRE:
707 case ARM::STR_PRE_IMM:
708 return 4;
709 default:
711 }
712
714
715
716 for (int i = MI.getNumOperands() - 1; i >= 4; --i)
719}
720
722 size_t StackSizeInBytes) {
726
727 StackProbeSize =
728 F.getFnAttributeAsParsedInteger("stack-probe-size", StackProbeSize);
729 return (StackSizeInBytes >= StackProbeSize) &&
730 .hasFnAttribute("no-stack-arg-probe");
731}
732
733namespace {
734
735struct StackAdjustingInsts {
736 struct InstInfo {
738 unsigned SPAdjust;
739 bool BeforeFPSet;
740
741#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
742 void dump() {
743 dbgs() << " " << (BeforeFPSet ? "before-fp " : " ")
744 << "sp-adjust=" << SPAdjust;
745 I->dump();
746 }
747#endif
748 };
749
751
753 bool BeforeFPSet = false) {
754 InstInfo Info = {I, SPAdjust, BeforeFPSet};
756 }
757
761 assert(Info != Insts.end() && "invalid sp adjusting instruction");
762 Info->SPAdjust += ExtraBytes;
763 }
764
765 void emitDefCFAOffsets(MachineBasicBlock &MBB, bool HasFP) {
767 unsigned CFAOffset = 0;
768 for (auto &Info : Insts) {
769 if (HasFP && .BeforeFPSet)
770 return;
771
772 CFAOffset += Info.SPAdjust;
773 CFIBuilder.setInsertPoint(std::next(Info.I));
774 CFIBuilder.buildDefCFAOffset(CFAOffset);
775 }
776 }
777
778#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
779 void dump() {
780 dbgs() << "StackAdjustingInsts:\n";
781 for (auto &Info : Insts)
783 }
784#endif
785};
786
787}
788
789
790
791
792
793
794
795
801 const Align Alignment,
802 const bool MustBeSingleInstruction) {
804 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();
805 const unsigned AlignMask = Alignment.value() - 1U;
806 const unsigned NrBitsToZero = Log2(Alignment);
809
810
811
812
813
814
815
816
817
818 if (CanUseBFC) {
823 } else if (AlignMask <= 255) {
829 } else {
830 assert(!MustBeSingleInstruction &&
831 "Shouldn't call emitAligningInstructions demanding a single "
832 "instruction to be emitted for large stack alignment for a target "
833 "without BFC.");
844 }
845 } else {
846
847
853 }
854}
855
856
857
858
859
860
861
866
867
870
871
872 int MaxRegBytes = 8 * 4;
874
875 MaxRegBytes = 11 * 4;
877
878 MaxRegBytes = 11 * 4 + 8 * 8;
879 }
880 int FPCXTSaveSize =
883}
884
894 "This emitPrologue does not support Thumb1!");
896 Align Alignment = STI.getFrameLowering()->getStackAlign();
900 int FPCXTSaveSize = 0;
903 STI.getPushPopSplitVariation(MF);
904
906
907
908
910
912
913
914
915 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,
916 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;
917 int FramePtrSpillFI = 0;
918 int D8SpillFI = 0;
919
920
921
923 return;
924
925 StackAdjustingInsts DefCFAOffsetCandidates;
926 bool HasFP = hasFP(MF);
927
930 if (NumBytes != 0) {
933 DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes, true);
934 }
935 if (!NeedsWinCFI)
936 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);
937 if (NeedsWinCFI && MBBI != MBB.begin()) {
942 }
943 return;
944 }
945
946
948 bool BeforeFPPush = true;
951 int FI = I.getFrameIdx();
952
955
956 if (Reg == FramePtr.asMCReg()) {
957 FramePtrSpillFI = FI;
958 FramePtrSpillArea = Area;
959 }
960 if (Reg == ARM::D8)
961 D8SpillFI = FI;
962
963 switch (Area) {
965 FPCXTSaveSize += 4;
966 break;
968 GPRCS1Size += 4;
969 break;
971 GPRCS2Size += 4;
972 break;
974 FPStatusSize += 4;
975 break;
977 DPRCS1Size += 8;
978 break;
980 GPRCS3Size += 4;
981 break;
983 DPRCS2Size += 8;
984 break;
985 }
986 }
987
989 DPRCS1Push, GPRCS3Push;
990
991
993 LastPush = MBBI++;
994
995
996 if (FPCXTSaveSize > 0) {
997 LastPush = MBBI++;
998 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);
999 }
1000
1001
1002 if (ArgRegsSaveSize) {
1005 LastPush = std::prev(MBBI);
1006 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);
1007 }
1008
1009
1010 if (GPRCS1Size > 0) {
1011 GPRCS1Push = LastPush = MBBI++;
1012 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);
1014 BeforeFPPush = false;
1015 }
1016
1017
1018
1019
1020
1021 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
1022 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
1023 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
1024 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;
1025
1026 Align DPRAlign = DPRCS1Size ? std::min(Align(8), Alignment) : Align(4);
1027 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1028 GPRCS2Size + FPStatusSize) %
1029 DPRAlign.value();
1030
1031 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;
1032
1033 if (HasFP) {
1034
1035 [[maybe_unused]] int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);
1036 LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI
1037 << ", FPOffset: " << FPOffset << "\n");
1039 "Max FP estimation is wrong");
1041 NumBytes);
1042 }
1046
1047
1048 if (GPRCS2Size > 0) {
1050 GPRCS2Push = LastPush = MBBI++;
1051 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);
1053 BeforeFPPush = false;
1054 }
1055
1056
1057 if (FPStatusSize > 0) {
1058 while (MBBI != MBB.end()) {
1059 unsigned Opc = MBBI->getOpcode();
1060 if (Opc == ARM::VMRS || Opc == ARM::VMRS_FPEXC)
1062 else
1063 break;
1064 }
1065 LastPush = MBBI++;
1066 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);
1067 }
1068
1069
1070
1071 if (DPRGapSize) {
1072 assert(DPRGapSize == 4 && "unexpected alignment requirements for DPRs");
1073 if (LastPush != MBB.end() &&
1075 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);
1076 else {
1079 DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize, BeforeFPPush);
1080 }
1081 }
1082
1083
1084 if (DPRCS1Size > 0) {
1085
1086
1087 while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) {
1089 BeforeFPPush);
1090 DPRCS1Push = LastPush = MBBI++;
1091 }
1092 }
1093
1094
1095 if (DPRCS2Size > 0) {
1097
1098
1099
1100
1102 } else
1103 NumBytes = DPRCS1Offset;
1104
1105
1106 if (GPRCS3Size > 0) {
1108 GPRCS3Push = LastPush = MBBI++;
1109 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);
1111 BeforeFPPush = false;
1112 }
1113
1114 bool NeedsWinCFIStackAlloc = NeedsWinCFI;
1116 NeedsWinCFIStackAlloc = false;
1117
1119 uint32_t NumWords = NumBytes >> 2;
1120
1121 if (NumWords < 65536) {
1126 } else {
1127
1128
1129
1131 .addImm(NumWords & 0xffff)
1136 .addImm(NumWords >> 16)
1139 }
1140
1141 switch (TM.getCodeModel()) {
1152 break;
1157
1163 break;
1164 }
1165
1173 if (NeedsWinCFIStackAlloc) {
1174 SEH = BuildMI(MF, dl, TII.get(ARM::SEH_StackAlloc))
1178 MBB.insertAfter(Instr, SEH);
1179 }
1180 NumBytes = 0;
1181 }
1182
1183 if (NumBytes) {
1184
1187 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);
1188 else {
1191 DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes);
1192 }
1193
1194 if (HasFP && isARM)
1195
1196
1197
1198
1199
1200
1201
1202
1204 }
1205
1206
1207
1208
1209
1210
1211
1213 if (HasFP) {
1215
1216
1217 int64_t FPOffsetAfterPush;
1218 switch (FramePtrSpillArea) {
1220 FPPushInst = GPRCS1Push;
1221 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
1222 ArgRegsSaveSize + FPCXTSaveSize +
1224 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS1, offset "
1225 << FPOffsetAfterPush << " after that push\n");
1226 break;
1228 FPPushInst = GPRCS2Push;
1229 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
1230 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1232 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS2, offset "
1233 << FPOffsetAfterPush << " after that push\n");
1234 break;
1236 FPPushInst = GPRCS3Push;
1237 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +
1238 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +
1239 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +
1241 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS3, offset "
1242 << FPOffsetAfterPush << " after that push\n");
1243 break;
1244 default:
1246 break;
1247 }
1248 AfterPush = std::next(FPPushInst);
1250 assert(FPOffsetAfterPush == 0);
1251
1252
1254 FramePtr, ARM::SP, FPOffsetAfterPush,
1256
1257 if (!NeedsWinCFI) {
1258
1259
1261 if (FPOffsetAfterPush != 0)
1263 else
1265 }
1266 }
1267
1268
1269
1270 if (NeedsWinCFI && MBBI != MBB.begin()) {
1273 End = AfterPush;
1275 BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))
1278 }
1279
1280
1281
1282
1283 if (!NeedsWinCFI) {
1284 for (const auto &Entry : reverse(CSI)) {
1286 int FI = Entry.getFrameIdx();
1289 RegInfo)) {
1291 CFIPos = std::next(GPRCS1Push);
1292 break;
1294 CFIPos = std::next(GPRCS2Push);
1295 break;
1297 CFIPos = std::next(DPRCS1Push);
1298 break;
1300 CFIPos = std::next(GPRCS3Push);
1301 break;
1305
1306 break;
1307 }
1308
1311 .buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1313 }
1314 }
1315 }
1316
1317
1318
1319
1320
1321 if (!NeedsWinCFI) {
1322 LLVM_DEBUG(DefCFAOffsetCandidates.dump());
1323 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);
1324 }
1325
1326 if (STI.isTargetELF() && hasFP(MF))
1329
1337
1338
1339
1340
1341
1347 false);
1348 } else {
1349
1350
1351
1352
1353
1354
1355
1360 false);
1364 }
1365
1367 }
1368
1369
1370
1371
1372
1373
1374 if (RegInfo->hasBasePointer(MF)) {
1375 if (isARM)
1376 BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), RegInfo->getBaseRegister())
1380 else
1381 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), RegInfo->getBaseRegister())
1384 }
1385
1386
1387
1388
1391}
1392
1401 "This emitEpilogue does not support Thumb1!");
1404 STI.getPushPopSplitVariation(MF);
1405
1407
1408
1409
1411
1412
1413
1417
1418
1419
1421 return;
1422
1423
1426
1433 }
1434
1435 if (NumBytes + IncomingArgStackToRestore != 0)
1437 NumBytes + IncomingArgStackToRestore,
1439 } else {
1440
1441 if (MBBI != MBB.begin()) {
1442 do {
1444 } while (MBBI != MBB.begin() &&
1448 }
1449
1454 }
1455
1456
1457 NumBytes -=
1462
1463
1464
1467 if (NumBytes) {
1468 if (isARM)
1472 else {
1473
1474
1475
1476
1477
1478
1479
1481 "No scratch register to restore SP from FP!");
1488 }
1489 } else {
1490
1491 if (isARM)
1497 else
1502 }
1503 } else if (NumBytes &&
1507
1508
1511 (void)PushPopSplit;
1513 }
1514
1517
1518
1519 while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VLDMDIA_UPD)
1521 }
1524 "unexpected DPR alignment gap");
1527 }
1528
1531 (void)PushPopSplit;
1533 }
1535
1536 if (ReservedArgStack || IncomingArgStackToRestore) {
1537 assert((int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&
1538 "attempting to restore negative stack amount");
1540 ReservedArgStack + IncomingArgStackToRestore,
1542 }
1543
1544
1545
1546
1547
1550 }
1551
1556 }
1557}
1558
1559
1560
1561
1562
1568
1571 int SPAdj) const {
1579
1580 FrameReg = ARM::SP;
1582
1583
1584
1586
1587
1588
1589 if (RegInfo->hasStackRealignment(MF)) {
1590 assert(hasFP(MF) && "dynamic stack realignment without a FP!");
1591 if (isFixed) {
1592 FrameReg = RegInfo->getFrameRegister(MF);
1594 } else if (hasMovingSP) {
1595 assert(RegInfo->hasBasePointer(MF) &&
1596 "VLAs and dynamic stack alignment, but missing base pointer!");
1597 FrameReg = RegInfo->getBaseRegister();
1599 }
1601 }
1602
1603
1605
1606
1607 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
1608 FrameReg = RegInfo->getFrameRegister(MF);
1609 return FPOffset;
1610 } else if (hasMovingSP) {
1611 assert(RegInfo->hasBasePointer(MF) && "missing base pointer!");
1613
1614
1615
1616 if (FPOffset >= -255 && FPOffset < 0) {
1617 FrameReg = RegInfo->getFrameRegister(MF);
1618 return FPOffset;
1619 }
1620 }
1622
1623
1624
1625
1626
1629
1630
1631 if (AFI->isThumb2Function() && FPOffset >= -255 && FPOffset < 0) {
1632 FrameReg = RegInfo->getFrameRegister(MF);
1633 return FPOffset;
1634 }
1635 } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {
1636
1637 FrameReg = RegInfo->getFrameRegister(MF);
1638 return FPOffset;
1639 }
1640 }
1641
1642
1643
1644 if (RegInfo->hasBasePointer(MF)) {
1645 FrameReg = RegInfo->getBaseRegister();
1647 }
1649}
1650
1654 unsigned StmOpc, unsigned StrOpc,
1655 bool NoGap,
1660
1662
1663 using RegAndKill = std::pair<unsigned, bool>;
1664
1666 unsigned i = CSI.size();
1667 while (i != 0) {
1668 unsigned LastReg = 0;
1669 for (; i != 0; --i) {
1671 if (!Func(Reg))
1672 continue;
1673
1675 bool isLiveIn = MRI.isLiveIn(Reg);
1676 if (!isLiveIn && .isReserved(Reg))
1677 MBB.addLiveIn(Reg);
1678
1679
1680
1681 if (NoGap && LastReg && LastReg != Reg-1)
1682 break;
1683 LastReg = Reg;
1684
1685
1686
1687
1688
1689 Regs.push_back(std::make_pair(Reg, !isLiveIn));
1690 }
1691
1692 if (Regs.empty())
1693 continue;
1694
1695 llvm::sort(Regs, [&](const RegAndKill &LHS, const RegAndKill &RHS) {
1696 return TRI.getEncodingValue(LHS.first) < TRI.getEncodingValue(RHS.first);
1697 });
1698
1699 if (Regs.size() > 1 || StrOpc== 0) {
1704 for (const auto &[Reg, Kill] : Regs)
1706 } else if (Regs.size() == 1) {
1713 }
1714 Regs.clear();
1715
1716
1717
1718
1720 --MI;
1721 }
1722}
1723
1727 unsigned LdmOpc, unsigned LdrOpc,
1728 bool isVarArg, bool NoGap,
1732 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
1733 ARMFunctionInfo *AFI = MF.getInfo();
1736 bool isTailCall = false;
1737 bool isInterrupt = false;
1738 bool isTrap = false;
1739 bool isCmseEntry = false;
1741 STI.getPushPopSplitVariation(MF);
1744 unsigned RetOpcode = MI->getOpcode();
1745 isTailCall =
1746 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||
1747 RetOpcode == ARM::TCRETURNrinotr12);
1748 isInterrupt =
1749 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;
1750 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;
1751 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);
1752 }
1753
1754 SmallVector<unsigned, 4> Regs;
1755 unsigned i = CSI.size();
1756 while (i != 0) {
1757 unsigned LastReg = 0;
1758 bool DeleteRet = false;
1759 for (; i != 0; --i) {
1760 CalleeSavedInfo &Info = CSI[i-1];
1761 MCRegister Reg = Info.getReg();
1763 continue;
1764
1765 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
1770 Reg = ARM::PC;
1771
1772 DeleteRet = true;
1773 LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;
1774 }
1775
1776
1777
1778
1779 if (NoGap && LastReg && LastReg != Reg-1)
1780 break;
1781
1782 LastReg = Reg;
1784 }
1785
1786 if (Regs.empty())
1787 continue;
1788
1790 return TRI.getEncodingValue(LHS) < TRI.getEncodingValue(RHS);
1791 });
1792
1793 if (Regs.size() > 1 || LdrOpc == 0) {
1798 for (unsigned Reg : Regs)
1800 if (DeleteRet) {
1803 MI->eraseFromParent();
1804 }
1805 }
1806 MI = MIB;
1807 } else if (Regs.size() == 1) {
1808
1809
1810 if (Regs[0] == ARM::PC)
1811 Regs[0] = ARM::LR;
1812 MachineInstrBuilder MIB =
1817
1818
1819 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {
1822 } else
1825 }
1826 Regs.clear();
1827
1828
1829
1831 ++MI;
1832 }
1833}
1834
1838 unsigned PushOpc) const {
1841
1843 auto RegPresent = [&CSI](MCRegister Reg) {
1845 return C.getReg() == Reg;
1846 });
1847 };
1848
1849
1850
1851 if (RegPresent(ARM::FPSCR)) {
1855
1857 }
1858
1859
1860
1861 if (RegPresent(ARM::FPEXC)) {
1865
1867 }
1868
1869
1870 if (Regs.size() == 0)
1871 return;
1872
1873
1874 MachineInstrBuilder MIB =
1879
1882 }
1883}
1884
1885void ARMFrameLowering::emitFPStatusRestores(
1890
1891 auto RegPresent = [&CSI](MCRegister Reg) {
1893 return C.getReg() == Reg;
1894 });
1895 };
1896
1897
1898 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))
1899 return;
1900
1901
1902 MachineInstrBuilder MIB =
1907
1908
1909 if (RegPresent(ARM::FPSCR)) {
1911 }
1912
1913
1914 if (RegPresent(ARM::FPEXC)) {
1916 }
1917
1918
1919 if (RegPresent(ARM::FPSCR)) {
1924 }
1925
1926
1927
1928 if (RegPresent(ARM::FPEXC)) {
1933 }
1934}
1935
1936
1937
1938
1941 unsigned NumAlignedDPRCS2Regs,
1949
1950
1951
1952
1954 unsigned DNum = I.getReg() - ARM::D8;
1955 if (DNum > NumAlignedDPRCS2Regs - 1)
1956 continue;
1957 int FI = I.getFrameIdx();
1958
1959
1961
1962
1963
1964
1965
1966
1967
1968 if (DNum == 0)
1970 }
1971
1972
1973
1974
1975
1976
1977
1978
1982
1983
1984
1985 unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;
1988 .addImm(8 * NumAlignedDPRCS2Regs)
1991
1993
1994
1995
1996
1997
1999
2000
2001
2002
2003
2004 Opc = isThumb ? ARM::tMOVr : ARM::MOVr;
2010
2011
2012
2013 unsigned NextReg = ARM::D8;
2014
2015
2016
2017 if (NumAlignedDPRCS2Regs >= 6) {
2019 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2020 MBB.addLiveIn(SupReg);
2027 NextReg += 4;
2028 NumAlignedDPRCS2Regs -= 4;
2029 }
2030
2031
2032
2033 unsigned R4BaseReg = NextReg;
2034
2035
2036 if (NumAlignedDPRCS2Regs >= 4) {
2038 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2039 MBB.addLiveIn(SupReg);
2046 NextReg += 4;
2047 NumAlignedDPRCS2Regs -= 4;
2048 }
2049
2050
2051 if (NumAlignedDPRCS2Regs >= 2) {
2053 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2054 MBB.addLiveIn(SupReg);
2060 NextReg += 2;
2061 NumAlignedDPRCS2Regs -= 2;
2062 }
2063
2064
2065 if (NumAlignedDPRCS2Regs) {
2066 MBB.addLiveIn(NextReg);
2067
2071 .addImm((NextReg - R4BaseReg) * 2)
2073 }
2074
2075
2076 std::prev(MI)->addRegisterKilled(ARM::R4, TRI);
2077}
2078
2079
2080
2083 unsigned NumAlignedDPRCS2Regs) {
2084
2085
2086
2088 assert(MI->mayStore() && "Expecting spill instruction");
2089
2090
2091 switch(NumAlignedDPRCS2Regs) {
2092 case 7:
2093 ++MI;
2094 assert(MI->mayStore() && "Expecting spill instruction");
2095 [[fallthrough]];
2096 default:
2097 ++MI;
2098 assert(MI->mayStore() && "Expecting spill instruction");
2099 [[fallthrough]];
2100 case 1:
2101 case 2:
2102 case 4:
2103 assert(MI->killsRegister(ARM::R4, nullptr) && "Missed kill flag");
2104 ++MI;
2105 }
2106 return MI;
2107}
2108
2109
2110
2111
2114 unsigned NumAlignedDPRCS2Regs,
2121
2122
2123 int D8SpillFI = 0;
2125 if (I.getReg() == ARM::D8) {
2126 D8SpillFI = I.getFrameIdx();
2127 break;
2128 }
2129
2130
2131
2132
2133
2134
2137
2138 unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;
2144
2145
2146 unsigned NextReg = ARM::D8;
2147
2148
2149 if (NumAlignedDPRCS2Regs >= 6) {
2151 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2158 NextReg += 4;
2159 NumAlignedDPRCS2Regs -= 4;
2160 }
2161
2162
2163
2164 unsigned R4BaseReg = NextReg;
2165
2166
2167 if (NumAlignedDPRCS2Regs >= 4) {
2169 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);
2175 NextReg += 4;
2176 NumAlignedDPRCS2Regs -= 4;
2177 }
2178
2179
2180 if (NumAlignedDPRCS2Regs >= 2) {
2182 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);
2187 NextReg += 2;
2188 NumAlignedDPRCS2Regs -= 2;
2189 }
2190
2191
2192 if (NumAlignedDPRCS2Regs)
2195 .addImm(2 * (NextReg - R4BaseReg))
2197
2198
2200}
2201
2205 if (CSI.empty())
2206 return false;
2207
2211 STI.getPushPopSplitVariation(MF);
2213
2214 unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
2216 ARM::t2STR_PRE : ARM::STR_PRE_IMM;
2217 unsigned FltOpc = ARM::VSTMDDB_UPD;
2219
2223 }
2224
2226 return C.getReg() == ARM::FPCXTNS;
2227 })) {
2229 ARM::SP)
2233 }
2234
2235 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2236 RegInfo](unsigned Reg, SpillArea TestArea) {
2237 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2238 TestArea;
2239 };
2240 auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {
2242 };
2243 auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {
2245 };
2246 auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {
2248 };
2249 auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {
2251 };
2252
2253 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS1);
2254 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS2);
2255 emitFPStatusSaves(MBB, MI, CSI, PushOpc);
2256 emitPushInst(MBB, MI, CSI, FltOpc, 0, true, IsDPRCS1);
2257 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS3);
2258
2259
2260
2261
2262 if (NumAlignedDPRCS2Regs)
2264
2265 return true;
2266}
2267
2271 if (CSI.empty())
2272 return false;
2273
2277
2281 STI.getPushPopSplitVariation(MF);
2282
2283
2284
2285 if (NumAlignedDPRCS2Regs)
2287
2288 unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;
2289 unsigned LdrOpc =
2290 AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
2291 unsigned FltOpc = ARM::VLDMDIA_UPD;
2292
2293 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,
2294 RegInfo](unsigned Reg, SpillArea TestArea) {
2295 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==
2296 TestArea;
2297 };
2298 auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {
2300 };
2301 auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {
2303 };
2304 auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {
2306 };
2307 auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {
2309 };
2310
2311 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS3);
2312 emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, IsDPRCS1);
2313 emitFPStatusRestores(MBB, MI, CSI, PopOpc);
2314 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS2);
2315 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS1);
2316
2317 return true;
2318}
2319
2320
2323 unsigned FnSize = 0;
2324 for (auto &MBB : MF) {
2326 FnSize += TII.getInstSizeInBytes(MI);
2327 }
2330 FnSize += Table.MBBs.size() * 4;
2332 return FnSize;
2333}
2334
2335
2336
2337
2338
2341 bool &HasNonSPFrameIndex) {
2345 unsigned Limit = (1 << 12) - 1;
2346 for (auto &MBB : MF) {
2348 if (MI.isDebugInstr())
2349 continue;
2350 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
2351 if (.getOperand(i).isFI())
2352 continue;
2353
2354
2355
2356 if (MI.getOpcode() == ARM::ADDri) {
2357 Limit = std::min(Limit, (1U << 8) - 1);
2358 break;
2359 }
2360
2361
2362 if (MI.getOpcode() == ARM::t2ADDri || MI.getOpcode() == ARM::t2ADDri12)
2363 break;
2364
2367 if (RegClass && !RegClass->contains(ARM::SP))
2368 HasNonSPFrameIndex = true;
2369
2370
2374
2375 break;
2378 Limit = std::min(Limit, (1U << 8) - 1);
2379 break;
2381 Limit = std::min(Limit, ((1U << 8) - 1) * 2);
2382 break;
2386 Limit = std::min(Limit, ((1U << 8) - 1) * 4);
2387 break;
2389
2390
2392 Limit = std::min(Limit, (1U << 8) - 1);
2393 break;
2396
2397
2398 return 0;
2400 Limit = std::min(Limit, ((1U << 7) - 1) * 1);
2401 break;
2403 Limit = std::min(Limit, ((1U << 7) - 1) * 2);
2404 break;
2406 Limit = std::min(Limit, ((1U << 7) - 1) * 4);
2407 break;
2408 default:
2409 llvm_unreachable("Unhandled addressing mode in stack size limit calculation");
2410 }
2411 break;
2412 }
2413 }
2414 }
2415
2416 return Limit;
2417}
2418
2419
2420
2421
2422static void
2426 return;
2427
2428
2430 return;
2431
2432
2434 return;
2435
2436
2438 return;
2439
2440
2443 return;
2444
2445
2446
2447
2448
2449
2450 unsigned NumSpills = 0;
2451 for (; NumSpills < 8; ++NumSpills)
2452 if (!SavedRegs.test(ARM::D8 + NumSpills))
2453 break;
2454
2455
2456 if (NumSpills < 2)
2457 return;
2458
2459
2461
2462
2463 SavedRegs.set(ARM::R4);
2464}
2465
2467
2468
2469 if (STI.hasV8_1MMainlineOps() &&
2471 return false;
2472
2473
2474
2475
2477 true ))
2478 return false;
2479
2480 return true;
2481}
2482
2486 return Subtarget.createAAPCSFrameChain() && hasFP(MF);
2487}
2488
2489
2490
2491
2496 return false;
2497
2499 for (const auto &MBB : MF)
2500 for (const auto &MI : MBB)
2501 if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi ||
2502 STI.genExecuteOnly())
2503 for (const auto &Op : MI.operands())
2504 if (Op.isFI()) {
2507 if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::SP)
2508 return true;
2509 }
2510 return false;
2511}
2512
2517
2518
2519
2520
2523 bool CS1Spilled = false;
2524 bool LRSpilled = false;
2525 unsigned NumGPRSpills = 0;
2526 unsigned NumFPRSpills = 0;
2538 (void)TRI;
2541 STI.getPushPopSplitVariation(MF);
2542
2543
2544
2545 if (F.hasFnAttribute("interrupt") && F.hasFnAttribute("save-fp")) {
2546 SavedRegs.set(ARM::FPSCR);
2547 SavedRegs.set(ARM::R4);
2548
2549
2550 if (STI.isMClass()) {
2551 SavedRegs.reset(ARM::FPEXC);
2552 } else {
2553 SavedRegs.set(ARM::FPEXC);
2554 SavedRegs.set(ARM::R5);
2555 }
2556 }
2557
2558
2559
2560
2561
2562
2564 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))
2565 SavedRegs.set(ARM::R4);
2566
2567
2568
2569
2570
2571
2572 if (STI.isTargetWindows() &&
2574 SavedRegs.set(ARM::R4);
2575 SavedRegs.set(ARM::LR);
2576 }
2577
2579
2581 SavedRegs.set(ARM::LR);
2582
2583
2584
2585
2586
2587
2588
2589 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||
2590 MFI.estimateStackSize(MF) > 508)
2591 SavedRegs.set(ARM::R4);
2592 }
2593
2594
2596
2597
2598 if (RegInfo->hasBasePointer(MF))
2599 SavedRegs.set(RegInfo->getBaseRegister());
2600
2601
2603 CanEliminateFrame = false;
2604
2605
2607 CanEliminateFrame = false;
2608
2609
2610
2611 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
2612 for (unsigned i = 0; CSRegs[i]; ++i) {
2613 unsigned Reg = CSRegs[i];
2614 bool Spilled = false;
2615 if (SavedRegs.test(Reg)) {
2616 Spilled = true;
2617 CanEliminateFrame = false;
2618 }
2619
2620 if (!ARM::GPRRegClass.contains(Reg)) {
2621 if (Spilled) {
2622 if (ARM::SPRRegClass.contains(Reg))
2623 NumFPRSpills++;
2624 else if (ARM::DPRRegClass.contains(Reg))
2625 NumFPRSpills += 2;
2626 else if (ARM::QPRRegClass.contains(Reg))
2627 NumFPRSpills += 4;
2628 }
2629 continue;
2630 }
2631
2632 if (Spilled) {
2633 NumGPRSpills++;
2634
2636 if (Reg == ARM::LR)
2637 LRSpilled = true;
2638 CS1Spilled = true;
2639 continue;
2640 }
2641
2642
2643 switch (Reg) {
2644 case ARM::LR:
2645 LRSpilled = true;
2646 [[fallthrough]];
2647 case ARM::R0: case ARM::R1:
2648 case ARM::R2: case ARM::R3:
2649 case ARM::R4: case ARM::R5:
2650 case ARM::R6: case ARM::R7:
2651 CS1Spilled = true;
2652 break;
2653 default:
2654 break;
2655 }
2656 } else {
2658 UnspilledCS1GPRs.push_back(Reg);
2659 continue;
2660 }
2661
2662 switch (Reg) {
2663 case ARM::R0: case ARM::R1:
2664 case ARM::R2: case ARM::R3:
2665 case ARM::R4: case ARM::R5:
2666 case ARM::R6: case ARM::R7:
2667 case ARM::LR:
2668 UnspilledCS1GPRs.push_back(Reg);
2669 break;
2670 default:
2671 UnspilledCS2GPRs.push_back(Reg);
2672 break;
2673 }
2674 }
2675 }
2676
2677 bool ForceLRSpill = false;
2680
2681
2682 if (FnSize >= (1 << 11)) {
2683 CanEliminateFrame = false;
2684 ForceLRSpill = true;
2685 }
2686 }
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702 unsigned EstimatedStackSize =
2703 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);
2704
2705
2706 int MaxFixedOffset = 0;
2707 for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {
2708 int MaxObjectOffset = MFI.getObjectOffset(I) + MFI.getObjectSize(I);
2709 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);
2710 }
2711
2712 bool HasFP = hasFP(MF);
2713 if (HasFP) {
2715 EstimatedStackSize += 4;
2716 } else {
2717
2718
2719 EstimatedStackSize += MaxFixedOffset;
2720 }
2721 EstimatedStackSize += 16;
2722
2723 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;
2724 bool HasNonSPFrameIndex = false;
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744 if (RegInfo->hasBasePointer(MF))
2745 EstimatedRSStackSizeLimit = (1U << 5) * 4;
2746 else
2747 EstimatedRSStackSizeLimit = (1U << 8) * 4;
2748 EstimatedRSFixedSizeLimit = (1U << 5) * 4;
2749 } else {
2750 EstimatedRSStackSizeLimit =
2752 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;
2753 }
2754
2755
2756 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;
2757
2758
2759
2760
2761
2762 bool HasMovingSP = MFI.hasVarSizedObjects() ||
2764 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;
2765
2766
2767
2768
2769
2770
2771
2773 bool HasLargeArgumentList =
2774 HasFP && (MaxFixedOffset - MaxFPOffset) > (int)EstimatedRSFixedSizeLimit;
2775
2776 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||
2777 HasLargeArgumentList || HasNonSPFrameIndex;
2778 LLVM_DEBUG(dbgs() << "EstimatedLimit: " << EstimatedRSStackSizeLimit
2779 << "; EstimatedStack: " << EstimatedStackSize
2780 << "; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset
2781 << "; BigFrameOffsets: " << BigFrameOffsets << "\n");
2782 if (BigFrameOffsets ||
2783 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
2785
2786
2787
2788
2789
2792
2793
2796 !LRSpilled) {
2797 SavedRegs.set(ARM::LR);
2798 LRSpilled = true;
2799 NumGPRSpills++;
2800 auto LRPos = llvm::find(UnspilledCS1GPRs, ARM::LR);
2801 if (LRPos != UnspilledCS1GPRs.end())
2802 UnspilledCS1GPRs.erase(LRPos);
2803 }
2805 if (FPPos != UnspilledCS1GPRs.end())
2806 UnspilledCS1GPRs.erase(FPPos);
2807 NumGPRSpills++;
2809 CS1Spilled = true;
2810 }
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824 unsigned NumExtraCSSpill = 0;
2825
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2838
2839
2840
2841 int EntryRegDeficit = 0;
2842 for (unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {
2844 --EntryRegDeficit;
2847 << " is unused argument register, EntryRegDeficit = "
2848 << EntryRegDeficit << "\n");
2849 }
2850 }
2851
2852
2855 << " return regs used, ExitRegDeficit = "
2856 << ExitRegDeficit << "\n");
2857
2858 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);
2859 LLVM_DEBUG(dbgs() << "RegDeficit = " << RegDeficit << "\n");
2860
2861
2862
2863 for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {
2864 if (SavedRegs.test(Reg)) {
2865 --RegDeficit;
2867 << " is saved low register, RegDeficit = "
2868 << RegDeficit << "\n");
2869 } else {
2874 << " is non-saved low register, adding to AvailableRegs\n");
2875 }
2876 }
2877
2878
2879 if (!HasFP || FramePtr != ARM::R7) {
2880 if (SavedRegs.test(ARM::R7)) {
2881 --RegDeficit;
2882 LLVM_DEBUG(dbgs() << "%r7 is saved low register, RegDeficit = "
2883 << RegDeficit << "\n");
2884 } else {
2885 AvailableRegs.push_back(ARM::R7);
2888 << "%r7 is non-saved low register, adding to AvailableRegs\n");
2889 }
2890 }
2891
2892
2893 for (unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {
2894 if (SavedRegs.test(Reg)) {
2895 ++RegDeficit;
2897 << " is saved high register, RegDeficit = "
2898 << RegDeficit << "\n");
2899 }
2900 }
2901
2902
2903
2904
2905 if ((EntryRegDeficit > ExitRegDeficit) &&
2908 if (SavedRegs.test(ARM::LR)) {
2909 --RegDeficit;
2910 LLVM_DEBUG(dbgs() << "%lr is saved register, RegDeficit = "
2911 << RegDeficit << "\n");
2912 } else {
2913 AvailableRegs.push_back(ARM::LR);
2914 LLVM_DEBUG(dbgs() << "%lr is not saved, adding to AvailableRegs\n");
2915 }
2916 }
2917
2918
2919
2920
2921
2922
2923 LLVM_DEBUG(dbgs() << "Final RegDeficit = " << RegDeficit << "\n");
2924 for (; RegDeficit > 0 && !AvailableRegs.empty(); --RegDeficit) {
2925 unsigned Reg = AvailableRegs.pop_back_val();
2927 << " to make up reg deficit\n");
2928 SavedRegs.set(Reg);
2929 NumGPRSpills++;
2930 CS1Spilled = true;
2931 assert(.isReserved(Reg) && "Should not be reserved");
2932 if (Reg != ARM::LR && .isPhysRegUsed(Reg))
2933 NumExtraCSSpill++;
2934 UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg));
2935 if (Reg == ARM::LR)
2936 LRSpilled = true;
2937 }
2938 LLVM_DEBUG(dbgs() << "After adding spills, RegDeficit = " << RegDeficit
2939 << "\n");
2940 }
2941
2942
2943
2945
2946
2947
2948 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {
2949 SavedRegs.set(ARM::LR);
2950 NumGPRSpills++;
2952 LRPos = llvm::find(UnspilledCS1GPRs, (unsigned)ARM::LR);
2953 if (LRPos != UnspilledCS1GPRs.end())
2954 UnspilledCS1GPRs.erase(LRPos);
2955
2956 ForceLRSpill = false;
2957 if (.isReserved(ARM::LR) &&
.isPhysRegUsed(ARM::LR) &&
2959 NumExtraCSSpill++;
2960 }
2961
2962
2963
2964
2965 LLVM_DEBUG(dbgs() << "NumGPRSpills = " << NumGPRSpills << "\n");
2967 if (TargetAlign >= Align(8) && (NumGPRSpills & 1)) {
2968 if (CS1Spilled && !UnspilledCS1GPRs.empty()) {
2969 for (unsigned Reg : UnspilledCS1GPRs) {
2970
2971
2973 (STI.isTargetWindows() && Reg == ARM::R11) ||
2975 (Reg == ARM::LR && !ExpensiveLRRestore)) {
2976 SavedRegs.set(Reg);
2978 << " to make up alignment\n");
2979 if (.isReserved(Reg) &&
.isPhysRegUsed(Reg) &&
2981 NumExtraCSSpill++;
2982 break;
2983 }
2984 }
2986 unsigned Reg = UnspilledCS2GPRs.front();
2987 SavedRegs.set(Reg);
2989 << " to make up alignment\n");
2990 if (.isReserved(Reg) &&
.isPhysRegUsed(Reg))
2991 NumExtraCSSpill++;
2992 }
2993 }
2994
2995
2996
2997
2998
2999
3000
3001 unsigned RegsNeeded = 0;
3003 RegsNeeded++;
3004
3005
3007 RegsNeeded++;
3008 }
3009
3010 if (RegsNeeded > NumExtraCSSpill) {
3011
3012
3013 unsigned NumExtras = TargetAlign.value() / 4;
3015 while (NumExtras && !UnspilledCS1GPRs.empty()) {
3016 unsigned Reg = UnspilledCS1GPRs.pop_back_val();
3017 if (.isReserved(Reg) &&
3020 NumExtras--;
3021 }
3022 }
3023
3025 while (NumExtras && !UnspilledCS2GPRs.empty()) {
3026 unsigned Reg = UnspilledCS2GPRs.pop_back_val();
3027 if (.isReserved(Reg)) {
3029 NumExtras--;
3030 }
3031 }
3032 }
3033 if (NumExtras == 0) {
3034 for (unsigned Reg : Extras) {
3035 SavedRegs.set(Reg);
3036 if (.isPhysRegUsed(Reg))
3037 NumExtraCSSpill++;
3038 }
3039 }
3040 while ((RegsNeeded > NumExtraCSSpill) && RS) {
3041
3042 LLVM_DEBUG(dbgs() << "Reserving emergency spill slot\n");
3044 unsigned Size = TRI->getSpillSize(RC);
3045 Align Alignment = TRI->getSpillAlign(RC);
3046 RS->addScavengingFrameIndex(
3047 MFI.CreateSpillStackObject(Size, Alignment));
3048 --RegsNeeded;
3049 }
3050 }
3051 }
3052
3053 if (ForceLRSpill)
3054 SavedRegs.set(ARM::LR);
3056}
3057
3061 return;
3062
3063
3064
3065
3067 if (Info.getReg() != ARM::LR)
3068 continue;
3071 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||
3072 Term.getOpcode() == ARM::t2LDMIA_RET ||
3073 Term.getOpcode() == ARM::tPOP_RET;
3074 });
3075 })) {
3076 Info.setRestored(false);
3077 break;
3078 }
3079 }
3080}
3081
3087
3091
3092
3093
3094
3097 SavedRegs.set(ARM::R0);
3098}
3099
3102 std::vector &CSI) const {
3103
3104
3105 if (STI.hasV8_1MMainlineOps() &&
3107 CSI.emplace_back(ARM::FPCXTNS);
3108 CSI.back().setRestored(false);
3109 }
3110
3111
3112
3113
3116
3117
3118
3119
3120 switch (STI.getPushPopSplitVariation(MF)) {
3122
3124 [=](const auto &CS) {
3126 return Reg == ARM::R10 || Reg == ARM::R11 ||
3127 Reg == ARM::R8 || Reg == ARM::R9 ||
3128 ARM::DPRRegClass.contains(Reg);
3129 }),
3131 break;
3133
3134
3136 break;
3139 "ABI-required frame pointers need a CSR split when signing return "
3140 "address.");
3142 [=](const auto &CS) {
3144 return Reg != ARM::LR;
3145 }),
3147 break;
3148 default:
3149 llvm_unreachable("Unexpected CSR split with return address signing");
3150 }
3151 }
3152
3153 return false;
3154}
3155
3158 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};
3159 NumEntries = std::size(FixedSpillOffsets);
3160 return FixedSpillOffsets;
3161}
3162
3171 unsigned Opc = I->getOpcode();
3172 bool IsDestroy = Opc == TII.getCallFrameDestroyOpcode();
3173 unsigned CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0;
3174
3176 "This eliminateCallFramePseudoInstr does not support Thumb1!");
3177
3178 int PIdx = I->findFirstPredOperandIdx();
3181 : (ARMCC::CondCodes)I->getOperand(PIdx).getImm();
3182 unsigned PredReg = TII.getFramePred(*I);
3183
3185
3186 if (IsDestroy && CalleePopAmount != -1U)
3188
3189
3190
3191
3192 unsigned Amount = TII.getFrameSize(*I);
3193 if (Amount != 0) {
3194
3195
3196
3198
3199 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {
3201 Pred, PredReg);
3202 } else {
3203 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);
3205 Pred, PredReg);
3206 }
3207 }
3208 } else if (CalleePopAmount != -1U) {
3209
3210
3213 }
3215}
3216
3217
3218
3219
3220
3222 unsigned Shifted = 0;
3223
3225 return 0;
3226
3227 while (!(Value & 0xC0000000)) {
3229 Shifted += 2;
3230 }
3231
3232 bool Carry = (Value & 0x00FFFFFF);
3233 Value = ((Value & 0xFF000000) >> 24) + Carry;
3234
3235 if (Value & 0x0000100)
3237
3238 if (Shifted > 24)
3240 else
3242
3244}
3245
3246
3247
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3276 unsigned Opcode;
3278 bool Thumb = ST->isThumb();
3279 bool Thumb2 = ST->isThumb2();
3280
3281
3282
3284 report_fatal_error("Segmented stacks do not support vararg functions.");
3285 if (!ST->isTargetAndroid() && !ST->isTargetLinux())
3286 report_fatal_error("Segmented stacks not supported on this platform.");
3287
3293
3295 return;
3296
3298
3299
3300
3301 unsigned ScratchReg0 = ARM::R4;
3302 unsigned ScratchReg1 = ARM::R5;
3303 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;
3305
3311
3312
3315 WalkList.push_back(&PrologueMBB);
3316
3317 do {
3320 if (BeforePrologueRegion.insert(PredBB).second)
3322 }
3323 } while (!WalkList.empty());
3324
3325
3326
3327
3328
3329 MachineBasicBlock *AddedBlocks[] = {PrevStackMBB, McrMBB, GetMBB, AllocMBB,
3330 PostStackMBB};
3331
3332 BeforePrologueRegion.insert_range(AddedBlocks);
3333
3334 for (const auto &LI : PrologueMBB.liveins()) {
3336 PredBB->addLiveIn(LI);
3337 }
3338
3339
3340
3342 BeforePrologueRegion.erase(B);
3344 }
3345
3347
3348 MBB->sortUniqueLiveIns();
3349
3350
3351 if (MBB->isSuccessor(&PrologueMBB))
3352 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);
3353 }
3354
3355
3357
3358
3359
3361
3362
3363
3364
3365
3366
3367
3368
3369 if (Thumb) {
3370 BuildMI(PrevStackMBB, DL, TII.get(ARM::tPUSH))
3372 .addReg(ScratchReg0)
3373 .addReg(ScratchReg1);
3374 } else {
3375 BuildMI(PrevStackMBB, DL, TII.get(ARM::STMDB_UPD))
3379 .addReg(ScratchReg0)
3380 .addReg(ScratchReg1);
3381 }
3382
3383
3384
3388 CFIBuilder.buildOffset(ScratchReg1, -4);
3389 CFIBuilder.buildOffset(ScratchReg0, -8);
3390 }
3391
3392
3393 if (Thumb) {
3394 BuildMI(McrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1)
3397 } else if (CompareStackPointer) {
3398 BuildMI(McrMBB, DL, TII.get(ARM::MOVr), ScratchReg1)
3402 }
3403
3404
3405 if (!CompareStackPointer && Thumb) {
3406 if (AlignedStackSize < 256) {
3407 BuildMI(McrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1)
3409 .addReg(ScratchReg1)
3410 .addImm(AlignedStackSize)
3412 } else {
3413 if (Thumb2 || ST->genExecuteOnly()) {
3414 BuildMI(McrMBB, DL, TII.get(MovOp), ScratchReg0)
3415 .addImm(AlignedStackSize);
3416 } else {
3417 auto MBBI = McrMBB->end();
3418 auto RegInfo = STI.getRegisterInfo();
3419 RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,
3420 AlignedStackSize);
3421 }
3422 BuildMI(McrMBB, DL, TII.get(ARM::tSUBrr), ScratchReg1)
3424 .addReg(ScratchReg1)
3425 .addReg(ScratchReg0)
3427 }
3428 } else if (!CompareStackPointer) {
3429 if (AlignedStackSize < 256) {
3430 BuildMI(McrMBB, DL, TII.get(ARM::SUBri), ScratchReg1)
3432 .addImm(AlignedStackSize)
3435 } else {
3436 auto MBBI = McrMBB->end();
3437 auto RegInfo = STI.getRegisterInfo();
3438 RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,
3439 AlignedStackSize);
3440 BuildMI(McrMBB, DL, TII.get(ARM::SUBrr), ScratchReg1)
3442 .addReg(ScratchReg0)
3445 }
3446 }
3447
3448 if (Thumb && ST->isThumb1Only()) {
3449 if (ST->genExecuteOnly()) {
3450 BuildMI(GetMBB, DL, TII.get(MovOp), ScratchReg0)
3452 } else {
3458
3459
3460 BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0)
3463 }
3464
3465
3466 BuildMI(GetMBB, DL, TII.get(ARM::tLDRi), ScratchReg0)
3467 .addReg(ScratchReg0)
3470 } else {
3471
3472
3473 BuildMI(McrMBB, DL, TII.get(Thumb ? ARM::t2MRC : ARM::MRC),
3474 ScratchReg0)
3481
3482
3483 assert(ST->isTargetAndroid() || ST->isTargetLinux());
3484 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
3485
3486
3487
3488 BuildMI(GetMBB, DL, TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),
3489 ScratchReg0)
3490 .addReg(ScratchReg0)
3491 .addImm(4 * TlsOffset)
3493 }
3494
3495
3496
3497 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;
3499 .addReg(ScratchReg0)
3500 .addReg(ScratchReg1)
3502
3503
3504 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;
3506 .addMBB(PostStackMBB)
3509
3510
3511
3512
3513
3514
3515
3516 if (Thumb) {
3517 if (AlignedStackSize < 256) {
3518 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0)
3520 .addImm(AlignedStackSize)
3522 } else {
3523 if (Thumb2 || ST->genExecuteOnly()) {
3524 BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg0)
3525 .addImm(AlignedStackSize);
3526 } else {
3527 auto MBBI = AllocMBB->end();
3528 auto RegInfo = STI.getRegisterInfo();
3529 RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,
3530 AlignedStackSize);
3531 }
3532 }
3533 } else {
3534 if (AlignedStackSize < 256) {
3535 BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg0)
3536 .addImm(AlignedStackSize)
3539 } else {
3540 auto MBBI = AllocMBB->end();
3541 auto RegInfo = STI.getRegisterInfo();
3542 RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,
3543 AlignedStackSize);
3544 }
3545 }
3546
3547
3548
3549 if (Thumb) {
3551 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1)
3555 } else {
3556 if (Thumb2 || ST->genExecuteOnly()) {
3557 BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg1)
3559 } else {
3560 auto MBBI = AllocMBB->end();
3561 auto RegInfo = STI.getRegisterInfo();
3562 RegInfo->emitLoadConstPool(
3563 *AllocMBB, MBBI, DL, ScratchReg1, 0,
3565 }
3566 }
3567 } else {
3569 BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg1)
3573 } else {
3574 auto MBBI = AllocMBB->end();
3575 auto RegInfo = STI.getRegisterInfo();
3576 RegInfo->emitLoadConstPool(
3577 *AllocMBB, MBBI, DL, ScratchReg1, 0,
3579 }
3580 }
3581
3582
3583 if (Thumb) {
3587 } else {
3588 BuildMI(AllocMBB, DL, TII.get(ARM::STMDB_UPD))
3593 }
3594
3595
3596
3601 }
3602
3603
3604 if (Thumb) {
3608 } else {
3611 }
3612
3613
3614 if (Thumb) {
3615 if (ST->isThumb1Only()) {
3618 .addReg(ScratchReg0);
3619 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVr), ARM::LR)
3620 .addReg(ScratchReg0)
3622 } else {
3623 BuildMI(AllocMBB, DL, TII.get(ARM::t2LDR_POST))
3629 }
3630 } else {
3631 BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))
3636 }
3637
3638
3639
3640
3641
3642 if (Thumb) {
3645 .addReg(ScratchReg0)
3646 .addReg(ScratchReg1);
3647 } else {
3648 BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))
3652 .addReg(ScratchReg0)
3653 .addReg(ScratchReg1);
3654 }
3655
3656
3659
3660
3662
3663
3664
3665 if (Thumb) {
3666 BuildMI(PostStackMBB, DL, TII.get(ARM::tPOP))
3668 .addReg(ScratchReg0)
3669 .addReg(ScratchReg1);
3670 } else {
3671 BuildMI(PostStackMBB, DL, TII.get(ARM::LDMIA_UPD))
3675 .addReg(ScratchReg0)
3676 .addReg(ScratchReg1);
3677 }
3678
3679
3683
3684
3685
3688 }
3689
3690
3692
3694
3697
3699
3701
3702#ifdef EXPENSIVE_CHECKS
3704#endif
3705}
unsigned const MachineRegisterInfo * MRI
static unsigned estimateRSStackSizeLimit(MachineFunction &MF)
Look at each instruction that references stack frames and return the stack size limit beyond which so...
static bool needsWinCFI(const MachineFunction *MF)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
static bool isThumb(const MCSubtargetInfo &STI)
static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)
Skip past the code inserted by emitAlignedDPRCS2Spills, and return an iterator to the following instr...
Definition ARMFrameLowering.cpp:2082
static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const unsigned Reg, const Align Alignment, const bool MustBeSingleInstruction)
Emit an instruction sequence that will align the address in register Reg by zero-ing out the lower bi...
Definition ARMFrameLowering.cpp:796
static uint32_t alignToARMConstant(uint32_t Value)
Get the minimum constant for ARM that is greater than or equal to the argument.
Definition ARMFrameLowering.cpp:3221
static void checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs)
Definition ARMFrameLowering.cpp:2423
static void insertSEHRange(MachineBasicBlock &MBB, MachineBasicBlock::iterator Start, const MachineBasicBlock::iterator &End, const ARMBaseInstrInfo &TII, unsigned MIFlags)
Definition ARMFrameLowering.cpp:649
static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
Definition ARMFrameLowering.cpp:2112
static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)
Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers starting from d8.
Definition ARMFrameLowering.cpp:1939
static int getArgumentStackToRestore(MachineFunction &MF, MachineBasicBlock &MBB)
Definition ARMFrameLowering.cpp:390
static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
Definition ARMFrameLowering.cpp:686
static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)
Definition ARMFrameLowering.cpp:2321
static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, const TargetInstrInfo &TII, unsigned Flags)
Definition ARMFrameLowering.cpp:429
SpillArea getSpillArea(Register Reg, ARMSubtarget::PushPopSplitVariation Variation, unsigned NumAlignedDPRCS2Regs, const ARMBaseRegisterInfo *RegInfo)
Get the spill area that Reg should be saved into in the prologue.
Definition ARMFrameLowering.cpp:183
static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI)
Definition ARMFrameLowering.cpp:2492
static bool WindowsRequiresStackProbe(const MachineFunction &MF, size_t StackSizeInBytes)
Definition ARMFrameLowering.cpp:721
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, const MachineFunction &MF)
We need the offset of the frame pointer relative to other MachineFrameInfo offsets which are encoded ...
Definition ARMFrameLowering.cpp:862
static MachineBasicBlock::iterator initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI)
Definition ARMFrameLowering.cpp:643
static int sizeOfSPAdjustment(const MachineInstr &MI)
Definition ARMFrameLowering.cpp:696
static const uint64_t kSplitStackAvailable
Definition ARMFrameLowering.cpp:3248
SpillArea
Definition ARMFrameLowering.cpp:172
@ FPCXT
Definition ARMFrameLowering.cpp:179
@ GPRCS3
Definition ARMFrameLowering.cpp:178
@ DPRCS1
Definition ARMFrameLowering.cpp:176
@ DPRCS2
Definition ARMFrameLowering.cpp:177
@ GPRCS2
Definition ARMFrameLowering.cpp:174
@ GPRCS1
Definition ARMFrameLowering.cpp:173
@ FPStatus
Definition ARMFrameLowering.cpp:175
static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))
static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)
Definition ARMFrameLowering.cpp:673
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const unsigned FramePtr
bool canRealignStack(const MachineFunction &MF) const override
static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)
ARMConstantPoolValue - ARM specific constantpool value.
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
Definition ARMFrameLowering.cpp:2268
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.
Definition ARMFrameLowering.cpp:1563
bool keepFramePointer(const MachineFunction &MF) const
Definition ARMFrameLowering.cpp:313
static void updateLRRestored(MachineFunction &MF)
Update the IsRestored flag on LR if it is spilled, based on the return instructions.
Definition ARMFrameLowering.cpp:3058
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
Definition ARMFrameLowering.cpp:885
ARMFrameLowering(const ARMSubtarget &sti)
Definition ARMFrameLowering.cpp:309
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
Definition ARMFrameLowering.cpp:2466
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Definition ARMFrameLowering.cpp:1393
bool requiresAAPCSFrameRecord(const MachineFunction &MF) const
Definition ARMFrameLowering.cpp:2483
bool isFPReserved(const MachineFunction &MF) const
isFPReserved - Return true if the frame pointer register should be considered a reserved register on ...
Definition ARMFrameLowering.cpp:354
bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override
canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...
Definition ARMFrameLowering.cpp:381
void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &MBB) const override
Adjust the prologue to have the function use segmented stacks.
Definition ARMFrameLowering.cpp:3274
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
Definition ARMFrameLowering.cpp:2202
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
Definition ARMFrameLowering.cpp:363
const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override
getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs, that contains an entry...
Definition ARMFrameLowering.cpp:3157
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
Definition ARMFrameLowering.cpp:3082
bool hasFPImpl(const MachineFunction &MF) const override
hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.
Definition ARMFrameLowering.cpp:335
int ResolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, int SPAdj) const
Definition ARMFrameLowering.cpp:1569
void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const override
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
Definition ARMFrameLowering.cpp:3088
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
Definition ARMFrameLowering.cpp:2513
bool enableCalleeSaveSkip(const MachineFunction &MF) const override
Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functi...
Definition ARMFrameLowering.cpp:322
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
Definition ARMFrameLowering.cpp:3100
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool hasStackFrame() const
bool isThumb2Function() const
unsigned getFPCXTSaveAreaSize() const
unsigned getGPRCalleeSavedArea1Size() const
unsigned getDPRCalleeSavedGapSize() const
unsigned getDPRCalleeSavedArea1Size() const
unsigned createPICLabelUId()
void setLRIsSpilled(bool s)
void setDPRCalleeSavedArea1Offset(unsigned o)
void setGPRCalleeSavedArea2Size(unsigned s)
bool isThumb1OnlyFunction() const
void setHasStackFrame(bool s)
bool isThumbFunction() const
void setFramePtrSpillOffset(unsigned o)
unsigned getGPRCalleeSavedArea2Size() const
unsigned getNumAlignedDPRCS2Regs() const
bool shouldSignReturnAddress() const
void setGPRCalleeSavedArea1Size(unsigned s)
unsigned getArgumentStackToRestore() const
void setFPCXTSaveAreaSize(unsigned s)
bool isCmseNSEntryFunction() const
unsigned getGPRCalleeSavedArea3Size() const
unsigned getFramePtrSpillOffset() const
bool shouldRestoreSPFromFP() const
unsigned getArgRegsSaveSize() const
void setGPRCalleeSavedArea2Offset(unsigned o)
void setGPRCalleeSavedArea1Offset(unsigned o)
void setDPRCalleeSavedArea1Size(unsigned s)
void setDPRCalleeSavedGapSize(unsigned s)
void setFPStatusSavesSize(unsigned s)
unsigned getArgumentStackSize() const
void setShouldRestoreSPFromFP(bool s)
unsigned getReturnRegsCount() const
void setGPRCalleeSavedArea3Size(unsigned s)
bool getPreservesR0() const
unsigned getFPStatusSavesSize() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
enum PushPopSplitVariation getPushPopSplitVariation(const MachineFunction &MF) const
PushPopSplitVariation
How the push and pop instructions of callee saved general-purpose registers should be split.
@ SplitR11WindowsSEH
When the stack frame size is not known (because of variable-sized objects or realignment),...
@ SplitR7
R7 and LR must be adjacent, because R7 is the frame pointer, and must point to a frame record consist...
@ SplitR11AAPCSSignRA
When generating AAPCS-compilant frame chains, R11 is the frame pointer, and must be pushed adjacent t...
@ NoSplit
All GPRs can be pushed in a single instruction.
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 empty() const
empty - Check if the array is empty.
bool test(unsigned Idx) const
Helper class for creating CFI instructions and inserting them into MIR.
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void buildDefCFARegister(MCRegister Reg) const
void buildSameValue(MCRegister Reg) const
void buildOffset(MCRegister Reg, int64_t Offset) const
void buildDefCFA(MCRegister Reg, int64_t Offset) const
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool usesWindowsCFI() const
Describe properties that are true of each instruction in the target description file.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Wrapper class representing physical registers. Should be passed by value.
iterator_range< livein_iterator > liveins() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
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.
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
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.
bool needsSplitStackProlog() const
Return true if this function requires a split stack prolog, even if it uses no stack space.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int getStackProtectorIndex() const
Return the index for the stack protector object.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const
Return a set of physical registers that are pristine.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
void setHasWinCFI(bool v)
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const
Run the current MachineFunction through the machine code verifier, useful for debugger 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 MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
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 & 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 & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
bool isValid() const
Check for null.
Representation of each machine instruction.
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool isLiveIn(Register Reg) const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Wrapper class representing virtual and physical registers.
bool erase(PtrType Ptr)
Remove pointer from the set.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
iterator erase(const_iterator CI)
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
Information about stack frame layout on the target.
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
virtual void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const
Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
int alignSPAdjust(int SPAdj) const
alignSPAdjust - This method aligns the stack adjustment to the correct alignment.
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
LLVM_ABI bool FramePointerIsReserved(const MachineFunction &MF) const
FramePointerIsReserved - This returns true if the frame pointer must always either point to a new fra...
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)
unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)
@ D16
Only 16 D registers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ 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.
initializer< Ty > init(const Ty &Val)
NodeAddr< FuncNode * > Func
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.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static bool isARMLowRegister(MCRegister Reg)
isARMLowRegister - Returns true if the register is a low register (r0-r7).
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)
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...
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
unsigned getDefRegState(bool B)
unsigned getKillRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionAddr VTableAddr Next
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
unsigned Log2(Align A)
Returns the log2 of the alignment.
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...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void emitT2RegPlusImmediate(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)
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.