LLVM: lib/Target/RISCV/RISCVFrameLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
28
29#include
30
31#define DEBUG_TYPE "riscv-frame"
32
33using namespace llvm;
34
42
49
50
52
53
55
56
58
59
60
61
62
65 RISCV::X18, RISCV::X19, RISCV::X20,
66 RISCV::X21, RISCV::X22, RISCV::X23,
67 RISCV::X24, RISCV::X25, RISCV::X26,
68 RISCV::X27};
69
70
71
73
75
76 { FPReg, -2},
77
78 { RAReg, -4},
79
80 { RISCV::X5, -6},
81 { RISCV::X6, -7},
82 { RISCV::X7, -8},
83 { RISCV::X10, -9},
84 { RISCV::X11, -10},
85 { RISCV::X12, -11},
86 { RISCV::X13, -12},
87 { RISCV::X14, -13},
88 { RISCV::X15, -14},
89 { RISCV::X16, -15},
90 { RISCV::X17, -16},
91 { RISCV::X28, -17},
92 { RISCV::X29, -18},
93 { RISCV::X30, -19},
94 { RISCV::X31, -20},
95
96};
97
98
102
103
104
109
110
111
112
113
114
116 STI.hasStdExtZimop();
117 bool HasSWShadowStack =
119 if (!HasHWShadowStack && !HasSWShadowStack)
120 return;
121
123
124
125
129 return;
130
132 if (HasHWShadowStack) {
133 if (STI.hasStdExtZcmop()) {
134 static_assert(RAReg == RISCV::X1, "C.SSPUSH only accepts X1");
136 } else {
138 }
139 return;
140 }
141
143
144 bool IsRV64 = STI.is64Bit();
145 int64_t SlotSize = STI.getXLen() / 8;
146
147
148
159
161 return;
162
163
164
165 char DwarfSCSReg = TRI->getDwarfRegNum(SCSPReg, true);
166 assert(DwarfSCSReg < 32 && "SCS Register should be < 32 (X3).");
167
168 char Offset = static_cast<char>(-SlotSize) & 0x7f;
169 const char CFIInst[] = {
170 dwarf::DW_CFA_val_expression,
171 DwarfSCSReg,
172 2,
173 static_cast<char>(unsigned(dwarf::DW_OP_breg0 + DwarfSCSReg)),
174 Offset,
175 };
176
179}
180
186 STI.hasStdExtZimop();
187 bool HasSWShadowStack =
189 if (!HasHWShadowStack && !HasSWShadowStack)
190 return;
191
192
196 return;
197
199 if (HasHWShadowStack) {
201 return;
202 }
203
205
206 bool IsRV64 = STI.is64Bit();
207 int64_t SlotSize = STI.getXLen() / 8;
208
209
210
222
224 }
225}
226
227
232
233 if (!RVFI->isSiFiveStackSwapInterrupt(MF))
234 return;
235
238
239 assert(STI.hasVendorXSfmclic() && "Stack Swapping Requires XSfmclic");
240
243 .addImm(RISCVSysReg::sf_mscratchcsw)
246
247
248}
249
250static void
254 return;
255
260
261
262
263
264 for (int I = 0; I < 2; ++I) {
266 true);
268 }
269}
270
276
277 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
278 return;
279
282
283
284
285
286
287
288
289
290
291
292 TII->storeRegToStackSlot(MBB, MBBI, RISCV::X8, true,
293 RVFI->getInterruptCSRFrameIndex(0),
294 &RISCV::GPRRegClass, Register(),
296 TII->storeRegToStackSlot(MBB, MBBI, RISCV::X9, true,
297 RVFI->getInterruptCSRFrameIndex(1),
298 &RISCV::GPRRegClass, Register(),
300
301
302
303
306 .addImm(RISCVSysReg::mcause)
311 .addImm(RISCVSysReg::mepc)
314
315
318 .addImm(RISCVSysReg::mstatus)
321}
322
328
329 if (!RVFI->isSiFivePreemptibleInterrupt(MF))
330 return;
331
334
335
336
337
340 .addImm(RISCVSysReg::mstatus)
343
344
345
346
349 .addImm(RISCVSysReg::mepc)
354 .addImm(RISCVSysReg::mcause)
357
358
359
360 TII->loadRegFromStackSlot(
361 MBB, MBBI, RISCV::X9, RVFI->getInterruptCSRFrameIndex(1),
363 TII->loadRegFromStackSlot(
364 MBB, MBBI, RISCV::X8, RVFI->getInterruptCSRFrameIndex(0),
366}
367
368
369
370
371
373 const std::vector &CSI) {
375
376 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
377 return -1;
378
380 for (auto &CS : CSI)
381
382
383 if (CS.getFrameIdx() < 0)
384 MaxReg = std::max(MaxReg.id(), CS.getReg().id());
385
386 if (!MaxReg)
387 return -1;
388
389 switch (MaxReg.id()) {
390 default:
392
393 case RISCV::X27: return 12;
394 case RISCV::X26: return 11;
395 case RISCV::X25: return 10;
396 case RISCV::X24: return 9;
397 case RISCV::X23: return 8;
398 case RISCV::X22: return 7;
399 case RISCV::X21: return 6;
400 case RISCV::X20: return 5;
401 case RISCV::X19: return 4;
402 case RISCV::X18: return 3;
403 case RISCV::X9: return 2;
404 case FPReg: return 1;
405 case RAReg: return 0;
406
407 }
408}
409
410
411
412static const char *
414 const std::vector &CSI) {
415 static const char *const SpillLibCalls[] = {
416 "__riscv_save_0",
417 "__riscv_save_1",
418 "__riscv_save_2",
419 "__riscv_save_3",
420 "__riscv_save_4",
421 "__riscv_save_5",
422 "__riscv_save_6",
423 "__riscv_save_7",
424 "__riscv_save_8",
425 "__riscv_save_9",
426 "__riscv_save_10",
427 "__riscv_save_11",
428 "__riscv_save_12"
429 };
430
432 if (LibCallID == -1)
433 return nullptr;
434 return SpillLibCalls[LibCallID];
435}
436
437
438
439static const char *
441 const std::vector &CSI) {
442 static const char *const RestoreLibCalls[] = {
443 "__riscv_restore_0",
444 "__riscv_restore_1",
445 "__riscv_restore_2",
446 "__riscv_restore_3",
447 "__riscv_restore_4",
448 "__riscv_restore_5",
449 "__riscv_restore_6",
450 "__riscv_restore_7",
451 "__riscv_restore_8",
452 "__riscv_restore_9",
453 "__riscv_restore_10",
454 "__riscv_restore_11",
455 "__riscv_restore_12"
456 };
457
459 if (LibCallID == -1)
460 return nullptr;
461 return RestoreLibCalls[LibCallID];
462}
463
464
466 unsigned NumPushPopRegs = 0;
467 for (auto &CS : CSI) {
469 [&](MCPhysReg P) { return P == CS.getReg(); });
471 unsigned RegNum = std::distance(std::begin(FixedCSRFIMap), FII);
472 NumPushPopRegs = std::max(NumPushPopRegs, RegNum + 1);
473 }
474 }
475 assert(NumPushPopRegs != 12 && "x26 requires x27 to also be pushed");
476 return NumPushPopRegs;
477}
478
479
480
481
482
491
495
496
497
498
499
503 TRI->hasStackRealignment(MF);
504}
505
506
507void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
510
511
513
514
515 if (RVFI->useQCIInterrupt(MF))
517
518
520
521
522 FrameSize = alignTo(FrameSize, StackAlign);
523
524
526
527
528
529
530
532 if (RVFI->getRVVStackSize() && ((MF) || TRI->hasStackRealignment(MF))) {
533 int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() -
534 RVFI->getVarArgsSaveSize();
535 if (auto RVVPadding =
537 RVFI->setRVVPadding(RVVPadding);
538 }
539}
540
541
542
549
552 const std::vector &CSI) {
555
556 for (auto &CS : CSI) {
557 int FI = CS.getFrameIdx();
560 }
561
562 return NonLibcallCSI;
563}
564
567 const std::vector &CSI) {
570
571 for (auto &CS : CSI) {
572 int FI = CS.getFrameIdx();
575 }
576
577 return RVVCSI;
578}
579
582 const std::vector &CSI) {
584
586 if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
587 return PushOrLibCallsCSI;
588
589 for (const auto &CS : CSI) {
590 if (RVFI->useQCIInterrupt(MF)) {
591
592
593
594
596 CS.getReg()))
597 continue;
598 }
599
601 PushOrLibCallsCSI.push_back(CS);
602 }
603
604 return PushOrLibCallsCSI;
605}
606
609 const std::vector &CSI) {
611
613 if (!RVFI->useQCIInterrupt(MF))
614 return QCIInterruptCSI;
615
616 for (const auto &CS : CSI) {
618 CS.getReg()))
619 QCIInterruptCSI.push_back(CS);
620 }
621
622 return QCIInterruptCSI;
623}
624
625void RISCVFrameLowering::allocateAndProbeStackForRVV(
629 assert(Amount != 0 && "Did not need to adjust stack pointer for RVV.");
630
631
632
633
634 const RISCVInstrInfo *TII = STI.getInstrInfo();
635 Register TargetReg = RISCV::X6;
639 TII->mulImm(MF, MBB, MBBI, DL, TargetReg, NumOfVReg, Flag);
640
642 if (EmitCFI) {
643
644 CFIBuilder.buildDefCFA(TargetReg, -Amount);
645 }
646
647
650
651 if (EmitCFI) {
652
653 CFIBuilder.buildDefCFARegister(SPReg);
654 }
655
656
661
662
663 if (DynAllocation) {
669 }
670}
671
674 int FixedOffset, int ScalableOffset,
676 unsigned DwarfVLenB = TRI.getDwarfRegNum(RISCV::VLENB, true);
678 if (FixedOffset) {
679 Expr.push_back(dwarf::DW_OP_consts);
682 Comment << (FixedOffset < 0 ? " - " : " + ") << std::abs(FixedOffset);
683 }
684
687
691
694
695 Comment << (ScalableOffset < 0 ? " - " : " + ") << std::abs(ScalableOffset)
696 << " * vlenb";
697}
698
703 assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
705 std::string CommentBuffer;
707
708 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
712 Comment << "sp";
713 else
715
717 Comment);
718
721 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
724
726 Comment.str());
727}
728
732 assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
734 std::string CommentBuffer;
737
738
740 Comment);
741
744 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
745 DefCfaExpr.push_back(dwarf::DW_CFA_expression);
749
751 Comment.str());
752}
753
754
758 uint64_t RealStackSize, bool EmitCFI,
759 bool NeedProbe, uint64_t ProbeSize,
760 bool DynAllocation,
765 bool IsRV64 = STI.is64Bit();
767
768
769 if (!NeedProbe || Offset <= ProbeSize) {
772
773 if (EmitCFI)
775
776 if (NeedProbe && DynAllocation) {
777
783 }
784
785 return;
786 }
787
788
789 if (Offset < ProbeSize * 5) {
791
793 while (CurrentOffset + ProbeSize <= Offset) {
796
802
803 CurrentOffset += ProbeSize;
804 if (EmitCFI)
806 }
807
809 if (Residual) {
812 if (EmitCFI)
814
815 if (DynAllocation) {
816
822 }
823 }
824
825 return;
826 }
827
828
831
832 Register TargetReg = RISCV::X6;
833
836
837 if (EmitCFI) {
838
839 CFIBuilder.buildDefCFA(TargetReg, RoundedSize);
840 }
841
842
844
845 if (EmitCFI) {
846
848 }
849
850 if (Residual) {
853 if (DynAllocation) {
854
860 }
861 }
862
863 if (EmitCFI)
865}
866
867static bool isPush(unsigned Opcode) {
868 switch (Opcode) {
869 case RISCV::CM_PUSH:
870 case RISCV::QC_CM_PUSH:
871 case RISCV::QC_CM_PUSHFP:
872 return true;
873 default:
874 return false;
875 }
876}
877
878static bool isPop(unsigned Opcode) {
879
880
881 switch (Opcode) {
882 case RISCV::CM_POP:
883 case RISCV::QC_CM_POP:
884 return true;
885 default:
886 return false;
887 }
888}
889
891 bool UpdateFP) {
892 switch (Kind) {
894 return RISCV::CM_PUSH;
896 return UpdateFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
897 default:
899 }
900}
901
903
904
905 switch (Kind) {
907 return RISCV::CM_POP;
909 return RISCV::QC_CM_POP;
910 default:
912 }
913}
914
921
923
924
925
927
928
929
931 return;
932
933
935
936
938
939
940
941
942 auto PossiblePush = MBBI;
943
944
947
948
949 determineFrameLayout(MF);
950
952
953
954
955
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
980
981
982
983 unsigned LibCallFrameSize =
985 RVFI->setLibCallStackSize(LibCallFrameSize);
986
987 if (NeedsDwarfCFI) {
992 }
993 }
994
995
996
998 uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
999 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1000
1001
1002 if (RealStackSize == 0 && !MFI.adjustsStack() && RVVStackSize == 0)
1003 return;
1004
1005
1006
1007 if (STI.isRegisterReservedByUser(SPReg))
1009 MF.getFunction(), "Stack pointer required, but has been reserved."});
1010
1012
1013 if (FirstSPAdjustAmount) {
1014 StackSize = FirstSPAdjustAmount;
1015 RealStackSize = FirstSPAdjustAmount;
1016 }
1017
1018 if (RVFI->useQCIInterrupt(MF)) {
1019
1020
1021 ++PossiblePush;
1022
1023 if (NeedsDwarfCFI) {
1024
1025
1026
1033 }
1034 }
1035
1036 if (RVFI->isPushable(MF) && PossiblePush != MBB.end() &&
1037 isPush(PossiblePush->getOpcode())) {
1038
1039
1040
1041
1044 PossiblePush->getOperand(1).setImm(StackAdj);
1045 StackSize -= StackAdj;
1046
1047 if (NeedsDwarfCFI) {
1052 }
1053 }
1054
1055
1060 bool DynAllocation =
1062 if (StackSize != 0)
1064 NeedProbe, ProbeSize, DynAllocation,
1066
1067
1069
1070
1071
1072
1073
1074
1075
1078
1079
1080
1081 if (NeedsDwarfCFI)
1085
1086
1087 if (hasFP(MF)) {
1088 if (STI.isRegisterReservedByUser(FPReg))
1090 MF.getFunction(), "Frame pointer required, but has been reserved."});
1091
1093
1094
1095
1096 if (!RVFI->hasImplicitFPUpdates(MF)) {
1097 RI->adjustReg(
1101 }
1102
1103 if (NeedsDwarfCFI)
1105 }
1106
1107 uint64_t SecondSPAdjustAmount = 0;
1108
1109 if (FirstSPAdjustAmount) {
1111 assert(SecondSPAdjustAmount > 0 &&
1112 "SecondSPAdjustAmount should be greater than zero");
1113
1116 NeedProbe, ProbeSize, DynAllocation,
1118 }
1119
1120 if (RVVStackSize) {
1121 if (NeedProbe) {
1122 allocateAndProbeStackForRVV(MF, MBB, MBBI, DL, RVVStackSize,
1124 NeedsDwarfCFI && (MF), DynAllocation);
1125 } else {
1126
1127
1131 }
1132
1133 if (NeedsDwarfCFI && (MF)) {
1134
1137 }
1138
1140 if (NeedsDwarfCFI)
1141 emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
1142 }
1143
1144 if (hasFP(MF)) {
1145
1147 if (RI->hasStackRealignment(MF)) {
1149
1151 if (isInt<12>(-(int)MaxAlignment.value())) {
1154 .addImm(-(int)MaxAlignment.value())
1156 } else {
1157 unsigned ShiftAmount = Log2(MaxAlignment);
1162 .addImm(ShiftAmount)
1166 .addImm(ShiftAmount)
1168 }
1169 if (NeedProbe && RVVStackSize == 0) {
1170
1171
1172 if (SecondSPAdjustAmount < ProbeSize &&
1173 SecondSPAdjustAmount + MaxAlignment.value() >= ProbeSize) {
1174 bool IsRV64 = STI.is64Bit();
1180 }
1181 }
1182
1183
1184
1185 if (hasBP(MF)) {
1186
1191 }
1192 }
1193 }
1194}
1195
1196void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
1201 int64_t CFAOffset) const {
1203
1206 StackSize = 0;
1207
1211}
1212
1218
1219
1220
1222 return;
1223
1224
1225
1228 if (.empty()) {
1229 MBBI = MBB.getLastNonDebugInstr();
1231 DL = MBBI->getDebugLoc();
1232
1233 MBBI = MBB.getFirstTerminator();
1234
1235
1236 while (MBBI != MBB.begin() &&
1239 }
1240
1242
1243
1244
1245
1246 auto FirstScalarCSRRestoreInsn =
1251
1253 uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1255 uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1257 RVFI->getReservedSpillsSize();
1258 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
1259 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1260
1261 bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
1263 if (RVVStackSize) {
1264
1265
1266 if (!RestoreSPFromFP)
1270
1271 if (NeedsDwarfCFI) {
1274 emitCalleeSavedRVVEpilogCFI(MBB, FirstScalarCSRRestoreInsn);
1275 }
1276 }
1277
1278 if (FirstSPAdjustAmount) {
1279 uint64_t SecondSPAdjustAmount =
1281 assert(SecondSPAdjustAmount > 0 &&
1282 "SecondSPAdjustAmount should be greater than zero");
1283
1284
1285
1286 if (!RestoreSPFromFP)
1290
1291 if (NeedsDwarfCFI && (MF))
1293 }
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305 if (RestoreSPFromFP) {
1306 assert(hasFP(MF) && "frame pointer should not have been eliminated");
1310 }
1311
1312 if (NeedsDwarfCFI && hasFP(MF))
1314
1315
1316
1317
1320
1322
1323
1324
1325 if (StackSize != 0)
1326 deallocateStack(MF, MBB, MBBI, DL, StackSize,
1327 RVFI->getLibCallStackSize());
1328
1329
1331 return;
1332 }
1333
1334
1335 if (NeedsDwarfCFI)
1338
1339 if (RVFI->isPushable(MF) && MBBI != MBB.end() && isPop(MBBI->getOpcode())) {
1340
1341
1342
1343
1346 MBBI->getOperand(1).setImm(StackAdj);
1347 StackSize -= StackAdj;
1348
1349 if (StackSize != 0)
1350 deallocateStack(MF, MBB, MBBI, DL, StackSize,
1351 RealStackSize - StackSize);
1352
1354 if (NextI == MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
1356 if (NeedsDwarfCFI) {
1358
1361
1362
1363
1364
1366 }
1367 }
1368 }
1369
1371
1372
1373
1374
1375 if (StackSize != 0)
1376 deallocateStack(MF, MBB, MBBI, DL, StackSize,
1377 RVFI->getQCIInterruptStackSize());
1378
1379
1381
1382
1384}
1385
1392
1393
1394
1395
1397 int MinCSFI = 0;
1398 int MaxCSFI = -1;
1401
1404 "Unexpected stack ID for the frame object.");
1411 }
1412
1414
1415 if (CSI.size()) {
1416 MinCSFI = CSI[0].getFrameIdx();
1417 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
1418 }
1419
1420 if (FI >= MinCSFI && FI <= MaxCSFI) {
1421 FrameReg = SPReg;
1422
1423 if (FirstSPAdjustAmount)
1425 else
1428 }
1429
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 if (hasBP(MF)) {
1465 } else {
1466
1468 FrameReg = SPReg;
1469 }
1470 } else {
1472 }
1473
1474 if (FrameReg == FPReg) {
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1493 "Can't index across variable sized realign");
1494
1495
1496
1498 "Inconsistent stack layout");
1500 }
1502 }
1503
1504
1505
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1541 "Can't index across variable sized realign");
1543 RVFI->getRVVStackSize());
1544 } else {
1546 }
1548
1549
1550 int ScalarLocalVarSize = MFI.getStackSize() -
1551 RVFI->getCalleeSavedStackSize() -
1552 RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding();
1554 }
1556}
1557
1561
1562
1563 if (!BaseReg.isValid())
1564 BaseReg = Reg;
1565 return BaseReg;
1566}
1567
1572
1573
1574
1575
1576
1577
1578
1579
1581 const MCPhysReg *CSRegs = MRI.getCalleeSavedRegs();
1583 for (unsigned i = 0; CSRegs[i]; ++i) {
1584 unsigned CSReg = CSRegs[i];
1585
1587 continue;
1588
1589 SavedRegs.reset(CSReg);
1590
1591 auto SubRegs = TRI.subregs(CSReg);
1592
1593 if (.def_empty(CSReg) || MRI.getUsedPhysRegsMask().test(CSReg)) {
1594 SavedRegs.set(CSReg);
1595 for (unsigned Reg : SubRegs)
1596 SavedRegs.set(Reg);
1597 }
1598
1599
1600 if (!SubRegs.empty() && llvm::all_of(SubRegs, [&](unsigned Reg) {
1601 return SavedRegs.test(Reg);
1602 }))
1603 SavedRegs.set(CSReg);
1604 }
1605
1606
1607
1608 if (hasFP(MF)) {
1611 }
1612
1615
1616
1618 if (RVFI->isPushable(MF) && SavedRegs.test(RISCV::X26))
1619 SavedRegs.set(RISCV::X27);
1620
1621
1623}
1624
1625std::pair<int64_t, Align>
1626RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFunction &MF) const {
1628
1630 auto pushRVVObjects = [&](int FIBegin, int FIEnd) {
1631 for (int I = FIBegin, E = FIEnd; I != E; ++I) {
1634 continue;
1636 continue;
1637
1639 }
1640 };
1641
1644 if (!RVVCSI.empty())
1645 pushRVVObjects(RVVCSI[0].getFrameIdx(),
1646 RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1);
1648
1649
1650 Align RVVStackAlign(16);
1652
1653 if (.hasVInstructions()) {
1655 "Can't allocate scalable-vector objects without V instructions");
1656 return std::make_pair(0, RVVStackAlign);
1657 }
1658
1659
1661 for (int FI : ObjectsToAllocate) {
1662
1664 auto ObjectAlign =
1666
1667
1672
1673 RVVStackAlign = std::max(RVVStackAlign, ObjectAlign);
1674 }
1675
1676 uint64_t StackSize = Offset;
1677
1678
1679
1680
1681
1682
1683
1684 auto VScale =
1686 if (auto RVVStackAlignVScale = RVVStackAlign.value() / VScale) {
1687 if (auto AlignmentPadding =
1689 StackSize += AlignmentPadding;
1690 for (int FI : ObjectsToAllocate)
1692 }
1693 }
1694
1695 return std::make_pair(StackSize, RVVStackAlign);
1696}
1697
1699
1700
1701 static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2;
1702
1703
1704
1705 static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1;
1706
1707
1708
1709 static constexpr unsigned ScavSlotsADDIScalableObject = 1;
1710
1711 static constexpr unsigned MaxScavSlotsNumKnown =
1712 std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject,
1713 ScavSlotsNumRVVSpillNonScalableObject});
1714
1715 unsigned MaxScavSlotsNum = 0;
1717 return false;
1721 for (auto &MO : MI.operands()) {
1722 if (!MO.isFI())
1723 continue;
1726 if (IsRVVSpill) {
1727 MaxScavSlotsNum = std::max(
1728 MaxScavSlotsNum, IsScalableVectorID
1729 ? ScavSlotsNumRVVSpillScalableObject
1730 : ScavSlotsNumRVVSpillNonScalableObject);
1731 } else if (MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) {
1732 MaxScavSlotsNum =
1733 std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject);
1734 }
1735 }
1736 if (MaxScavSlotsNum == MaxScavSlotsNumKnown)
1737 return MaxScavSlotsNumKnown;
1738 }
1739 return MaxScavSlotsNum;
1740}
1741
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1759}
1760
1763 unsigned FnSize = 0;
1764 for (auto &MBB : MF) {
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783 if (MI.isConditionalBranch())
1784 FnSize += TII.getInstSizeInBytes(MI);
1785 if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
1787 FnSize += 2 + 8 + 2 + 2;
1788 else
1789 FnSize += 4 + 8 + 4 + 4;
1790 continue;
1791 }
1792
1793 FnSize += TII.getInstSizeInBytes(MI);
1794 }
1795 }
1796 return FnSize;
1797}
1798
1807
1808 int64_t RVVStackSize;
1809 Align RVVStackAlign;
1810 std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MF);
1811
1812 RVFI->setRVVStackSize(RVVStackSize);
1813 RVFI->setRVVStackAlign(RVVStackAlign);
1814
1816
1817
1818
1820 }
1821
1822 unsigned ScavSlotsNum = 0;
1823
1824
1825
1826
1828 ScavSlotsNum = 1;
1829
1830
1832 if (IsLargeFunction)
1833 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
1834
1835
1836
1837
1839
1840 for (unsigned I = 0; I < ScavSlotsNum; I++) {
1842 RegInfo->getSpillAlign(*RC));
1843 RS->addScavengingFrameIndex(FI);
1844
1845 if (IsLargeFunction && RVFI->getBranchRelaxationScratchFrameIndex() == -1)
1846 RVFI->setBranchRelaxationScratchFrameIndex(FI);
1847 }
1848
1849 unsigned Size = RVFI->getReservedSpillsSize();
1851 int FrameIdx = Info.getFrameIdx();
1853 continue;
1854
1856 }
1857 RVFI->setCalleeSavedStackSize(Size);
1858}
1859
1860
1861
1862
1863
1868
1869
1874
1876
1877
1878
1879
1880
1881 int64_t Amount = MI->getOperand(0).getImm();
1882
1883 if (Amount != 0) {
1884
1886
1887 if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
1888 Amount = -Amount;
1889
1894
1895
1896
1897 bool DynAllocation =
1901 true, ProbeSize, DynAllocation,
1903 } else {
1907 }
1908 }
1909 }
1910
1912}
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1929 const std::vector &CSI = MFI.getCalleeSavedInfo();
1931
1932
1933
1934
1935 if (RVFI->getReservedSpillsSize())
1936 return 0;
1937
1938
1939
1940 if ((StackSize) && (CSI.size() > 0)) {
1941
1942
1943
1944
1945
1946
1948
1949
1950
1951
1952
1953 if (STI.hasStdExtZca()) {
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963 const uint64_t RVCompressLen = STI.getXLen() * 8;
1964
1965
1966
1967
1968
1969
1970 auto CanCompress = [&](uint64_t CompressLen) -> bool {
1971 if (StackSize <= 2047 + CompressLen ||
1972 (StackSize > 2048 * 2 - StackAlign &&
1973 StackSize <= 2047 * 2 + CompressLen) ||
1974 StackSize > 2048 * 3 - StackAlign)
1975 return true;
1976
1977 return false;
1978 };
1979
1980
1981
1982 const uint64_t ADDI16SPCompressLen = 496;
1983 if (STI.is64Bit() && CanCompress(ADDI16SPCompressLen))
1984 return ADDI16SPCompressLen;
1985 if (CanCompress(RVCompressLen))
1986 return RVCompressLen;
1987 }
1988 return 2048 - StackAlign;
1989 }
1990 return 0;
1991}
1992
1995 std::vector &CSI) const {
1999
2000
2001
2002 if (RVFI->isSiFivePreemptibleInterrupt(MF)) {
2003 for (int I = 0; I < 2; ++I) {
2004 int FI = RVFI->getInterruptCSRFrameIndex(I);
2005 MFI.setIsCalleeSavedObjectIndex(FI, true);
2006 }
2007 }
2008
2009
2010 if (CSI.empty())
2011 return true;
2012
2013 if (RVFI->useQCIInterrupt(MF)) {
2015 }
2016
2017 if (RVFI->isPushable(MF)) {
2018
2020
2021
2022
2023
2024 unsigned OnlyPushIfMoreThan = RVFI->useQCIInterrupt(MF) ? 2 : 0;
2025 if (PushedRegNum > OnlyPushIfMoreThan) {
2026 RVFI->setRVPushRegs(PushedRegNum);
2027 RVFI->setRVPushStackSize(alignTo((STI.getXLen() / 8) * PushedRegNum, 16));
2028 }
2029 }
2030
2031 for (auto &CS : CSI) {
2034 unsigned Size = RegInfo->getSpillSize(*RC);
2035
2036 if (RVFI->useQCIInterrupt(MF)) {
2038 return P.first == CS.getReg();
2039 });
2041 int64_t Offset = FFI->second * (int64_t)Size;
2042
2043 int FrameIdx = MFI.CreateFixedSpillStackObject(Size, Offset);
2044 assert(FrameIdx < 0);
2045 CS.setFrameIdx(FrameIdx);
2046 continue;
2047 }
2048 }
2049
2050 if (RVFI->useSaveRestoreLibCalls(MF) || RVFI->isPushable(MF)) {
2053 unsigned RegNum = std::distance(std::begin(FixedCSRFIMap), FII);
2054
2057 if (RVFI->getPushPopKind(MF) ==
2059 Offset = -int64_t(RVFI->getRVPushRegs() - RegNum) * Size;
2060 else
2061 Offset = -int64_t(RegNum + 1) * Size;
2062
2063 if (RVFI->useQCIInterrupt(MF))
2065
2066 int FrameIdx = MFI.CreateFixedSpillStackObject(Size, Offset);
2067 assert(FrameIdx < 0);
2068 CS.setFrameIdx(FrameIdx);
2069 continue;
2070 }
2071 }
2072
2073
2074 Align Alignment = RegInfo->getSpillAlign(*RC);
2075
2076
2077
2078 Alignment = std::min(Alignment, getStackAlign());
2079 int FrameIdx = MFI.CreateStackObject(Size, Alignment, true);
2080 MFI.setIsCalleeSavedObjectIndex(FrameIdx, true);
2081 CS.setFrameIdx(FrameIdx);
2084 }
2085
2086 if (RVFI->useQCIInterrupt(MF)) {
2087
2088
2089 MFI.CreateFixedSpillStackObject(
2091 }
2092
2093 if (RVFI->isPushable(MF)) {
2095
2096 if (int64_t PushSize = RVFI->getRVPushStackSize())
2097 MFI.CreateFixedSpillStackObject(PushSize, -PushSize - QCIOffset);
2098 } else if (int LibCallRegs = getLibCallID(MF, CSI) + 1) {
2099 int64_t LibCallFrameSize =
2101 MFI.CreateFixedSpillStackObject(LibCallFrameSize, -LibCallFrameSize);
2102 }
2103
2104 return true;
2105}
2106
2110 if (CSI.empty())
2111 return true;
2112
2116 if (MI != MBB.end() && ->isDebugInstr())
2118
2121
2126 ? RISCV::QC_C_MIENTER_NEST
2127 : RISCV::QC_C_MIENTER))
2129
2131 MBB.addLiveIn(Reg);
2132 }
2133
2135
2137 if (PushedRegNum > 0) {
2138
2145 PushBuilder.addImm(RegEnc);
2146 PushBuilder.addImm(0);
2147
2148 for (unsigned i = 0; i < PushedRegNum; i++)
2150 }
2152
2156
2157
2158 for (auto &CS : CSI)
2159 MBB.addLiveIn(CS.getReg());
2160 }
2161
2162
2165
2166 auto storeRegsToStackSlots = [&](decltype(UnmanagedCSI) CSInfo) {
2167 for (auto &CS : CSInfo) {
2168
2171 TII.storeRegToStackSlot(MBB, MI, Reg, .isLiveIn(Reg),
2172 CS.getFrameIdx(), RC, Register(),
2174 }
2175 };
2176 storeRegsToStackSlots(UnmanagedCSI);
2177 storeRegsToStackSlots(RVVCSI);
2178
2179 return true;
2180}
2181
2183 return RISCV::VRRegClass.contains(BaseReg) ? 1
2184 : RISCV::VRM2RegClass.contains(BaseReg) ? 2
2185 : RISCV::VRM4RegClass.contains(BaseReg) ? 4
2186 : 8;
2187}
2188
2189void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
2192 const MachineFrameInfo &MFI = MF->getFrameInfo();
2193 RISCVMachineFunctionInfo *RVFI = MF->getInfo();
2194 const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
2195
2197 if (RVVCSI.empty())
2198 return;
2199
2201 if (!HasFP) {
2202 uint64_t ScalarLocalVarSize =
2205 FixedSize -= ScalarLocalVarSize;
2206 }
2207
2209 for (auto &CS : RVVCSI) {
2210
2211 int FI = CS.getFrameIdx();
2214 for (unsigned i = 0; i < NumRegs; ++i) {
2217 }
2218 }
2219}
2220
2221void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
2224 const MachineFrameInfo &MFI = MF->getFrameInfo();
2225 const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
2226
2229 for (auto &CS : RVVCSI) {
2232 for (unsigned i = 0; i < NumRegs; ++i)
2233 CFIHelper.buildRestore(BaseReg + i);
2234 }
2235}
2236
2240 if (CSI.empty())
2241 return true;
2242
2246 if (MI != MBB.end() && ->isDebugInstr())
2248
2249
2250
2251
2252
2253
2254
2257
2258 auto loadRegFromStackSlot = [&](decltype(UnmanagedCSI) CSInfo) {
2259 for (auto &CS : CSInfo) {
2262 TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, Register(),
2265 "loadRegFromStackSlot didn't insert any code!");
2266 }
2267 };
2268 loadRegFromStackSlot(RVVCSI);
2269 loadRegFromStackSlot(UnmanagedCSI);
2270
2273
2274
2275 assert(MI->getOpcode() == RISCV::QC_C_MILEAVERET &&
2276 "Unexpected QCI Interrupt Return Instruction");
2277 }
2278
2281 if (PushedRegNum > 0) {
2287
2288 PopBuilder.addImm(RegEnc);
2289 PopBuilder.addImm(0);
2290
2291 for (unsigned i = 0; i < RVFI->getRVPushRegs(); i++)
2293 }
2294 } else {
2296 if (RestoreLibCall) {
2297
2302
2303
2304
2305 if (MI != MBB.end() && MI->getOpcode() == RISCV::PseudoRET) {
2306 NewMI->copyImplicitOps(*MF, *MI);
2307 MI->eraseFromParent();
2308 }
2309 }
2310 }
2311 return true;
2312}
2313
2315
2317 return false;
2318
2319 return true;
2320}
2321
2326
2327
2328
2329
2330
2331
2332
2333
2334 if (STI.preferVsetvliOverReadVLENB() &&
2335 (MBB.isLiveIn(RISCV::VTYPE) || MBB.isLiveIn(RISCV::VL)))
2336 return false;
2337
2339 return true;
2340
2341
2342
2343
2344
2346 RS.enterBasicBlock(*TmpMBB);
2347 return !RS.isRegUsed(RISCV::X5);
2348}
2349
2354
2355
2356
2358 return MBB.succ_empty();
2359
2361 return true;
2362
2363
2364
2365
2366
2367 if (MBB.succ_size() > 1)
2368 return false;
2369
2372
2373
2374
2375
2376 if (!SuccMBB)
2377 return true;
2378
2379
2380
2382}
2383
2385 switch (ID) {
2388 return true;
2393 return false;
2394 }
2396}
2397
2401
2402
2404 Register TargetReg, bool IsRVV) {
2405 assert(TargetReg != RISCV::X2 && "New top of stack cannot already be in SP");
2406
2409
2412 bool IsRV64 = Subtarget.is64Bit();
2413 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
2416
2420 MF.insert(MBBInsertPoint, LoopTestMBB);
2422 MF.insert(MBBInsertPoint, ExitMBB);
2424 Register ScratchReg = RISCV::X7;
2425
2426
2427 TII->movImm(MBB, MBBI, DL, ScratchReg, ProbeSize, Flags);
2428
2429
2430
2435
2436
2437 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL,
2438 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
2443
2444 if (IsRVV) {
2445
2446 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::SUB),
2447 TargetReg)
2451
2452
2453 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BGE))
2456 .addMBB(LoopTestMBB)
2458
2459 } else {
2460
2461 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BNE))
2464 .addMBB(LoopTestMBB)
2466 }
2467
2470
2473 MBB.addSuccessor(LoopTestMBB);
2474
2476}
2477
2478void RISCVFrameLowering::inlineStackProbe(MachineFunction &MF,
2480
2481
2482
2483 SmallVector<MachineInstr *, 4> ToReplace;
2484 for (MachineInstr &MI : MBB) {
2485 unsigned Opc = MI.getOpcode();
2486 if (Opc == RISCV::PROBED_STACKALLOC ||
2487 Opc == RISCV::PROBED_STACKALLOC_RVV) {
2489 }
2490 }
2491
2492 for (MachineInstr *MI : ToReplace) {
2493 if (MI->getOpcode() == RISCV::PROBED_STACKALLOC ||
2494 MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) {
2497 Register TargetReg = MI->getOperand(0).getReg();
2499 (MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV));
2501 }
2502 }
2503}
2504
2508
2511 return RISCV::X2;
2512}
unsigned const MachineRegisterInfo * MRI
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file contains constants used for implementing Dwarf debug support.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII, const MachineFunction &MF)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr uint64_t QCIInterruptPushAmount
Definition RISCVFrameLowering.cpp:72
static unsigned getPushOpcode(RISCVMachineFunctionInfo::PushPopKind Kind, bool UpdateFP)
Definition RISCVFrameLowering.cpp:890
static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
Definition RISCVFrameLowering.cpp:271
static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI, const Register &Reg)
Definition RISCVFrameLowering.cpp:1558
static void createSiFivePreemptibleInterruptFrameEntries(MachineFunction &MF, RISCVMachineFunctionInfo &RVFI)
Definition RISCVFrameLowering.cpp:251
static constexpr MCPhysReg FPReg
Definition RISCVFrameLowering.cpp:51
static const char * getRestoreLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:440
static bool needsDwarfCFI(const MachineFunction &MF)
Returns true if DWARF CFI instructions ("frame moves") should be emitted.
Definition RISCVFrameLowering.cpp:99
static constexpr MCPhysReg SPReg
Definition RISCVFrameLowering.cpp:54
static const char * getSpillLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:413
static bool hasRVVFrameObject(const MachineFunction &MF)
Definition RISCVFrameLowering.cpp:1742
static SmallVector< CalleeSavedInfo, 8 > getQCISavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:608
static void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
Definition RISCVFrameLowering.cpp:323
static SmallVector< CalleeSavedInfo, 8 > getRVVCalleeSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:566
static void appendScalableVectorExpression(const TargetRegisterInfo &TRI, SmallVectorImpl< char > &Expr, int FixedOffset, int ScalableOffset, llvm::raw_string_ostream &Comment)
Definition RISCVFrameLowering.cpp:672
static bool isPop(unsigned Opcode)
Definition RISCVFrameLowering.cpp:878
static unsigned getCalleeSavedRVVNumRegs(const Register &BaseReg)
Definition RISCVFrameLowering.cpp:2182
static void emitStackProbeInline(MachineBasicBlock::iterator MBBI, DebugLoc DL, Register TargetReg, bool IsRVV)
Definition RISCVFrameLowering.cpp:2403
static Align getABIStackAlignment(RISCVABI::ABI ABI)
Definition RISCVFrameLowering.cpp:35
static unsigned getPopOpcode(RISCVMachineFunctionInfo::PushPopKind Kind)
Definition RISCVFrameLowering.cpp:902
static SmallVector< CalleeSavedInfo, 8 > getPushOrLibCallsSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:581
static int getLibCallID(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:372
static const std::pair< MCPhysReg, int8_t > FixedCSRFIQCIInterruptMap[]
Definition RISCVFrameLowering.cpp:74
static bool isPush(unsigned Opcode)
Definition RISCVFrameLowering.cpp:867
static constexpr MCPhysReg RAReg
Definition RISCVFrameLowering.cpp:57
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
Definition RISCVFrameLowering.cpp:105
static const MCPhysReg FixedCSRFIMap[]
Definition RISCVFrameLowering.cpp:63
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
Definition RISCVFrameLowering.cpp:181
static SmallVector< CalleeSavedInfo, 8 > getUnmanagedCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:551
static void emitSiFiveCLICStackSwap(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL)
Definition RISCVFrameLowering.cpp:228
static unsigned getNumPushPopRegs(const std::vector< CalleeSavedInfo > &CSI)
Definition RISCVFrameLowering.cpp:465
static unsigned getScavSlotsNumForRVV(MachineFunction &MF)
Definition RISCVFrameLowering.cpp:1698
static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI, Register Reg, uint64_t FixedOffset, uint64_t ScalableOffset)
Definition RISCVFrameLowering.cpp:729
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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 buildEscape(StringRef Bytes, StringRef Comment="") const
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void buildRestore(MCRegister Reg) const
void buildDefCFARegister(MCRegister Reg) const
void buildOffset(MCRegister Reg, int64_t Offset) const
void insertCFIInst(const MCCFIInstruction &CFIInst) const
void buildDefCFA(MCRegister Reg, int64_t Offset) const
void setInsertPoint(MachineBasicBlock::iterator IP)
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
MCRegister getReg() const
Diagnostic information for unsupported feature in backend.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasOptNone() const
Do not optimize this function (-O0).
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.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
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.
constexpr unsigned id() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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 adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
LLVM_ABI void ensureMaxAlignment(Align Alignment)
Make sure the function is at least Align bytes aligned.
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...
void setObjectOffset(int ObjectIdx, int64_t SPOffset)
Set the stack frame offset of the specified object.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
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.
bool isMaxCallFrameSizeComputed() const
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
uint8_t getStackID(int ObjectIdx) const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
void setStackSize(uint64_t Size)
Set the size of the stack.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
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.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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 & 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 & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
Definition RISCVFrameLowering.cpp:1993
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
Definition RISCVFrameLowering.cpp:915
uint64_t getFirstSPAdjustAmount(const MachineFunction &MF) const
Definition RISCVFrameLowering.cpp:1926
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
Definition RISCVFrameLowering.cpp:2314
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 RISCVFrameLowering.cpp:2107
bool hasBP(const MachineFunction &MF) const
Definition RISCVFrameLowering.cpp:492
void allocateStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineFunction &MF, uint64_t Offset, uint64_t RealStackSize, bool EmitCFI, bool NeedProbe, uint64_t ProbeSize, bool DynAllocation, MachineInstr::MIFlag Flag) const
Definition RISCVFrameLowering.cpp:755
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
Definition RISCVFrameLowering.cpp:2350
bool hasFPImpl(const MachineFunction &MF) const override
Definition RISCVFrameLowering.cpp:483
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 RISCVFrameLowering.cpp:2237
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
Definition RISCVFrameLowering.cpp:1864
Register getInitialCFARegister(const MachineFunction &MF) const override
Return initial CFA register value i.e.
Definition RISCVFrameLowering.cpp:2510
const RISCVSubtarget & STI
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
Definition RISCVFrameLowering.cpp:1387
bool isSupportedStackID(TargetStackID::Value ID) const override
Definition RISCVFrameLowering.cpp:2384
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
Definition RISCVFrameLowering.cpp:1568
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
Definition RISCVFrameLowering.cpp:1213
TargetStackID::Value getStackIDForScalableVectors() const override
Returns the StackID that scalable vectors should be associated with.
Definition RISCVFrameLowering.cpp:2398
int getInitialCFAOffset(const MachineFunction &MF) const override
Return initial CFA offset value i.e.
Definition RISCVFrameLowering.cpp:2505
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
Definition RISCVFrameLowering.cpp:1799
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
Definition RISCVFrameLowering.cpp:1870
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
Definition RISCVFrameLowering.cpp:2322
RISCVFrameLowering(const RISCVSubtarget &STI)
Definition RISCVFrameLowering.cpp:43
uint64_t getStackSizeWithRVVPadding(const MachineFunction &MF) const
Definition RISCVFrameLowering.cpp:543
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
bool isPushable(const MachineFunction &MF) const
InterruptStackKind getInterruptStackKind(const MachineFunction &MF) const
bool isSiFivePreemptibleInterrupt(const MachineFunction &MF) const
void pushInterruptCSRFrameIndex(int FI)
PushPopKind getPushPopKind(const MachineFunction &MF) const
uint64_t getRVVPadding() const
unsigned getRVPushRegs() const
bool useSaveRestoreLibCalls(const MachineFunction &MF) const
unsigned getVarArgsSaveSize() const
bool useQCIInterrupt(const MachineFunction &MF) const
unsigned getCalleeSavedStackSize() const
bool hasVInstructions() const
const RISCVRegisterInfo * getRegisterInfo() const override
bool hasInlineStackProbe(const MachineFunction &MF) const override
True if stack clash protection is enabled for this functions.
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
Wrapper class representing virtual and physical registers.
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
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.
int64_t getScalable() const
Returns the scalable component of the stack.
static StackOffset get(int64_t Fixed, int64_t Scalable)
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
StringRef - Represent a constant reference to a string, i.e.
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...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
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.
TargetInstrInfo - Interface to description of machine instruction set.
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
static unsigned encodeRegListNumRegs(unsigned NumRegs)
static constexpr unsigned RVVBitsPerBlock
bool isRVVSpill(const MachineInstr &MI)
static constexpr unsigned RVVBytesPerBlock
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ ScalablePredicateVector
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
unsigned Log2(Align A)
Returns the log2 of the alignment.
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
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.
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 bool isRVVRegClass(const TargetRegisterClass *RC)
void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, Register SrcReg, StackOffset Offset, MachineInstr::MIFlag Flag, MaybeAlign RequiredAlign) const