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

64 RAReg, FPReg, RISCV::X9,

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() && (hasFP(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 && hasFP(MF), DynAllocation);

1125 } else {

1126

1127

1131 }

1132

1133 if (NeedsDwarfCFI && hasFP(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 (MBB.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 && hasFP(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 (MRI.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 (ST.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) {

1765 for (auto &MI : MBB) {

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

1911 return MBB.erase(MI);

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 (isInt<12>(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() && MI->isDebugInstr())

2117 DL = MI->getDebugLoc();

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, MBB.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() && MI->isDebugInstr())

2247 DL = MI->getDebugLoc();

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