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() && (hasFP(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

855 emitCFIForCSI(MBB, MBBI,

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

899 emitCFIForCSI(MBB, MBBI,

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 (hasFP(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 (hasFP(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 (hasFP(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 (ST.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) {

1561 for (auto &MI : MBB) {

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

1862 DL = MI->getDebugLoc();

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

1996 DL = MI->getDebugLoc();

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