LLVM: lib/Target/RISCV/RISCVFrameLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
26
27#include
28
29using namespace llvm;
30
31namespace {
32
33class CFISaveRegisterEmitter {
36
37public:
39 : MF{MF}, MFI{MF.getFrameInfo()} {};
40
48 nullptr, RI.getDwarfRegNum(Reg, true), Offset));
52 }
53};
54
55class CFIRestoreRegisterEmitter {
57
58public:
59 CFIRestoreRegisterEmitter(MachineFunction &MF) : MF{MF} {};
60
70 }
71};
72
73}
74
75template
76void RISCVFrameLowering::emitCFIForCSI(
83
85 for (const auto &CS : CSI)
87}
88
95}
96
100 0,
102 STI(STI) {}
103
104
106
107
109
110
112
113
114
116 { RAReg, -1}, { FPReg, -2},
117 { RISCV::X9, -3}, { RISCV::X18, -4},
118 { RISCV::X19, -5}, { RISCV::X20, -6},
119 { RISCV::X21, -7}, { RISCV::X22, -8},
120 { RISCV::X23, -9}, { RISCV::X24, -10},
121 { RISCV::X25, -11}, { RISCV::X26, -12},
122 { RISCV::X27, -13}};
123
124
125
131 STI.hasStdExtZicfiss();
132 bool HasSWShadowStack =
134 if (!HasHWShadowStack && !HasSWShadowStack)
135 return;
136
139
140
141
145 return;
146
148 if (HasHWShadowStack) {
150 return;
151 }
152
154
155 bool IsRV64 = STI.is64Bit();
156 int64_t SlotSize = STI.getXLen() / 8;
157
158
159
170
171
172
173 char DwarfSCSReg = TRI->getDwarfRegNum(SCSPReg, true);
174 assert(DwarfSCSReg < 32 && "SCS Register should be < 32 (X3).");
175
176 char Offset = static_cast<char>(-SlotSize) & 0x7f;
177 const char CFIInst[] = {
178 dwarf::DW_CFA_val_expression,
179 DwarfSCSReg,
180 2,
181 static_cast<char>(unsigned(dwarf::DW_OP_breg0 + DwarfSCSReg)),
182 Offset,
183 };
184
186 nullptr, StringRef(CFIInst, sizeof(CFIInst))));
190}
191
197 STI.hasStdExtZicfiss();
198 bool HasSWShadowStack =
200 if (!HasHWShadowStack && !HasSWShadowStack)
201 return;
202
203 Register RAReg = STI.getRegisterInfo()->getRARegister();
204
205
209 return;
210
212 if (HasHWShadowStack) {
214 return;
215 }
216
218
219 bool IsRV64 = STI.is64Bit();
220 int64_t SlotSize = STI.getXLen() / 8;
221
222
223
234
236 nullptr, STI.getRegisterInfo()->getDwarfRegNum(SCSPReg, true)));
240}
241
242
243
244
245
247 const std::vector &CSI) {
249
250 if (CSI.empty() || !RVFI->useSaveRestoreLibCalls(MF))
251 return -1;
252
253 Register MaxReg = RISCV::NoRegister;
254 for (auto &CS : CSI)
255
256
258 MaxReg = std::max(MaxReg.id(), CS.getReg().id());
259
260 if (MaxReg == RISCV::NoRegister)
261 return -1;
262
263 switch (MaxReg) {
264 default:
266
267 case RISCV::X27: return 12;
268 case RISCV::X26: return 11;
269 case RISCV::X25: return 10;
270 case RISCV::X24: return 9;
271 case RISCV::X23: return 8;
272 case RISCV::X22: return 7;
273 case RISCV::X21: return 6;
274 case RISCV::X20: return 5;
275 case RISCV::X19: return 4;
276 case RISCV::X18: return 3;
277 case RISCV::X9: return 2;
278 case FPReg: return 1;
279 case RAReg: return 0;
280
281 }
282}
283
284
285
286static const char *
288 const std::vector &CSI) {
289 static const char *const SpillLibCalls[] = {
290 "__riscv_save_0",
291 "__riscv_save_1",
292 "__riscv_save_2",
293 "__riscv_save_3",
294 "__riscv_save_4",
295 "__riscv_save_5",
296 "__riscv_save_6",
297 "__riscv_save_7",
298 "__riscv_save_8",
299 "__riscv_save_9",
300 "__riscv_save_10",
301 "__riscv_save_11",
302 "__riscv_save_12"
303 };
304
306 if (LibCallID == -1)
307 return nullptr;
308 return SpillLibCalls[LibCallID];
309}
310
311
312
313static const char *
315 const std::vector &CSI) {
316 static const char *const RestoreLibCalls[] = {
317 "__riscv_restore_0",
318 "__riscv_restore_1",
319 "__riscv_restore_2",
320 "__riscv_restore_3",
321 "__riscv_restore_4",
322 "__riscv_restore_5",
323 "__riscv_restore_6",
324 "__riscv_restore_7",
325 "__riscv_restore_8",
326 "__riscv_restore_9",
327 "__riscv_restore_10",
328 "__riscv_restore_11",
329 "__riscv_restore_12"
330 };
331
333 if (LibCallID == -1)
334 return nullptr;
335 return RestoreLibCalls[LibCallID];
336}
337
338
339
340static std::pair<unsigned, unsigned>
342 switch (MaxReg) {
343 default:
345 case RISCV::X27:
347 case RISCV::X25:
349 case RISCV::X24:
351 case RISCV::X23:
353 case RISCV::X22:
355 case RISCV::X21:
357 case RISCV::X20:
359 case RISCV::X19:
361 case RISCV::X18:
363 case RISCV::X9:
365 case FPReg:
367 case RAReg:
369 }
370}
371
372
374 const std::vector &CSI) {
375 Register MaxPushPopReg = RISCV::NoRegister;
376 for (auto &CS : CSI) {
378 return P.first == CS.getReg();
380 MaxPushPopReg = std::max(MaxPushPopReg.id(), CS.getReg().id());
381 }
382 assert(MaxPushPopReg != RISCV::X26 && "x26 requires x27 to also be pushed");
383 return MaxPushPopReg;
384}
385
386
387
388
389
392
397}
398
402
403
404
405
406
410 TRI->hasStackRealignment(MF);
411}
412
413
414void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const {
417
418
420
421
423
424
425 FrameSize = alignTo(FrameSize, StackAlign);
426
427
429
430
431
432
433
435 if (RVFI->getRVVStackSize() && ((MF) || TRI->hasStackRealignment(MF))) {
436 int ScalarLocalVarSize = FrameSize - RVFI->getCalleeSavedStackSize() -
437 RVFI->getVarArgsSaveSize();
438 if (auto RVVPadding =
440 RVFI->setRVVPadding(RVVPadding);
441 }
442}
443
444
445
451}
452
455 const std::vector &CSI) {
458
459 for (auto &CS : CSI) {
463 }
464
465 return NonLibcallCSI;
466}
467
470 const std::vector &CSI) {
473
474 for (auto &CS : CSI) {
478 }
479
480 return RVVCSI;
481}
482
485 const std::vector &CSI) {
487
489 if (!RVFI->useSaveRestoreLibCalls(MF) && !RVFI->isPushable(MF))
490 return PushOrLibCallsCSI;
491
492 for (const auto &CS : CSI) {
496 PushOrLibCallsCSI.push_back(CS);
497 }
498
499 return PushOrLibCallsCSI;
500}
501
502void RISCVFrameLowering::allocateAndProbeStackForRVV(
506 assert(Amount != 0 && "Did not need to adjust stack pointer for RVV.");
507
508
509
510
512 Register TargetReg = RISCV::X6;
516 TII->mulImm(MF, MBB, MBBI, DL, TargetReg, NumOfVReg, Flag);
517
518 if (EmitCFI) {
519
521 unsigned CFIIndex =
526 }
527
528
532
533 if (EmitCFI) {
534
536 unsigned CFIIndex =
541 }
542
543
548
549
550 if (DynAllocation) {
556 }
557}
558
561 int FixedOffset, int ScalableOffset,
563 unsigned DwarfVLenB = TRI.getDwarfRegNum(RISCV::VLENB, true);
565 if (FixedOffset) {
566 Expr.push_back(dwarf::DW_OP_consts);
569 Comment << (FixedOffset < 0 ? " - " : " + ") << std::abs(FixedOffset);
570 }
571
574
578
581
582 Comment << (ScalableOffset < 0 ? " - " : " + ") << std::abs(ScalableOffset)
583 << " * vlenb";
584}
585
590 assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
592 std::string CommentBuffer;
594
595 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
598 if (Reg == SPReg)
599 Comment << "sp";
600 else
602
604 Comment);
605
608 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
611
613 Comment.str());
614}
615
619 assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
621 std::string CommentBuffer;
623 Comment << printReg(Reg, &TRI) << " @ cfa";
624
625
627 Comment);
628
631 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
632 DefCfaExpr.push_back(dwarf::DW_CFA_expression);
636
638 Comment.str());
639}
640
641
645 uint64_t RealStackSize, bool EmitCFI,
646 bool NeedProbe, uint64_t ProbeSize,
647 bool DynAllocation) const {
652
653
654 if (!NeedProbe || Offset <= ProbeSize) {
657
658 if (EmitCFI) {
659
665 }
666
667 if (NeedProbe && DynAllocation) {
668
674 }
675
676 return;
677 }
678
679
680 if (Offset < ProbeSize * 5) {
682 while (CurrentOffset + ProbeSize <= Offset) {
686
692
693 CurrentOffset += ProbeSize;
694 if (EmitCFI) {
695
701 }
702 }
703
705 if (Residual) {
709 if (EmitCFI) {
710
711 unsigned CFIIndex =
716 }
717
718 if (DynAllocation) {
719
725 }
726 }
727
728 return;
729 }
730
731
734
735 Register TargetReg = RISCV::X6;
736
740
741 if (EmitCFI) {
742
743 unsigned Reg = STI.getRegisterInfo()->getDwarfRegNum(TargetReg, true);
744 unsigned CFIIndex =
749 }
750
751
755
756 if (EmitCFI) {
757
759 unsigned CFIIndex =
764 }
765
766 if (Residual) {
769 if (DynAllocation) {
770
776 }
777 }
778
779 if (EmitCFI) {
780
781 unsigned CFIIndex =
786 }
787}
788
796
798
799
800
802
803
804
806 return;
807
808
810
811 auto FirstFrameSetup = MBBI;
812
813
814
817
818
819 determineFrameLayout(MF);
820
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
842
843
844
845 unsigned LibCallFrameSize =
847 RVFI->setLibCallStackSize(LibCallFrameSize);
848
854
857 }
858
859
860
862 uint64_t StackSize = RealStackSize - RVFI->getReservedSpillsSize();
863 uint64_t RVVStackSize = RVFI->getRVVStackSize();
864
865
866 if (RealStackSize == 0 && !MFI.adjustsStack() && RVVStackSize == 0)
867 return;
868
869
870
873 MF.getFunction(), "Stack pointer required, but has been reserved."});
874
876
877 if (FirstSPAdjustAmount) {
878 StackSize = FirstSPAdjustAmount;
879 RealStackSize = FirstSPAdjustAmount;
880 }
881
882 if (RVFI->isPushable(MF) && FirstFrameSetup != MBB.end() &&
883 FirstFrameSetup->getOpcode() == RISCV::CM_PUSH) {
884
885
886
887
890 FirstFrameSetup->getOperand(1).setImm(Spimm);
891 StackSize -= Spimm;
892
898
901 }
902
903
908 bool DynAllocation =
910 if (StackSize != 0)
912 NeedProbe, ProbeSize, DynAllocation);
913
914
915
916
917
918
919
921
922
923
925
926
930 MF.getFunction(), "Frame pointer required, but has been reserved."});
931
933
937
938
940 nullptr, RI->getDwarfRegNum(FPReg, true), RVFI->getVarArgsSaveSize()));
944 }
945
946 uint64_t SecondSPAdjustAmount = 0;
947
948 if (FirstSPAdjustAmount) {
950 assert(SecondSPAdjustAmount > 0 &&
951 "SecondSPAdjustAmount should be greater than zero");
952
955 ProbeSize, DynAllocation);
956 }
957
958 if (RVVStackSize) {
959 if (NeedProbe) {
960 allocateAndProbeStackForRVV(MF, MBB, MBBI, DL, RVVStackSize,
962 DynAllocation);
963 } else {
964
965
969 }
970
971 if ((MF)) {
972
978 }
979
981 emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
982 }
983
985
987 if (RI->hasStackRealignment(MF)) {
989
991 if (isInt<12>(-(int)MaxAlignment.value())) {
996 } else {
997 unsigned ShiftAmount = Log2(MaxAlignment);
1002 .addImm(ShiftAmount)
1006 .addImm(ShiftAmount)
1008 }
1009 if (NeedProbe && RVVStackSize == 0) {
1010
1011
1012 if (SecondSPAdjustAmount < ProbeSize &&
1013 SecondSPAdjustAmount + MaxAlignment.value() >= ProbeSize) {
1020 }
1021 }
1022
1023
1024
1025 if (hasBP(MF)) {
1026
1031 }
1032 }
1033 }
1034}
1035
1036void RISCVFrameLowering::deallocateStack(MachineFunction &MF,
1041 int64_t CFAOffset) const {
1044
1047 StackSize = 0;
1048
1049 unsigned CFIIndex =
1054}
1055
1062
1063
1064
1066 return;
1067
1068
1069
1075 DL = MBBI->getDebugLoc();
1076
1078
1079
1080
1084 }
1085
1087
1088
1089
1090
1092
1094 uint64_t RealStackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1096 uint64_t StackSize = FirstSPAdjustAmount ? FirstSPAdjustAmount
1098 RVFI->getReservedSpillsSize();
1099 uint64_t FPOffset = RealStackSize - RVFI->getVarArgsSaveSize();
1100 uint64_t RVVStackSize = RVFI->getRVVStackSize();
1101
1102 bool RestoreSPFromFP = RI->hasStackRealignment(MF) ||
1104 if (RVVStackSize) {
1105
1106
1107 if (!RestoreSPFromFP)
1111
1112 if ((MF)) {
1114 nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
1116 TII->get(TargetOpcode::CFI_INSTRUCTION))
1119 }
1120
1121 emitCalleeSavedRVVEpilogCFI(MBB, LastFrameDestroy);
1122 }
1123
1124 if (FirstSPAdjustAmount) {
1125 uint64_t SecondSPAdjustAmount =
1127 assert(SecondSPAdjustAmount > 0 &&
1128 "SecondSPAdjustAmount should be greater than zero");
1129
1130
1131
1132 if (!RestoreSPFromFP)
1136
1137 if ((MF)) {
1141 TII->get(TargetOpcode::CFI_INSTRUCTION))
1144 }
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 if (RestoreSPFromFP) {
1158 assert(hasFP(MF) && "frame pointer should not have been eliminated");
1162 }
1163
1164 if (hasFP(MF)) {
1166 nullptr, RI->getDwarfRegNum(SPReg, true), RealStackSize));
1167 BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
1170 }
1171
1173
1174
1175
1176 if (StackSize != 0)
1177 deallocateStack(MF, MBB, MBBI, DL, StackSize,
1178 RVFI->getLibCallStackSize());
1179
1180
1182 return;
1183 }
1184
1185
1187
1188 bool ApplyPop = RVFI->isPushable(MF) && MBBI != MBB.end() &&
1189 MBBI->getOpcode() == RISCV::CM_POP;
1190 if (ApplyPop) {
1191
1192
1193
1194
1197 MBBI->getOperand(1).setImm(Spimm);
1198 StackSize -= Spimm;
1199
1200 if (StackSize != 0)
1201 deallocateStack(MF, MBB, MBBI, DL, StackSize,
1202 RealStackSize - StackSize);
1203
1205 if (NextI == MBB.end() || NextI->getOpcode() != RISCV::PseudoRET) {
1207
1208 emitCFIForCSI(
1210
1211
1212
1213 unsigned CFIIndex =
1218 }
1219 }
1220
1221
1222 if (StackSize != 0)
1223 deallocateStack(MF, MBB, MBBI, DL, StackSize, 0);
1224
1225
1227}
1228
1235
1236
1237
1238
1240 int MinCSFI = 0;
1241 int MaxCSFI = -1;
1244
1247 "Unexpected stack ID for the frame object.");
1254 }
1255
1257
1258 if (CSI.size()) {
1259 MinCSFI = CSI[0].getFrameIdx();
1260 MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
1261 }
1262
1263 if (FI >= MinCSFI && FI <= MaxCSFI) {
1264 FrameReg = SPReg;
1265
1266 if (FirstSPAdjustAmount)
1268 else
1271 }
1272
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306 if (hasBP(MF)) {
1308 } else {
1309
1311 FrameReg = SPReg;
1312 }
1313 } else {
1315 }
1316
1317 if (FrameReg == FPReg) {
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1336 "Can't index across variable sized realign");
1337
1338
1339
1341 "Inconsistent stack layout");
1343 }
1345 }
1346
1347
1348
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1384 "Can't index across variable sized realign");
1386 RVFI->getRVVStackSize());
1387 } else {
1389 }
1391
1392
1393 int ScalarLocalVarSize = MFI.getStackSize() -
1394 RVFI->getCalleeSavedStackSize() -
1395 RVFI->getVarArgsSaveSize() + RVFI->getRVVPadding();
1397 }
1399}
1400
1405
1406
1407 if (hasFP(MF)) {
1410 }
1411
1414
1415
1417 if (RVFI->isPushable(MF) && SavedRegs.test(RISCV::X26))
1418 SavedRegs.set(RISCV::X27);
1419}
1420
1421std::pair<int64_t, Align>
1422RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFunction &MF) const {
1424
1426 auto pushRVVObjects = [&](int FIBegin, int FIEnd) {
1427 for (int I = FIBegin, E = FIEnd; I != E; ++I) {
1430 continue;
1432 continue;
1433
1435 }
1436 };
1437
1440 if (!RVVCSI.empty())
1441 pushRVVObjects(RVVCSI[0].getFrameIdx(),
1442 RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1);
1444
1445
1446 Align RVVStackAlign(16);
1448
1449 if (.hasVInstructions()) {
1451 "Can't allocate scalable-vector objects without V instructions");
1452 return std::make_pair(0, RVVStackAlign);
1453 }
1454
1455
1457 for (int FI : ObjectsToAllocate) {
1458
1460 auto ObjectAlign =
1462
1463
1468
1469 RVVStackAlign = std::max(RVVStackAlign, ObjectAlign);
1470 }
1471
1473
1474
1475
1476
1477
1478
1479
1480 auto VScale =
1482 if (auto RVVStackAlignVScale = RVVStackAlign.value() / VScale) {
1483 if (auto AlignmentPadding =
1485 StackSize += AlignmentPadding;
1486 for (int FI : ObjectsToAllocate)
1488 }
1489 }
1490
1491 return std::make_pair(StackSize, RVVStackAlign);
1492}
1493
1495
1496
1497 static constexpr unsigned ScavSlotsNumRVVSpillScalableObject = 2;
1498
1499
1500
1501 static constexpr unsigned ScavSlotsNumRVVSpillNonScalableObject = 1;
1502
1503
1504
1505 static constexpr unsigned ScavSlotsADDIScalableObject = 1;
1506
1507 static constexpr unsigned MaxScavSlotsNumKnown =
1508 std::max({ScavSlotsADDIScalableObject, ScavSlotsNumRVVSpillScalableObject,
1509 ScavSlotsNumRVVSpillNonScalableObject});
1510
1511 unsigned MaxScavSlotsNum = 0;
1513 return false;
1517 for (auto &MO : MI.operands()) {
1518 if (!MO.isFI())
1519 continue;
1522 if (IsRVVSpill) {
1523 MaxScavSlotsNum = std::max(
1524 MaxScavSlotsNum, IsScalableVectorID
1525 ? ScavSlotsNumRVVSpillScalableObject
1526 : ScavSlotsNumRVVSpillNonScalableObject);
1527 } else if (MI.getOpcode() == RISCV::ADDI && IsScalableVectorID) {
1528 MaxScavSlotsNum =
1529 std::max(MaxScavSlotsNum, ScavSlotsADDIScalableObject);
1530 }
1531 }
1532 if (MaxScavSlotsNum == MaxScavSlotsNumKnown)
1533 return MaxScavSlotsNumKnown;
1534 }
1535 return MaxScavSlotsNum;
1536}
1537
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1555}
1556
1559 unsigned FnSize = 0;
1560 for (auto &MBB : MF) {
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579 if (MI.isConditionalBranch())
1580 FnSize += TII.getInstSizeInBytes(MI);
1581 if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) {
1583 FnSize += 2 + 8 + 2 + 2;
1584 else
1585 FnSize += 4 + 8 + 4 + 4;
1586 continue;
1587 }
1588
1589 FnSize += TII.getInstSizeInBytes(MI);
1590 }
1591 }
1592 return FnSize;
1593}
1594
1603
1604 int64_t RVVStackSize;
1605 Align RVVStackAlign;
1606 std::tie(RVVStackSize, RVVStackAlign) = assignRVVStackObjectOffsets(MF);
1607
1608 RVFI->setRVVStackSize(RVVStackSize);
1609 RVFI->setRVVStackAlign(RVVStackAlign);
1610
1612
1613
1614
1616 }
1617
1618 unsigned ScavSlotsNum = 0;
1619
1620
1621
1622
1624 ScavSlotsNum = 1;
1625
1626
1628 if (IsLargeFunction)
1629 ScavSlotsNum = std::max(ScavSlotsNum, 1u);
1630
1631
1632
1633
1635
1636 for (unsigned I = 0; I < ScavSlotsNum; I++) {
1638 RegInfo->getSpillAlign(*RC));
1640
1641 if (IsLargeFunction && RVFI->getBranchRelaxationScratchFrameIndex() == -1)
1642 RVFI->setBranchRelaxationScratchFrameIndex(FI);
1643 }
1644
1645 unsigned Size = RVFI->getReservedSpillsSize();
1647 int FrameIdx = Info.getFrameIdx();
1649 continue;
1650
1652 }
1653 RVFI->setCalleeSavedStackSize(Size);
1654}
1655
1656
1657
1658
1659
1663}
1664
1665
1670
1672
1673
1674
1675
1676
1677 int64_t Amount = MI->getOperand(0).getImm();
1678
1679 if (Amount != 0) {
1680
1682
1683 if (MI->getOpcode() == RISCV::ADJCALLSTACKDOWN)
1684 Amount = -Amount;
1685
1689 }
1690 }
1691
1693}
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1712
1713
1714
1715
1716 if (RVFI->getReservedSpillsSize())
1717 return 0;
1718
1719
1720
1721 if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
1722
1723
1724
1725
1726
1727
1729
1730
1731
1732
1733
1735
1736
1737
1738
1739
1740
1741
1742
1743
1745
1746
1747
1748
1749
1750
1751 auto CanCompress = [&](uint64_t CompressLen) -> bool {
1752 if (StackSize <= 2047 + CompressLen ||
1753 (StackSize > 2048 * 2 - StackAlign &&
1754 StackSize <= 2047 * 2 + CompressLen) ||
1755 StackSize > 2048 * 3 - StackAlign)
1756 return true;
1757
1758 return false;
1759 };
1760
1761
1762
1763 const uint64_t ADDI16SPCompressLen = 496;
1764 if (STI.is64Bit() && CanCompress(ADDI16SPCompressLen))
1765 return ADDI16SPCompressLen;
1766 if (CanCompress(RVCompressLen))
1767 return RVCompressLen;
1768 }
1769 return 2048 - StackAlign;
1770 }
1771 return 0;
1772}
1773
1776 std::vector &CSI, unsigned &MinCSFrameIndex,
1777 unsigned &MaxCSFrameIndex) const {
1778
1779 if (CSI.empty())
1780 return true;
1781
1783
1784 if (RVFI->isPushable(MF)) {
1785
1787 if (MaxReg != RISCV::NoRegister) {
1789 RVFI->setRVPushRegs(PushedRegNum);
1790 RVFI->setRVPushStackSize(alignTo((STI.getXLen() / 8) * PushedRegNum, 16));
1791
1792
1793 RVFI->setRVPushRlist(RegEnc);
1794 }
1795 }
1796
1799
1800 for (auto &CS : CSI) {
1801 unsigned Reg = CS.getReg();
1804
1805
1806 if (RVFI->useSaveRestoreLibCalls(MF) || RVFI->isPushable(MF)) {
1811 if (RVFI->isPushable(MF))
1812 Offset = -((FII->second + RVFI->getRVPushRegs() + 1) * (int64_t)Size);
1813 else
1814 Offset = FII->second * (int64_t)Size;
1815
1817 assert(FrameIdx < 0);
1819 continue;
1820 }
1821 }
1822
1823
1825
1826
1827
1828 Alignment = std::min(Alignment, getStackAlign());
1830 if ((unsigned)FrameIdx < MinCSFrameIndex)
1831 MinCSFrameIndex = FrameIdx;
1832 if ((unsigned)FrameIdx > MaxCSFrameIndex)
1833 MaxCSFrameIndex = FrameIdx;
1837 }
1838
1839
1840 if (RVFI->isPushable(MF)) {
1841 if (int64_t PushSize = RVFI->getRVPushStackSize())
1843 } else if (int LibCallRegs = getLibCallID(MF, CSI) + 1) {
1844 int64_t LibCallFrameSize =
1847 }
1848
1849 return true;
1850}
1851
1855 if (CSI.empty())
1856 return true;
1857
1861 if (MI != MBB.end() && ->isDebugInstr())
1863
1864
1868 if (PushedRegNum > 0) {
1869
1874 PushBuilder.addImm((int64_t)RegEnc);
1875 PushBuilder.addImm(0);
1876
1877 for (unsigned i = 0; i < PushedRegNum; i++)
1879 }
1881
1885
1886
1887 for (auto &CS : CSI)
1889 }
1890
1891
1894
1895 auto storeRegsToStackSlots = [&](decltype(UnmanagedCSI) CSInfo) {
1896 for (auto &CS : CSInfo) {
1897
1902 }
1903 };
1904 storeRegsToStackSlots(UnmanagedCSI);
1905 storeRegsToStackSlots(RVVCSI);
1906
1907 return true;
1908}
1909
1911 return RISCV::VRRegClass.contains(BaseReg) ? 1
1912 : RISCV::VRM2RegClass.contains(BaseReg) ? 2
1913 : RISCV::VRM4RegClass.contains(BaseReg) ? 4
1914 : 8;
1915}
1916
1919 MCRegister BaseReg = TRI.getSubReg(Reg, RISCV::sub_vrm1_0);
1920
1921
1922 if (BaseReg == RISCV::NoRegister)
1923 BaseReg = Reg;
1924 return BaseReg;
1925}
1926
1927void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
1935
1937 if (RVVCSI.empty())
1938 return;
1939
1941 if (!HasFP) {
1942 uint64_t ScalarLocalVarSize =
1945 FixedSize -= ScalarLocalVarSize;
1946 }
1947
1948 for (auto &CS : RVVCSI) {
1949
1953 for (unsigned i = 0; i < NumRegs; ++i) {
1959 }
1960 }
1961}
1962
1963void RISCVFrameLowering::emitCalleeSavedRVVEpilogCFI(
1971
1973 for (auto &CS : RVVCSI) {
1976 for (unsigned i = 0; i < NumRegs; ++i) {
1978 nullptr, RI->getDwarfRegNum(BaseReg + i, true)));
1982 }
1983 }
1984}
1985
1989 if (CSI.empty())
1990 return true;
1991
1995 if (MI != MBB.end() && ->isDebugInstr())
1997
1998
1999
2000
2001
2002
2003
2006
2007 auto loadRegFromStackSlot = [&](decltype(UnmanagedCSI) CSInfo) {
2008 for (auto &CS : CSInfo) {
2014 "loadRegFromStackSlot didn't insert any code!");
2015 }
2016 };
2017 loadRegFromStackSlot(RVVCSI);
2018 loadRegFromStackSlot(UnmanagedCSI);
2019
2027
2028 PopBuilder.addImm(RegEnc);
2029 PopBuilder.addImm(0);
2030
2031 for (unsigned i = 0; i < RVFI->getRVPushRegs(); i++)
2033 }
2034 } else {
2036 if (RestoreLibCall) {
2037
2042
2043
2044
2045 if (MI != MBB.end() && MI->getOpcode() == RISCV::PseudoRET) {
2046 NewMI->copyImplicitOps(*MF, *MI);
2047 MI->eraseFromParent();
2048 }
2049 }
2050 }
2051 return true;
2052}
2053
2055
2057 return false;
2058
2059 return true;
2060}
2061
2066
2068 return true;
2069
2070
2071
2072
2073
2076 return !RS.isRegUsed(RISCV::X5);
2077}
2078
2083
2085 return true;
2086
2087
2088
2089
2090
2092 return false;
2093
2096
2097
2098
2099
2100 if (!SuccMBB)
2101 return true;
2102
2103
2104
2106}
2107
2109 switch (ID) {
2112 return true;
2116 return false;
2117 }
2119}
2120
2123}
2124
2125
2128 Register TargetReg, bool IsRVV) {
2129 assert(TargetReg != RISCV::X2 && "New top of stack cannot already be in SP");
2130
2133 bool IsRV64 = Subtarget.is64Bit();
2134 Align StackAlign = Subtarget.getFrameLowering()->getStackAlign();
2137
2141 MF.insert(MBBInsertPoint, LoopTestMBB);
2143 MF.insert(MBBInsertPoint, ExitMBB);
2145 Register ScratchReg = RISCV::X7;
2146
2147
2148 TII->movImm(MBB, MBBI, DL, ScratchReg, ProbeSize, Flags);
2149
2150
2151
2156
2157
2158 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL,
2159 TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
2164
2165 if (IsRVV) {
2166
2167 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::SUB),
2168 TargetReg)
2172
2173
2174 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BGE))
2177 .addMBB(LoopTestMBB)
2179
2180 } else {
2181
2182 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(RISCV::BNE))
2185 .addMBB(LoopTestMBB)
2187 }
2188
2191
2195
2197}
2198
2199void RISCVFrameLowering::inlineStackProbe(MachineFunction &MF,
2201
2202
2203
2206 unsigned Opc = MI.getOpcode();
2207 if (Opc == RISCV::PROBED_STACKALLOC ||
2208 Opc == RISCV::PROBED_STACKALLOC_RVV) {
2210 }
2211 }
2212
2214 if (MI->getOpcode() == RISCV::PROBED_STACKALLOC ||
2215 MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV) {
2218 Register TargetReg = MI->getOperand(1).getReg();
2220 (MI->getOpcode() == RISCV::PROBED_STACKALLOC_RVV));
2222 }
2223 }
2224}
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Analysis containing CSE Info
dxil DXContainer Global Emitter
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
static uint64_t estimateFunctionSizeInBytes(const LoongArchInstrInfo *TII, const MachineFunction &MF)
unsigned const TargetRegisterInfo * TRI
static constexpr Register SPReg
static constexpr Register FPReg
static MCRegister getRVVBaseRegister(const RISCVRegisterInfo &TRI, const Register &Reg)
static void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, Register TargetReg, bool IsRVV)
static const char * getRestoreLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static const char * getSpillLibCallName(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static bool hasRVVFrameObject(const MachineFunction &MF)
static std::pair< unsigned, unsigned > getPushPopEncodingAndNum(const Register MaxReg)
static const std::pair< MCPhysReg, int8_t > FixedCSRFIMap[]
static SmallVector< CalleeSavedInfo, 8 > getRVVCalleeSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static void appendScalableVectorExpression(const TargetRegisterInfo &TRI, SmallVectorImpl< char > &Expr, int FixedOffset, int ScalableOffset, llvm::raw_string_ostream &Comment)
static unsigned getCalleeSavedRVVNumRegs(const Register &BaseReg)
static Align getABIStackAlignment(RISCVABI::ABI ABI)
static SmallVector< CalleeSavedInfo, 8 > getPushOrLibCallsSavedInfo(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static int getLibCallID(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static constexpr Register RAReg
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL)
static SmallVector< CalleeSavedInfo, 8 > getUnmanagedCSI(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static Register getMaxPushPopReg(const MachineFunction &MF, const std::vector< CalleeSavedInfo > &CSI)
static unsigned getScavSlotsNumForRVV(MachineFunction &MF)
static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI, Register Reg, uint64_t FixedOffset, uint64_t ScalableOffset)
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
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.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
Load the specified register of the given register class from the specified stack frame index.
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_restore says that the rule for Register is now the same as it was at the beginning of the functi...
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
Wrapper class representing physical registers. Should be passed by value.
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
MachineBasicBlock * getFallThrough(bool JumpToFallThrough=true)
Return the fallthrough block if the block can implicitly transfer control to the block after it by fa...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
succ_iterator succ_begin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
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.
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.
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.
int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
uint64_t estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
void setStackID(int ObjectIdx, uint8_t ID)
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.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
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.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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 & addCFIIndex(unsigned CFIIndex) 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.
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
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...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
uint64_t getFirstSPAdjustAmount(const MachineFunction &MF) const
bool enableShrinkWrapping(const MachineFunction &MF) const override
Returns true if the target will correctly handle shrink wrapping.
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...
bool hasBP(const MachineFunction &MF) const
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a epilogue for the target.
bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI, unsigned &MinCSFrameIndex, unsigned &MaxCSFrameIndex) const override
assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.
bool hasFPImpl(const MachineFunction &MF) const override
void allocateStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineFunction &MF, uint64_t Offset, uint64_t RealStackSize, bool EmitCFI, bool NeedProbe, uint64_t ProbeSize, bool DynAllocation) const
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...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
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...
bool isSupportedStackID(TargetStackID::Value ID) const override
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
TargetStackID::Value getStackIDForScalableVectors() const override
Returns the StackID that scalable vectors should be associated with.
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
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...
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override
Check whether or not the given MBB can be used as a prologue for the target.
RISCVFrameLowering(const RISCVSubtarget &STI)
uint64_t getStackSizeWithRVVPadding(const MachineFunction &MF) const
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
bool isPushable(const MachineFunction &MF) const
int getRVPushRlist() const
uint64_t getRVVPadding() const
unsigned getRVPushRegs() const
bool useSaveRestoreLibCalls(const MachineFunction &MF) const
unsigned getVarArgsSaveSize() const
unsigned getCalleeSavedStackSize() const
bool hasStdExtCOrZca() const
bool hasVInstructions() const
bool isRegisterReservedByUser(Register i) const override
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() 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
bool isRegUsed(Register Reg, bool includeReserved=true) const
Return if a specific register is currently used.
void enterBasicBlock(MachineBasicBlock &MBB)
Start tracking liveness from the begin of basic block MBB.
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
constexpr unsigned id() const
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)
StringRef - Represent a constant reference to a string, i.e.
Information about stack frame layout on the target.
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...
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.
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...
const TargetRegisterClass * getMinimalPhysRegClass(MCRegister Reg, MVT VT=MVT::Other) const
Returns the Register Class of a physical register of the given type, picking the most sub register cl...
Align getSpillAlign(const TargetRegisterClass &RC) const
Return the minimum required alignment in bytes for a spill slot for a register of this class.
bool hasStackRealignment(const MachineFunction &MF) const
True if stack realignment is required and still possible.
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
self_iterator getIterator()
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
static constexpr unsigned RVVBitsPerBlock
bool isRVVSpill(const MachineInstr &MI)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
Reg
All possible values of the reg field in the ModR/M byte.
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.
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 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.
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...
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.
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.
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.
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