LLVM: lib/Target/ARM/ARMFrameLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

152#include

153#include

154#include

155#include

156#include

157#include

158#include

159

160#define DEBUG_TYPE "arm-frame-lowering"

161

162using namespace llvm;

163

166 cl::desc("Align ARM NEON spills in prolog and epilog"));

167

170 unsigned NumAlignedDPRCS2Regs);

171

181

182

185 unsigned NumAlignedDPRCS2Regs,

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212 switch (Reg) {

213 default:

216 break;

217

218 case ARM::FPCXTNS:

220

221 case ARM::FPSCR:

222 case ARM::FPEXC:

224

225 case ARM::R0:

226 case ARM::R1:

227 case ARM::R2:

228 case ARM::R3:

229 case ARM::R4:

230 case ARM::R5:

231 case ARM::R6:

232 case ARM::R7:

234

235 case ARM::R8:

236 case ARM::R9:

237 case ARM::R10:

240 else

242

243 case ARM::R11:

249

251

252 case ARM::R12:

255 else

257

258 case ARM::LR:

263

265

266 case ARM::D0:

267 case ARM::D1:

268 case ARM::D2:

269 case ARM::D3:

270 case ARM::D4:

271 case ARM::D5:

272 case ARM::D6:

273 case ARM::D7:

275

276 case ARM::D8:

277 case ARM::D9:

278 case ARM::D10:

279 case ARM::D11:

280 case ARM::D12:

281 case ARM::D13:

282 case ARM::D14:

283 case ARM::D15:

284 if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)

286 else

288

290 case ARM::D17:

291 case ARM::D18:

292 case ARM::D19:

293 case ARM::D20:

294 case ARM::D21:

295 case ARM::D22:

296 case ARM::D23:

297 case ARM::D24:

298 case ARM::D25:

299 case ARM::D26:

300 case ARM::D27:

301 case ARM::D28:

302 case ARM::D29:

303 case ARM::D30:

304 case ARM::D31:

306 }

307}

308

312

319

320

321

326

327

328

329 return true;

330}

331

332

333

334

338

339

341 return true;

342

343

345 return true;

346

347

348 return (RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||

350}

351

352

353

357

358

359

360

361

362

366

367

368

369

370 if (CFSize >= ((1 << 12) - 1) / 2)

371 return false;

372

374}

375

376

377

378

379

380bool

384

385

386

387

388

389

393 bool IsTailCallReturn = false;

395 unsigned RetOpcode = MBBI->getOpcode();

396 IsTailCallReturn = RetOpcode == ARM::TCRETURNdi ||

397 RetOpcode == ARM::TCRETURNri ||

398 RetOpcode == ARM::TCRETURNrinotr12;

399 }

401

402 int ArgumentPopSize = 0;

403 if (IsTailCallReturn) {

405

406

407

408

409 ArgumentPopSize = StackAdjust.getImm();

410 } else {

411

412

413

414

416 }

417

418 return ArgumentPopSize;

419}

420

424 F.needsUnwindTableEntry();

425}

426

427

428

431 unsigned Flags) {

432 unsigned Opc = MBBI->getOpcode();

439

441

442 switch (Opc) {

443 default:

445 break;

446 case ARM::t2ADDri:

447 case ARM::t2ADDri12:

448 case ARM::t2MOVTi16:

449 case ARM::tBL:

450

451

452

456 break;

457

458 case ARM::t2MOVi16: {

459 bool Wide = MBBI->getOperand(1).getImm() >= 256;

460 if (!Wide) {

463 NewInstr.add(MBBI->getOperand(0));

466 NewInstr.add(MO);

469 MBBI = NewMBBI;

470 }

472 break;

473 }

474

475 case ARM::tBLXr:

479 break;

480

481 case ARM::t2MOVi32imm:

482

483

484

485

486

487

488

492 MBB->insertAfter(MBBI, MIB);

496 break;

497

498 case ARM::t2STR_PRE:

499 if (MBBI->getOperand(0).getReg() == ARM::SP &&

500 MBBI->getOperand(2).getReg() == ARM::SP &&

501 MBBI->getOperand(3).getImm() == -4) {

502 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());

503 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))

507 } else {

509 }

510 break;

511

512 case ARM::t2LDR_POST:

513 if (MBBI->getOperand(1).getReg() == ARM::SP &&

514 MBBI->getOperand(2).getReg() == ARM::SP &&

515 MBBI->getOperand(3).getImm() == 4) {

516 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());

517 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveRegs))

521 } else {

523 }

524 break;

525

526 case ARM::t2LDMIA_RET:

527 case ARM::t2LDMIA_UPD:

528 case ARM::t2STMDB_UPD: {

529 unsigned Mask = 0;

530 bool Wide = false;

531 for (unsigned i = 4, NumOps = MBBI->getNumOperands(); i != NumOps; ++i) {

534 continue;

536 if (Reg == 15)

537 Reg = 14;

538 if (Reg >= 8 && Reg <= 13)

539 Wide = true;

540 else if (Opc == ARM::t2LDMIA_UPD && Reg == 14)

541 Wide = true;

542 Mask |= 1 << Reg;

543 }

544 if (!Wide) {

545 unsigned NewOpc;

546 switch (Opc) {

547 case ARM::t2LDMIA_RET:

548 NewOpc = ARM::tPOP_RET;

549 break;

550 case ARM::t2LDMIA_UPD:

551 NewOpc = ARM::tPOP;

552 break;

553 case ARM::t2STMDB_UPD:

554 NewOpc = ARM::tPUSH;

555 break;

556 default:

558 }

561 for (unsigned i = 2, NumOps = MBBI->getNumOperands(); i != NumOps; ++i)

562 NewInstr.add(MBBI->getOperand(i));

565 MBBI = NewMBBI;

566 }

567 unsigned SEHOpc =

568 (Opc == ARM::t2LDMIA_RET) ? ARM::SEH_SaveRegs_Ret : ARM::SEH_SaveRegs;

571 .addImm(Wide ? 1 : 0)

573 break;

574 }

575 case ARM::VSTMDDB_UPD:

576 case ARM::VLDMDIA_UPD: {

579 unsigned Reg = RegInfo->getSEHRegNum(MO.getReg());

583 }

584 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveFRegs))

588 break;

589 }

590 case ARM::tSUBspi:

591 case ARM::tADDspi:

592 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))

593 .addImm(MBBI->getOperand(2).getImm() * 4)

596 break;

597 case ARM::t2SUBspImm:

598 case ARM::t2SUBspImm12:

599 case ARM::t2ADDspImm:

600 case ARM::t2ADDspImm12:

601 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_StackAlloc))

602 .addImm(MBBI->getOperand(2).getImm())

605 break;

606

607 case ARM::tMOVr:

608 if (MBBI->getOperand(1).getReg() == ARM::SP &&

610 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(0).getReg());

611 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))

614 } else if (MBBI->getOperand(0).getReg() == ARM::SP &&

616 unsigned Reg = RegInfo->getSEHRegNum(MBBI->getOperand(1).getReg());

617 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_SaveSP))

620 } else {

622 }

623 break;

624

625 case ARM::tBX_RET:

626 case ARM::TCRETURNri:

627 case ARM::TCRETURNrinotr12:

628 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))

631 break;

632

633 case ARM::TCRETURNdi:

634 MIB = BuildMI(MF, DL, TII.get(ARM::SEH_Nop_Ret))

637 break;

638 }

639 return MBB->insertAfter(MBBI, MIB);

640}

641

646 return std::prev(MBBI);

647}

648

653 if (Start.isValid())

654 Start = std::next(Start);

655 else

656 Start = MBB.begin();

657

658 for (auto MI = Start; MI != End;) {

659 auto Next = std::next(MI);

660

661

663 MI = std::next(Next);

665 ++MI;

666 continue;

667 }

670 }

671}

672

678 if (isARM)

680 Pred, PredReg, TII, MIFlags);

681 else

683 Pred, PredReg, TII, MIFlags);

684}

685

691 unsigned PredReg = 0) {

693 MIFlags, Pred, PredReg);

694}

695

698 switch (MI.getOpcode()) {

699 case ARM::VSTMDDB_UPD:

701 break;

702 case ARM::STMDB_UPD:

703 case ARM::t2STMDB_UPD:

705 break;

706 case ARM::t2STR_PRE:

707 case ARM::STR_PRE_IMM:

708 return 4;

709 default:

711 }

712

714

715

716 for (int i = MI.getNumOperands() - 1; i >= 4; --i)

719}

720

722 size_t StackSizeInBytes) {

726

727 StackProbeSize =

728 F.getFnAttributeAsParsedInteger("stack-probe-size", StackProbeSize);

729 return (StackSizeInBytes >= StackProbeSize) &&

730 F.hasFnAttribute("no-stack-arg-probe");

731}

732

733namespace {

734

735struct StackAdjustingInsts {

736 struct InstInfo {

738 unsigned SPAdjust;

739 bool BeforeFPSet;

740

741#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

742 void dump() {

743 dbgs() << " " << (BeforeFPSet ? "before-fp " : " ")

744 << "sp-adjust=" << SPAdjust;

745 I->dump();

746 }

747#endif

748 };

749

751

753 bool BeforeFPSet = false) {

754 InstInfo Info = {I, SPAdjust, BeforeFPSet};

756 }

757

761 assert(Info != Insts.end() && "invalid sp adjusting instruction");

762 Info->SPAdjust += ExtraBytes;

763 }

764

765 void emitDefCFAOffsets(MachineBasicBlock &MBB, bool HasFP) {

767 unsigned CFAOffset = 0;

768 for (auto &Info : Insts) {

769 if (HasFP && Info.BeforeFPSet)

770 return;

771

772 CFAOffset += Info.SPAdjust;

773 CFIBuilder.setInsertPoint(std::next(Info.I));

774 CFIBuilder.buildDefCFAOffset(CFAOffset);

775 }

776 }

777

778#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

779 void dump() {

780 dbgs() << "StackAdjustingInsts:\n";

781 for (auto &Info : Insts)

783 }

784#endif

785};

786

787}

788

789

790

791

792

793

794

795

801 const Align Alignment,

802 const bool MustBeSingleInstruction) {

804 const bool CanUseBFC = AST.hasV6T2Ops() || AST.hasV7Ops();

805 const unsigned AlignMask = Alignment.value() - 1U;

806 const unsigned NrBitsToZero = Log2(Alignment);

809

810

811

812

813

814

815

816

817

818 if (CanUseBFC) {

823 } else if (AlignMask <= 255) {

829 } else {

830 assert(!MustBeSingleInstruction &&

831 "Shouldn't call emitAligningInstructions demanding a single "

832 "instruction to be emitted for large stack alignment for a target "

833 "without BFC.");

844 }

845 } else {

846

847

853 }

854}

855

856

857

858

859

860

861

866

867

870

871

872 int MaxRegBytes = 8 * 4;

874

875 MaxRegBytes = 11 * 4;

877

878 MaxRegBytes = 11 * 4 + 8 * 8;

879 }

880 int FPCXTSaveSize =

883}

884

894 "This emitPrologue does not support Thumb1!");

896 Align Alignment = STI.getFrameLowering()->getStackAlign();

900 int FPCXTSaveSize = 0;

903 STI.getPushPopSplitVariation(MF);

904

906

907

908

910

912

913

914

915 unsigned GPRCS1Size = 0, GPRCS2Size = 0, FPStatusSize = 0,

916 DPRCS1Size = 0, GPRCS3Size = 0, DPRCS2Size = 0;

917 int FramePtrSpillFI = 0;

918 int D8SpillFI = 0;

919

920

921

923 return;

924

925 StackAdjustingInsts DefCFAOffsetCandidates;

926 bool HasFP = hasFP(MF);

927

930 if (NumBytes != 0) {

933 DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes, true);

934 }

935 if (!NeedsWinCFI)

936 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);

937 if (NeedsWinCFI && MBBI != MBB.begin()) {

942 }

943 return;

944 }

945

946

948 bool BeforeFPPush = true;

951 int FI = I.getFrameIdx();

952

955

956 if (Reg == FramePtr.asMCReg()) {

957 FramePtrSpillFI = FI;

958 FramePtrSpillArea = Area;

959 }

960 if (Reg == ARM::D8)

961 D8SpillFI = FI;

962

963 switch (Area) {

965 FPCXTSaveSize += 4;

966 break;

968 GPRCS1Size += 4;

969 break;

971 GPRCS2Size += 4;

972 break;

974 FPStatusSize += 4;

975 break;

977 DPRCS1Size += 8;

978 break;

980 GPRCS3Size += 4;

981 break;

983 DPRCS2Size += 8;

984 break;

985 }

986 }

987

989 DPRCS1Push, GPRCS3Push;

990

991

993 LastPush = MBBI++;

994

995

996 if (FPCXTSaveSize > 0) {

997 LastPush = MBBI++;

998 DefCFAOffsetCandidates.addInst(LastPush, FPCXTSaveSize, BeforeFPPush);

999 }

1000

1001

1002 if (ArgRegsSaveSize) {

1005 LastPush = std::prev(MBBI);

1006 DefCFAOffsetCandidates.addInst(LastPush, ArgRegsSaveSize, BeforeFPPush);

1007 }

1008

1009

1010 if (GPRCS1Size > 0) {

1011 GPRCS1Push = LastPush = MBBI++;

1012 DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, BeforeFPPush);

1014 BeforeFPPush = false;

1015 }

1016

1017

1018

1019

1020

1021 unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;

1022 unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;

1023 unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;

1024 unsigned FPStatusOffset = GPRCS2Offset - FPStatusSize;

1025

1026 Align DPRAlign = DPRCS1Size ? std::min(Align(8), Alignment) : Align(4);

1027 unsigned DPRGapSize = (ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +

1028 GPRCS2Size + FPStatusSize) %

1029 DPRAlign.value();

1030

1031 unsigned DPRCS1Offset = FPStatusOffset - DPRGapSize - DPRCS1Size;

1032

1033 if (HasFP) {

1034

1035 [[maybe_unused]] int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);

1036 LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI

1037 << ", FPOffset: " << FPOffset << "\n");

1039 "Max FP estimation is wrong");

1041 NumBytes);

1042 }

1046

1047

1048 if (GPRCS2Size > 0) {

1050 GPRCS2Push = LastPush = MBBI++;

1051 DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size, BeforeFPPush);

1053 BeforeFPPush = false;

1054 }

1055

1056

1057 if (FPStatusSize > 0) {

1058 while (MBBI != MBB.end()) {

1059 unsigned Opc = MBBI->getOpcode();

1060 if (Opc == ARM::VMRS || Opc == ARM::VMRS_FPEXC)

1062 else

1063 break;

1064 }

1065 LastPush = MBBI++;

1066 DefCFAOffsetCandidates.addInst(LastPush, FPStatusSize);

1067 }

1068

1069

1070

1071 if (DPRGapSize) {

1072 assert(DPRGapSize == 4 && "unexpected alignment requirements for DPRs");

1073 if (LastPush != MBB.end() &&

1075 DefCFAOffsetCandidates.addExtraBytes(LastPush, DPRGapSize);

1076 else {

1079 DefCFAOffsetCandidates.addInst(std::prev(MBBI), DPRGapSize, BeforeFPPush);

1080 }

1081 }

1082

1083

1084 if (DPRCS1Size > 0) {

1085

1086

1087 while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VSTMDDB_UPD) {

1089 BeforeFPPush);

1090 DPRCS1Push = LastPush = MBBI++;

1091 }

1092 }

1093

1094

1095 if (DPRCS2Size > 0) {

1097

1098

1099

1100

1102 } else

1103 NumBytes = DPRCS1Offset;

1104

1105

1106 if (GPRCS3Size > 0) {

1108 GPRCS3Push = LastPush = MBBI++;

1109 DefCFAOffsetCandidates.addInst(LastPush, GPRCS3Size, BeforeFPPush);

1111 BeforeFPPush = false;

1112 }

1113

1114 bool NeedsWinCFIStackAlloc = NeedsWinCFI;

1116 NeedsWinCFIStackAlloc = false;

1117

1119 uint32_t NumWords = NumBytes >> 2;

1120

1121 if (NumWords < 65536) {

1126 } else {

1127

1128

1129

1131 .addImm(NumWords & 0xffff)

1136 .addImm(NumWords >> 16)

1139 }

1140

1141 switch (TM.getCodeModel()) {

1152 break;

1157

1163 break;

1164 }

1165

1173 if (NeedsWinCFIStackAlloc) {

1174 SEH = BuildMI(MF, dl, TII.get(ARM::SEH_StackAlloc))

1178 MBB.insertAfter(Instr, SEH);

1179 }

1180 NumBytes = 0;

1181 }

1182

1183 if (NumBytes) {

1184

1187 DefCFAOffsetCandidates.addExtraBytes(LastPush, NumBytes);

1188 else {

1191 DefCFAOffsetCandidates.addInst(std::prev(MBBI), NumBytes);

1192 }

1193

1194 if (HasFP && isARM)

1195

1196

1197

1198

1199

1200

1201

1202

1204 }

1205

1206

1207

1208

1209

1210

1211

1213 if (HasFP) {

1215

1216

1217 int64_t FPOffsetAfterPush;

1218 switch (FramePtrSpillArea) {

1220 FPPushInst = GPRCS1Push;

1221 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +

1222 ArgRegsSaveSize + FPCXTSaveSize +

1224 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS1, offset "

1225 << FPOffsetAfterPush << " after that push\n");

1226 break;

1228 FPPushInst = GPRCS2Push;

1229 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +

1230 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +

1232 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS2, offset "

1233 << FPOffsetAfterPush << " after that push\n");

1234 break;

1236 FPPushInst = GPRCS3Push;

1237 FPOffsetAfterPush = MFI.getObjectOffset(FramePtrSpillFI) +

1238 ArgRegsSaveSize + FPCXTSaveSize + GPRCS1Size +

1239 FPStatusSize + GPRCS2Size + DPRCS1Size + DPRGapSize +

1241 LLVM_DEBUG(dbgs() << "Frame pointer in GPRCS3, offset "

1242 << FPOffsetAfterPush << " after that push\n");

1243 break;

1244 default:

1246 break;

1247 }

1248 AfterPush = std::next(FPPushInst);

1250 assert(FPOffsetAfterPush == 0);

1251

1252

1254 FramePtr, ARM::SP, FPOffsetAfterPush,

1256

1257 if (!NeedsWinCFI) {

1258

1259

1261 if (FPOffsetAfterPush != 0)

1263 else

1265 }

1266 }

1267

1268

1269

1270 if (NeedsWinCFI && MBBI != MBB.begin()) {

1273 End = AfterPush;

1275 BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))

1278 }

1279

1280

1281

1282

1283 if (!NeedsWinCFI) {

1284 for (const auto &Entry : reverse(CSI)) {

1286 int FI = Entry.getFrameIdx();

1289 RegInfo)) {

1291 CFIPos = std::next(GPRCS1Push);

1292 break;

1294 CFIPos = std::next(GPRCS2Push);

1295 break;

1297 CFIPos = std::next(DPRCS1Push);

1298 break;

1300 CFIPos = std::next(GPRCS3Push);

1301 break;

1305

1306 break;

1307 }

1308

1311 .buildOffset(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,

1313 }

1314 }

1315 }

1316

1317

1318

1319

1320

1321 if (!NeedsWinCFI) {

1322 LLVM_DEBUG(DefCFAOffsetCandidates.dump());

1323 DefCFAOffsetCandidates.emitDefCFAOffsets(MBB, HasFP);

1324 }

1325

1326 if (STI.isTargetELF() && hasFP(MF))

1329

1337

1338

1339

1340

1341

1347 false);

1348 } else {

1349

1350

1351

1352

1353

1354

1355

1360 false);

1364 }

1365

1367 }

1368

1369

1370

1371

1372

1373

1374 if (RegInfo->hasBasePointer(MF)) {

1375 if (isARM)

1376 BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), RegInfo->getBaseRegister())

1380 else

1381 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), RegInfo->getBaseRegister())

1384 }

1385

1386

1387

1388

1391}

1392

1401 "This emitEpilogue does not support Thumb1!");

1404 STI.getPushPopSplitVariation(MF);

1405

1407

1408

1409

1411

1412

1413

1417

1418

1419

1421 return;

1422

1423

1426

1433 }

1434

1435 if (NumBytes + IncomingArgStackToRestore != 0)

1437 NumBytes + IncomingArgStackToRestore,

1439 } else {

1440

1441 if (MBBI != MBB.begin()) {

1442 do {

1444 } while (MBBI != MBB.begin() &&

1448 }

1449

1454 }

1455

1456

1457 NumBytes -=

1462

1463

1464

1467 if (NumBytes) {

1468 if (isARM)

1472 else {

1473

1474

1475

1476

1477

1478

1479

1481 "No scratch register to restore SP from FP!");

1488 }

1489 } else {

1490

1491 if (isARM)

1497 else

1502 }

1503 } else if (NumBytes &&

1507

1508

1511 (void)PushPopSplit;

1513 }

1514

1517

1518

1519 while (MBBI != MBB.end() && MBBI->getOpcode() == ARM::VLDMDIA_UPD)

1521 }

1524 "unexpected DPR alignment gap");

1527 }

1528

1531 (void)PushPopSplit;

1533 }

1535

1536 if (ReservedArgStack || IncomingArgStackToRestore) {

1537 assert((int)ReservedArgStack + IncomingArgStackToRestore >= 0 &&

1538 "attempting to restore negative stack amount");

1540 ReservedArgStack + IncomingArgStackToRestore,

1542 }

1543

1544

1545

1546

1547

1550 }

1551

1556 }

1557}

1558

1559

1560

1561

1562

1568

1571 int SPAdj) const {

1579

1580 FrameReg = ARM::SP;

1582

1583

1584

1586

1587

1588

1589 if (RegInfo->hasStackRealignment(MF)) {

1590 assert(hasFP(MF) && "dynamic stack realignment without a FP!");

1591 if (isFixed) {

1592 FrameReg = RegInfo->getFrameRegister(MF);

1594 } else if (hasMovingSP) {

1595 assert(RegInfo->hasBasePointer(MF) &&

1596 "VLAs and dynamic stack alignment, but missing base pointer!");

1597 FrameReg = RegInfo->getBaseRegister();

1599 }

1601 }

1602

1603

1605

1606

1607 if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {

1608 FrameReg = RegInfo->getFrameRegister(MF);

1609 return FPOffset;

1610 } else if (hasMovingSP) {

1611 assert(RegInfo->hasBasePointer(MF) && "missing base pointer!");

1613

1614

1615

1616 if (FPOffset >= -255 && FPOffset < 0) {

1617 FrameReg = RegInfo->getFrameRegister(MF);

1618 return FPOffset;

1619 }

1620 }

1622

1623

1624

1625

1626

1629

1630

1631 if (AFI->isThumb2Function() && FPOffset >= -255 && FPOffset < 0) {

1632 FrameReg = RegInfo->getFrameRegister(MF);

1633 return FPOffset;

1634 }

1635 } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) {

1636

1637 FrameReg = RegInfo->getFrameRegister(MF);

1638 return FPOffset;

1639 }

1640 }

1641

1642

1643

1644 if (RegInfo->hasBasePointer(MF)) {

1645 FrameReg = RegInfo->getBaseRegister();

1647 }

1649}

1650

1654 unsigned StmOpc, unsigned StrOpc,

1655 bool NoGap,

1660

1662

1663 using RegAndKill = std::pair<unsigned, bool>;

1664

1666 unsigned i = CSI.size();

1667 while (i != 0) {

1668 unsigned LastReg = 0;

1669 for (; i != 0; --i) {

1671 if (!Func(Reg))

1672 continue;

1673

1675 bool isLiveIn = MRI.isLiveIn(Reg);

1676 if (!isLiveIn && MRI.isReserved(Reg))

1677 MBB.addLiveIn(Reg);

1678

1679

1680

1681 if (NoGap && LastReg && LastReg != Reg-1)

1682 break;

1683 LastReg = Reg;

1684

1685

1686

1687

1688

1689 Regs.push_back(std::make_pair(Reg, !isLiveIn));

1690 }

1691

1692 if (Regs.empty())

1693 continue;

1694

1695 llvm::sort(Regs, [&](const RegAndKill &LHS, const RegAndKill &RHS) {

1696 return TRI.getEncodingValue(LHS.first) < TRI.getEncodingValue(RHS.first);

1697 });

1698

1699 if (Regs.size() > 1 || StrOpc== 0) {

1704 for (const auto &[Reg, Kill] : Regs)

1706 } else if (Regs.size() == 1) {

1713 }

1714 Regs.clear();

1715

1716

1717

1718

1720 --MI;

1721 }

1722}

1723

1727 unsigned LdmOpc, unsigned LdrOpc,

1728 bool isVarArg, bool NoGap,

1732 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();

1733 ARMFunctionInfo *AFI = MF.getInfo();

1736 bool isTailCall = false;

1737 bool isInterrupt = false;

1738 bool isTrap = false;

1739 bool isCmseEntry = false;

1741 STI.getPushPopSplitVariation(MF);

1743 DL = MI->getDebugLoc();

1744 unsigned RetOpcode = MI->getOpcode();

1745 isTailCall =

1746 (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNri ||

1747 RetOpcode == ARM::TCRETURNrinotr12);

1748 isInterrupt =

1749 RetOpcode == ARM::SUBS_PC_LR || RetOpcode == ARM::t2SUBS_PC_LR;

1750 isTrap = RetOpcode == ARM::TRAP || RetOpcode == ARM::tTRAP;

1751 isCmseEntry = (RetOpcode == ARM::tBXNS || RetOpcode == ARM::tBXNS_RET);

1752 }

1753

1754 SmallVector<unsigned, 4> Regs;

1755 unsigned i = CSI.size();

1756 while (i != 0) {

1757 unsigned LastReg = 0;

1758 bool DeleteRet = false;

1759 for (; i != 0; --i) {

1760 CalleeSavedInfo &Info = CSI[i-1];

1761 MCRegister Reg = Info.getReg();

1763 continue;

1764

1765 if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&

1770 Reg = ARM::PC;

1771

1772 DeleteRet = true;

1773 LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET;

1774 }

1775

1776

1777

1778

1779 if (NoGap && LastReg && LastReg != Reg-1)

1780 break;

1781

1782 LastReg = Reg;

1784 }

1785

1786 if (Regs.empty())

1787 continue;

1788

1790 return TRI.getEncodingValue(LHS) < TRI.getEncodingValue(RHS);

1791 });

1792

1793 if (Regs.size() > 1 || LdrOpc == 0) {

1798 for (unsigned Reg : Regs)

1800 if (DeleteRet) {

1803 MI->eraseFromParent();

1804 }

1805 }

1806 MI = MIB;

1807 } else if (Regs.size() == 1) {

1808

1809

1810 if (Regs[0] == ARM::PC)

1811 Regs[0] = ARM::LR;

1812 MachineInstrBuilder MIB =

1817

1818

1819 if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) {

1822 } else

1825 }

1826 Regs.clear();

1827

1828

1829

1831 ++MI;

1832 }

1833}

1834

1838 unsigned PushOpc) const {

1841

1843 auto RegPresent = [&CSI](MCRegister Reg) {

1845 return C.getReg() == Reg;

1846 });

1847 };

1848

1849

1850

1851 if (RegPresent(ARM::FPSCR)) {

1855

1857 }

1858

1859

1860

1861 if (RegPresent(ARM::FPEXC)) {

1865

1867 }

1868

1869

1870 if (Regs.size() == 0)

1871 return;

1872

1873

1874 MachineInstrBuilder MIB =

1879

1882 }

1883}

1884

1885void ARMFrameLowering::emitFPStatusRestores(

1890

1891 auto RegPresent = [&CSI](MCRegister Reg) {

1893 return C.getReg() == Reg;

1894 });

1895 };

1896

1897

1898 if (!RegPresent(ARM::FPSCR) && !RegPresent(ARM::FPEXC))

1899 return;

1900

1901

1902 MachineInstrBuilder MIB =

1907

1908

1909 if (RegPresent(ARM::FPSCR)) {

1911 }

1912

1913

1914 if (RegPresent(ARM::FPEXC)) {

1916 }

1917

1918

1919 if (RegPresent(ARM::FPSCR)) {

1924 }

1925

1926

1927

1928 if (RegPresent(ARM::FPEXC)) {

1933 }

1934}

1935

1936

1937

1938

1941 unsigned NumAlignedDPRCS2Regs,

1949

1950

1951

1952

1954 unsigned DNum = I.getReg() - ARM::D8;

1955 if (DNum > NumAlignedDPRCS2Regs - 1)

1956 continue;

1957 int FI = I.getFrameIdx();

1958

1959

1961

1962

1963

1964

1965

1966

1967

1968 if (DNum == 0)

1970 }

1971

1972

1973

1974

1975

1976

1977

1978

1982

1983

1984

1985 unsigned Opc = isThumb ? ARM::t2SUBri : ARM::SUBri;

1988 .addImm(8 * NumAlignedDPRCS2Regs)

1991

1993

1994

1995

1996

1997

1999

2000

2001

2002

2003

2004 Opc = isThumb ? ARM::tMOVr : ARM::MOVr;

2010

2011

2012

2013 unsigned NextReg = ARM::D8;

2014

2015

2016

2017 if (NumAlignedDPRCS2Regs >= 6) {

2019 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);

2020 MBB.addLiveIn(SupReg);

2027 NextReg += 4;

2028 NumAlignedDPRCS2Regs -= 4;

2029 }

2030

2031

2032

2033 unsigned R4BaseReg = NextReg;

2034

2035

2036 if (NumAlignedDPRCS2Regs >= 4) {

2038 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);

2039 MBB.addLiveIn(SupReg);

2046 NextReg += 4;

2047 NumAlignedDPRCS2Regs -= 4;

2048 }

2049

2050

2051 if (NumAlignedDPRCS2Regs >= 2) {

2053 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);

2054 MBB.addLiveIn(SupReg);

2060 NextReg += 2;

2061 NumAlignedDPRCS2Regs -= 2;

2062 }

2063

2064

2065 if (NumAlignedDPRCS2Regs) {

2066 MBB.addLiveIn(NextReg);

2067

2071 .addImm((NextReg - R4BaseReg) * 2)

2073 }

2074

2075

2076 std::prev(MI)->addRegisterKilled(ARM::R4, TRI);

2077}

2078

2079

2080

2083 unsigned NumAlignedDPRCS2Regs) {

2084

2085

2086

2088 assert(MI->mayStore() && "Expecting spill instruction");

2089

2090

2091 switch(NumAlignedDPRCS2Regs) {

2092 case 7:

2093 ++MI;

2094 assert(MI->mayStore() && "Expecting spill instruction");

2095 [[fallthrough]];

2096 default:

2097 ++MI;

2098 assert(MI->mayStore() && "Expecting spill instruction");

2099 [[fallthrough]];

2100 case 1:

2101 case 2:

2102 case 4:

2103 assert(MI->killsRegister(ARM::R4, nullptr) && "Missed kill flag");

2104 ++MI;

2105 }

2106 return MI;

2107}

2108

2109

2110

2111

2114 unsigned NumAlignedDPRCS2Regs,

2121

2122

2123 int D8SpillFI = 0;

2125 if (I.getReg() == ARM::D8) {

2126 D8SpillFI = I.getFrameIdx();

2127 break;

2128 }

2129

2130

2131

2132

2133

2134

2137

2138 unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri;

2144

2145

2146 unsigned NextReg = ARM::D8;

2147

2148

2149 if (NumAlignedDPRCS2Regs >= 6) {

2151 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);

2158 NextReg += 4;

2159 NumAlignedDPRCS2Regs -= 4;

2160 }

2161

2162

2163

2164 unsigned R4BaseReg = NextReg;

2165

2166

2167 if (NumAlignedDPRCS2Regs >= 4) {

2169 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QQPRRegClass);

2175 NextReg += 4;

2176 NumAlignedDPRCS2Regs -= 4;

2177 }

2178

2179

2180 if (NumAlignedDPRCS2Regs >= 2) {

2182 TRI->getMatchingSuperReg(NextReg, ARM::dsub_0, &ARM::QPRRegClass);

2187 NextReg += 2;

2188 NumAlignedDPRCS2Regs -= 2;

2189 }

2190

2191

2192 if (NumAlignedDPRCS2Regs)

2195 .addImm(2 * (NextReg - R4BaseReg))

2197

2198

2200}

2201

2205 if (CSI.empty())

2206 return false;

2207

2211 STI.getPushPopSplitVariation(MF);

2213

2214 unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;

2216 ARM::t2STR_PRE : ARM::STR_PRE_IMM;

2217 unsigned FltOpc = ARM::VSTMDDB_UPD;

2219

2223 }

2224

2226 return C.getReg() == ARM::FPCXTNS;

2227 })) {

2229 ARM::SP)

2233 }

2234

2235 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,

2236 RegInfo](unsigned Reg, SpillArea TestArea) {

2237 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==

2238 TestArea;

2239 };

2240 auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {

2242 };

2243 auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {

2245 };

2246 auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {

2248 };

2249 auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {

2251 };

2252

2253 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS1);

2254 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS2);

2255 emitFPStatusSaves(MBB, MI, CSI, PushOpc);

2256 emitPushInst(MBB, MI, CSI, FltOpc, 0, true, IsDPRCS1);

2257 emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, IsGPRCS3);

2258

2259

2260

2261

2262 if (NumAlignedDPRCS2Regs)

2264

2265 return true;

2266}

2267

2271 if (CSI.empty())

2272 return false;

2273

2277

2281 STI.getPushPopSplitVariation(MF);

2282

2283

2284

2285 if (NumAlignedDPRCS2Regs)

2287

2288 unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD;

2289 unsigned LdrOpc =

2290 AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;

2291 unsigned FltOpc = ARM::VLDMDIA_UPD;

2292

2293 auto CheckRegArea = [PushPopSplit, NumAlignedDPRCS2Regs,

2294 RegInfo](unsigned Reg, SpillArea TestArea) {

2295 return getSpillArea(Reg, PushPopSplit, NumAlignedDPRCS2Regs, RegInfo) ==

2296 TestArea;

2297 };

2298 auto IsGPRCS1 = [&CheckRegArea](unsigned Reg) {

2300 };

2301 auto IsGPRCS2 = [&CheckRegArea](unsigned Reg) {

2303 };

2304 auto IsDPRCS1 = [&CheckRegArea](unsigned Reg) {

2306 };

2307 auto IsGPRCS3 = [&CheckRegArea](unsigned Reg) {

2309 };

2310

2311 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS3);

2312 emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, IsDPRCS1);

2313 emitFPStatusRestores(MBB, MI, CSI, PopOpc);

2314 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS2);

2315 emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, IsGPRCS1);

2316

2317 return true;

2318}

2319

2320

2323 unsigned FnSize = 0;

2324 for (auto &MBB : MF) {

2325 for (auto &MI : MBB)

2326 FnSize += TII.getInstSizeInBytes(MI);

2327 }

2330 FnSize += Table.MBBs.size() * 4;

2332 return FnSize;

2333}

2334

2335

2336

2337

2338

2341 bool &HasNonSPFrameIndex) {

2345 unsigned Limit = (1 << 12) - 1;

2346 for (auto &MBB : MF) {

2347 for (auto &MI : MBB) {

2348 if (MI.isDebugInstr())

2349 continue;

2350 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {

2351 if (MI.getOperand(i).isFI())

2352 continue;

2353

2354

2355

2356 if (MI.getOpcode() == ARM::ADDri) {

2357 Limit = std::min(Limit, (1U << 8) - 1);

2358 break;

2359 }

2360

2361

2362 if (MI.getOpcode() == ARM::t2ADDri || MI.getOpcode() == ARM::t2ADDri12)

2363 break;

2364

2367 if (RegClass && !RegClass->contains(ARM::SP))

2368 HasNonSPFrameIndex = true;

2369

2370

2374

2375 break;

2378 Limit = std::min(Limit, (1U << 8) - 1);

2379 break;

2381 Limit = std::min(Limit, ((1U << 8) - 1) * 2);

2382 break;

2386 Limit = std::min(Limit, ((1U << 8) - 1) * 4);

2387 break;

2389

2390

2392 Limit = std::min(Limit, (1U << 8) - 1);

2393 break;

2396

2397

2398 return 0;

2400 Limit = std::min(Limit, ((1U << 7) - 1) * 1);

2401 break;

2403 Limit = std::min(Limit, ((1U << 7) - 1) * 2);

2404 break;

2406 Limit = std::min(Limit, ((1U << 7) - 1) * 4);

2407 break;

2408 default:

2409 llvm_unreachable("Unhandled addressing mode in stack size limit calculation");

2410 }

2411 break;

2412 }

2413 }

2414 }

2415

2416 return Limit;

2417}

2418

2419

2420

2421

2422static void

2426 return;

2427

2428

2430 return;

2431

2432

2434 return;

2435

2436

2438 return;

2439

2440

2443 return;

2444

2445

2446

2447

2448

2449

2450 unsigned NumSpills = 0;

2451 for (; NumSpills < 8; ++NumSpills)

2452 if (!SavedRegs.test(ARM::D8 + NumSpills))

2453 break;

2454

2455

2456 if (NumSpills < 2)

2457 return;

2458

2459

2461

2462

2463 SavedRegs.set(ARM::R4);

2464}

2465

2467

2468

2469 if (STI.hasV8_1MMainlineOps() &&

2471 return false;

2472

2473

2474

2475

2477 true ))

2478 return false;

2479

2480 return true;

2481}

2482

2486 return Subtarget.createAAPCSFrameChain() && hasFP(MF);

2487}

2488

2489

2490

2491

2496 return false;

2497

2499 for (const auto &MBB : MF)

2500 for (const auto &MI : MBB)

2501 if (MI.getOpcode() == ARM::tSTRspi || MI.getOpcode() == ARM::tSTRi ||

2502 STI.genExecuteOnly())

2503 for (const auto &Op : MI.operands())

2504 if (Op.isFI()) {

2507 if (ARM::hGPRRegClass.contains(Reg) && Reg != ARM::SP)

2508 return true;

2509 }

2510 return false;

2511}

2512

2517

2518

2519

2520

2523 bool CS1Spilled = false;

2524 bool LRSpilled = false;

2525 unsigned NumGPRSpills = 0;

2526 unsigned NumFPRSpills = 0;

2538 (void)TRI;

2541 STI.getPushPopSplitVariation(MF);

2542

2543

2544

2545 if (F.hasFnAttribute("interrupt") && F.hasFnAttribute("save-fp")) {

2546 SavedRegs.set(ARM::FPSCR);

2547 SavedRegs.set(ARM::R4);

2548

2549

2550 if (STI.isMClass()) {

2551 SavedRegs.reset(ARM::FPEXC);

2552 } else {

2553 SavedRegs.set(ARM::FPEXC);

2554 SavedRegs.set(ARM::R5);

2555 }

2556 }

2557

2558

2559

2560

2561

2562

2564 (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF)))

2565 SavedRegs.set(ARM::R4);

2566

2567

2568

2569

2570

2571

2572 if (STI.isTargetWindows() &&

2574 SavedRegs.set(ARM::R4);

2575 SavedRegs.set(ARM::LR);

2576 }

2577

2579

2581 SavedRegs.set(ARM::LR);

2582

2583

2584

2585

2586

2587

2588

2589 if (MFI.hasVarSizedObjects() || RegInfo->hasStackRealignment(MF) ||

2590 MFI.estimateStackSize(MF) > 508)

2591 SavedRegs.set(ARM::R4);

2592 }

2593

2594

2596

2597

2598 if (RegInfo->hasBasePointer(MF))

2599 SavedRegs.set(RegInfo->getBaseRegister());

2600

2601

2603 CanEliminateFrame = false;

2604

2605

2607 CanEliminateFrame = false;

2608

2609

2610

2611 const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);

2612 for (unsigned i = 0; CSRegs[i]; ++i) {

2613 unsigned Reg = CSRegs[i];

2614 bool Spilled = false;

2615 if (SavedRegs.test(Reg)) {

2616 Spilled = true;

2617 CanEliminateFrame = false;

2618 }

2619

2620 if (!ARM::GPRRegClass.contains(Reg)) {

2621 if (Spilled) {

2622 if (ARM::SPRRegClass.contains(Reg))

2623 NumFPRSpills++;

2624 else if (ARM::DPRRegClass.contains(Reg))

2625 NumFPRSpills += 2;

2626 else if (ARM::QPRRegClass.contains(Reg))

2627 NumFPRSpills += 4;

2628 }

2629 continue;

2630 }

2631

2632 if (Spilled) {

2633 NumGPRSpills++;

2634

2636 if (Reg == ARM::LR)

2637 LRSpilled = true;

2638 CS1Spilled = true;

2639 continue;

2640 }

2641

2642

2643 switch (Reg) {

2644 case ARM::LR:

2645 LRSpilled = true;

2646 [[fallthrough]];

2647 case ARM::R0: case ARM::R1:

2648 case ARM::R2: case ARM::R3:

2649 case ARM::R4: case ARM::R5:

2650 case ARM::R6: case ARM::R7:

2651 CS1Spilled = true;

2652 break;

2653 default:

2654 break;

2655 }

2656 } else {

2658 UnspilledCS1GPRs.push_back(Reg);

2659 continue;

2660 }

2661

2662 switch (Reg) {

2663 case ARM::R0: case ARM::R1:

2664 case ARM::R2: case ARM::R3:

2665 case ARM::R4: case ARM::R5:

2666 case ARM::R6: case ARM::R7:

2667 case ARM::LR:

2668 UnspilledCS1GPRs.push_back(Reg);

2669 break;

2670 default:

2671 UnspilledCS2GPRs.push_back(Reg);

2672 break;

2673 }

2674 }

2675 }

2676

2677 bool ForceLRSpill = false;

2680

2681

2682 if (FnSize >= (1 << 11)) {

2683 CanEliminateFrame = false;

2684 ForceLRSpill = true;

2685 }

2686 }

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696

2697

2698

2699

2700

2701

2702 unsigned EstimatedStackSize =

2703 MFI.estimateStackSize(MF) + 4 * (NumGPRSpills + NumFPRSpills);

2704

2705

2706 int MaxFixedOffset = 0;

2707 for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) {

2708 int MaxObjectOffset = MFI.getObjectOffset(I) + MFI.getObjectSize(I);

2709 MaxFixedOffset = std::max(MaxFixedOffset, MaxObjectOffset);

2710 }

2711

2712 bool HasFP = hasFP(MF);

2713 if (HasFP) {

2715 EstimatedStackSize += 4;

2716 } else {

2717

2718

2719 EstimatedStackSize += MaxFixedOffset;

2720 }

2721 EstimatedStackSize += 16;

2722

2723 unsigned EstimatedRSStackSizeLimit, EstimatedRSFixedSizeLimit;

2724 bool HasNonSPFrameIndex = false;

2726

2727

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744 if (RegInfo->hasBasePointer(MF))

2745 EstimatedRSStackSizeLimit = (1U << 5) * 4;

2746 else

2747 EstimatedRSStackSizeLimit = (1U << 8) * 4;

2748 EstimatedRSFixedSizeLimit = (1U << 5) * 4;

2749 } else {

2750 EstimatedRSStackSizeLimit =

2752 EstimatedRSFixedSizeLimit = EstimatedRSStackSizeLimit;

2753 }

2754

2755

2756 bool HasLargeStack = EstimatedStackSize > EstimatedRSStackSizeLimit;

2757

2758

2759

2760

2761

2762 bool HasMovingSP = MFI.hasVarSizedObjects() ||

2764 bool HasBPOrFixedSP = RegInfo->hasBasePointer(MF) || !HasMovingSP;

2765

2766

2767

2768

2769

2770

2771

2773 bool HasLargeArgumentList =

2774 HasFP && (MaxFixedOffset - MaxFPOffset) > (int)EstimatedRSFixedSizeLimit;

2775

2776 bool BigFrameOffsets = HasLargeStack || !HasBPOrFixedSP ||

2777 HasLargeArgumentList || HasNonSPFrameIndex;

2778 LLVM_DEBUG(dbgs() << "EstimatedLimit: " << EstimatedRSStackSizeLimit

2779 << "; EstimatedStack: " << EstimatedStackSize

2780 << "; EstimatedFPStack: " << MaxFixedOffset - MaxFPOffset

2781 << "; BigFrameOffsets: " << BigFrameOffsets << "\n");

2782 if (BigFrameOffsets ||

2783 !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {

2785

2786

2787

2788

2789

2792

2793

2796 !LRSpilled) {

2797 SavedRegs.set(ARM::LR);

2798 LRSpilled = true;

2799 NumGPRSpills++;

2800 auto LRPos = llvm::find(UnspilledCS1GPRs, ARM::LR);

2801 if (LRPos != UnspilledCS1GPRs.end())

2802 UnspilledCS1GPRs.erase(LRPos);

2803 }

2805 if (FPPos != UnspilledCS1GPRs.end())

2806 UnspilledCS1GPRs.erase(FPPos);

2807 NumGPRSpills++;

2809 CS1Spilled = true;

2810 }

2811

2812

2813

2814

2815

2816

2817

2818

2819

2820

2821

2822

2823

2824 unsigned NumExtraCSSpill = 0;

2825

2827

2828

2829

2830

2831

2832

2833

2834

2835

2836

2838

2839

2840

2841 int EntryRegDeficit = 0;

2842 for (unsigned Reg : {ARM::R0, ARM::R1, ARM::R2, ARM::R3}) {

2844 --EntryRegDeficit;

2847 << " is unused argument register, EntryRegDeficit = "

2848 << EntryRegDeficit << "\n");

2849 }

2850 }

2851

2852

2855 << " return regs used, ExitRegDeficit = "

2856 << ExitRegDeficit << "\n");

2857

2858 int RegDeficit = std::max(EntryRegDeficit, ExitRegDeficit);

2859 LLVM_DEBUG(dbgs() << "RegDeficit = " << RegDeficit << "\n");

2860

2861

2862

2863 for (unsigned Reg : {ARM::R4, ARM::R5, ARM::R6}) {

2864 if (SavedRegs.test(Reg)) {

2865 --RegDeficit;

2867 << " is saved low register, RegDeficit = "

2868 << RegDeficit << "\n");

2869 } else {

2874 << " is non-saved low register, adding to AvailableRegs\n");

2875 }

2876 }

2877

2878

2879 if (!HasFP || FramePtr != ARM::R7) {

2880 if (SavedRegs.test(ARM::R7)) {

2881 --RegDeficit;

2882 LLVM_DEBUG(dbgs() << "%r7 is saved low register, RegDeficit = "

2883 << RegDeficit << "\n");

2884 } else {

2885 AvailableRegs.push_back(ARM::R7);

2888 << "%r7 is non-saved low register, adding to AvailableRegs\n");

2889 }

2890 }

2891

2892

2893 for (unsigned Reg : {ARM::R8, ARM::R9, ARM::R10, ARM::R11}) {

2894 if (SavedRegs.test(Reg)) {

2895 ++RegDeficit;

2897 << " is saved high register, RegDeficit = "

2898 << RegDeficit << "\n");

2899 }

2900 }

2901

2902

2903

2904

2905 if ((EntryRegDeficit > ExitRegDeficit) &&

2908 if (SavedRegs.test(ARM::LR)) {

2909 --RegDeficit;

2910 LLVM_DEBUG(dbgs() << "%lr is saved register, RegDeficit = "

2911 << RegDeficit << "\n");

2912 } else {

2913 AvailableRegs.push_back(ARM::LR);

2914 LLVM_DEBUG(dbgs() << "%lr is not saved, adding to AvailableRegs\n");

2915 }

2916 }

2917

2918

2919

2920

2921

2922

2923 LLVM_DEBUG(dbgs() << "Final RegDeficit = " << RegDeficit << "\n");

2924 for (; RegDeficit > 0 && !AvailableRegs.empty(); --RegDeficit) {

2925 unsigned Reg = AvailableRegs.pop_back_val();

2927 << " to make up reg deficit\n");

2928 SavedRegs.set(Reg);

2929 NumGPRSpills++;

2930 CS1Spilled = true;

2931 assert(MRI.isReserved(Reg) && "Should not be reserved");

2932 if (Reg != ARM::LR && MRI.isPhysRegUsed(Reg))

2933 NumExtraCSSpill++;

2934 UnspilledCS1GPRs.erase(llvm::find(UnspilledCS1GPRs, Reg));

2935 if (Reg == ARM::LR)

2936 LRSpilled = true;

2937 }

2938 LLVM_DEBUG(dbgs() << "After adding spills, RegDeficit = " << RegDeficit

2939 << "\n");

2940 }

2941

2942

2943

2945

2946

2947

2948 if (!LRSpilled && CS1Spilled && !ExpensiveLRRestore) {

2949 SavedRegs.set(ARM::LR);

2950 NumGPRSpills++;

2952 LRPos = llvm::find(UnspilledCS1GPRs, (unsigned)ARM::LR);

2953 if (LRPos != UnspilledCS1GPRs.end())

2954 UnspilledCS1GPRs.erase(LRPos);

2955

2956 ForceLRSpill = false;

2957 if (MRI.isReserved(ARM::LR) && MRI.isPhysRegUsed(ARM::LR) &&

2959 NumExtraCSSpill++;

2960 }

2961

2962

2963

2964

2965 LLVM_DEBUG(dbgs() << "NumGPRSpills = " << NumGPRSpills << "\n");

2967 if (TargetAlign >= Align(8) && (NumGPRSpills & 1)) {

2968 if (CS1Spilled && !UnspilledCS1GPRs.empty()) {

2969 for (unsigned Reg : UnspilledCS1GPRs) {

2970

2971

2973 (STI.isTargetWindows() && Reg == ARM::R11) ||

2975 (Reg == ARM::LR && !ExpensiveLRRestore)) {

2976 SavedRegs.set(Reg);

2978 << " to make up alignment\n");

2979 if (MRI.isReserved(Reg) && MRI.isPhysRegUsed(Reg) &&

2981 NumExtraCSSpill++;

2982 break;

2983 }

2984 }

2986 unsigned Reg = UnspilledCS2GPRs.front();

2987 SavedRegs.set(Reg);

2989 << " to make up alignment\n");

2990 if (MRI.isReserved(Reg) && MRI.isPhysRegUsed(Reg))

2991 NumExtraCSSpill++;

2992 }

2993 }

2994

2995

2996

2997

2998

2999

3000

3001 unsigned RegsNeeded = 0;

3003 RegsNeeded++;

3004

3005

3007 RegsNeeded++;

3008 }

3009

3010 if (RegsNeeded > NumExtraCSSpill) {

3011

3012

3013 unsigned NumExtras = TargetAlign.value() / 4;

3015 while (NumExtras && !UnspilledCS1GPRs.empty()) {

3016 unsigned Reg = UnspilledCS1GPRs.pop_back_val();

3017 if (MRI.isReserved(Reg) &&

3020 NumExtras--;

3021 }

3022 }

3023

3025 while (NumExtras && !UnspilledCS2GPRs.empty()) {

3026 unsigned Reg = UnspilledCS2GPRs.pop_back_val();

3027 if (MRI.isReserved(Reg)) {

3029 NumExtras--;

3030 }

3031 }

3032 }

3033 if (NumExtras == 0) {

3034 for (unsigned Reg : Extras) {

3035 SavedRegs.set(Reg);

3036 if (MRI.isPhysRegUsed(Reg))

3037 NumExtraCSSpill++;

3038 }

3039 }

3040 while ((RegsNeeded > NumExtraCSSpill) && RS) {

3041

3042 LLVM_DEBUG(dbgs() << "Reserving emergency spill slot\n");

3044 unsigned Size = TRI->getSpillSize(RC);

3045 Align Alignment = TRI->getSpillAlign(RC);

3046 RS->addScavengingFrameIndex(

3047 MFI.CreateSpillStackObject(Size, Alignment));

3048 --RegsNeeded;

3049 }

3050 }

3051 }

3052

3053 if (ForceLRSpill)

3054 SavedRegs.set(ARM::LR);

3056}

3057

3061 return;

3062

3063

3064

3065

3067 if (Info.getReg() != ARM::LR)

3068 continue;

3071 return !Term.isReturn() || Term.getOpcode() == ARM::LDMIA_RET ||

3072 Term.getOpcode() == ARM::t2LDMIA_RET ||

3073 Term.getOpcode() == ARM::tPOP_RET;

3074 });

3075 })) {

3076 Info.setRestored(false);

3077 break;

3078 }

3079 }

3080}

3081

3087

3091

3092

3093

3094

3097 SavedRegs.set(ARM::R0);

3098}

3099

3102 std::vector &CSI) const {

3103

3104

3105 if (STI.hasV8_1MMainlineOps() &&

3107 CSI.emplace_back(ARM::FPCXTNS);

3108 CSI.back().setRestored(false);

3109 }

3110

3111

3112

3113

3116

3117

3118

3119

3120 switch (STI.getPushPopSplitVariation(MF)) {

3122

3124 [=](const auto &CS) {

3126 return Reg == ARM::R10 || Reg == ARM::R11 ||

3127 Reg == ARM::R8 || Reg == ARM::R9 ||

3128 ARM::DPRRegClass.contains(Reg);

3129 }),

3131 break;

3133

3134

3136 break;

3139 "ABI-required frame pointers need a CSR split when signing return "

3140 "address.");

3142 [=](const auto &CS) {

3144 return Reg != ARM::LR;

3145 }),

3147 break;

3148 default:

3149 llvm_unreachable("Unexpected CSR split with return address signing");

3150 }

3151 }

3152

3153 return false;

3154}

3155

3158 static const SpillSlot FixedSpillOffsets[] = {{ARM::FPCXTNS, -4}};

3159 NumEntries = std::size(FixedSpillOffsets);

3160 return FixedSpillOffsets;

3161}

3162

3171 unsigned Opc = I->getOpcode();

3172 bool IsDestroy = Opc == TII.getCallFrameDestroyOpcode();

3173 unsigned CalleePopAmount = IsDestroy ? I->getOperand(1).getImm() : 0;

3174

3176 "This eliminateCallFramePseudoInstr does not support Thumb1!");

3177

3178 int PIdx = I->findFirstPredOperandIdx();

3181 : (ARMCC::CondCodes)I->getOperand(PIdx).getImm();

3182 unsigned PredReg = TII.getFramePred(*I);

3183

3185

3186 if (IsDestroy && CalleePopAmount != -1U)

3187 return MBB.erase(I);

3188

3189

3190

3191

3192 unsigned Amount = TII.getFrameSize(*I);

3193 if (Amount != 0) {

3194

3195

3196

3198

3199 if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) {

3201 Pred, PredReg);

3202 } else {

3203 assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP);

3205 Pred, PredReg);

3206 }

3207 }

3208 } else if (CalleePopAmount != -1U) {

3209

3210

3213 }

3215}

3216

3217

3218

3219

3220

3222 unsigned Shifted = 0;

3223

3225 return 0;

3226

3227 while (!(Value & 0xC0000000)) {

3229 Shifted += 2;

3230 }

3231

3232 bool Carry = (Value & 0x00FFFFFF);

3233 Value = ((Value & 0xFF000000) >> 24) + Carry;

3234

3235 if (Value & 0x0000100)

3237

3238 if (Shifted > 24)

3240 else

3242

3244}

3245

3246

3247

3249

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3260

3261

3262

3263

3264

3265

3266

3267

3268

3269

3270

3271

3272

3273

3276 unsigned Opcode;

3278 bool Thumb = ST->isThumb();

3279 bool Thumb2 = ST->isThumb2();

3280

3281

3282

3284 report_fatal_error("Segmented stacks do not support vararg functions.");

3285 if (!ST->isTargetAndroid() && !ST->isTargetLinux())

3286 report_fatal_error("Segmented stacks not supported on this platform.");

3287

3293

3295 return;

3296

3298

3299

3300

3301 unsigned ScratchReg0 = ARM::R4;

3302 unsigned ScratchReg1 = ARM::R5;

3303 unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm;

3305

3311

3312

3315 WalkList.push_back(&PrologueMBB);

3316

3317 do {

3320 if (BeforePrologueRegion.insert(PredBB).second)

3322 }

3323 } while (!WalkList.empty());

3324

3325

3326

3327

3328

3329 MachineBasicBlock *AddedBlocks[] = {PrevStackMBB, McrMBB, GetMBB, AllocMBB,

3330 PostStackMBB};

3331

3332 BeforePrologueRegion.insert_range(AddedBlocks);

3333

3334 for (const auto &LI : PrologueMBB.liveins()) {

3336 PredBB->addLiveIn(LI);

3337 }

3338

3339

3340

3342 BeforePrologueRegion.erase(B);

3344 }

3345

3347

3348 MBB->sortUniqueLiveIns();

3349

3350

3351 if (MBB->isSuccessor(&PrologueMBB))

3352 MBB->ReplaceUsesOfBlockWith(&PrologueMBB, AddedBlocks[0]);

3353 }

3354

3355

3357

3358

3359

3361

3362

3363

3364

3365

3366

3367

3368

3369 if (Thumb) {

3370 BuildMI(PrevStackMBB, DL, TII.get(ARM::tPUSH))

3372 .addReg(ScratchReg0)

3373 .addReg(ScratchReg1);

3374 } else {

3375 BuildMI(PrevStackMBB, DL, TII.get(ARM::STMDB_UPD))

3379 .addReg(ScratchReg0)

3380 .addReg(ScratchReg1);

3381 }

3382

3383

3384

3388 CFIBuilder.buildOffset(ScratchReg1, -4);

3389 CFIBuilder.buildOffset(ScratchReg0, -8);

3390 }

3391

3392

3393 if (Thumb) {

3394 BuildMI(McrMBB, DL, TII.get(ARM::tMOVr), ScratchReg1)

3397 } else if (CompareStackPointer) {

3398 BuildMI(McrMBB, DL, TII.get(ARM::MOVr), ScratchReg1)

3402 }

3403

3404

3405 if (!CompareStackPointer && Thumb) {

3406 if (AlignedStackSize < 256) {

3407 BuildMI(McrMBB, DL, TII.get(ARM::tSUBi8), ScratchReg1)

3409 .addReg(ScratchReg1)

3410 .addImm(AlignedStackSize)

3412 } else {

3413 if (Thumb2 || ST->genExecuteOnly()) {

3414 BuildMI(McrMBB, DL, TII.get(MovOp), ScratchReg0)

3415 .addImm(AlignedStackSize);

3416 } else {

3417 auto MBBI = McrMBB->end();

3418 auto RegInfo = STI.getRegisterInfo();

3419 RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,

3420 AlignedStackSize);

3421 }

3422 BuildMI(McrMBB, DL, TII.get(ARM::tSUBrr), ScratchReg1)

3424 .addReg(ScratchReg1)

3425 .addReg(ScratchReg0)

3427 }

3428 } else if (!CompareStackPointer) {

3429 if (AlignedStackSize < 256) {

3430 BuildMI(McrMBB, DL, TII.get(ARM::SUBri), ScratchReg1)

3432 .addImm(AlignedStackSize)

3435 } else {

3436 auto MBBI = McrMBB->end();

3437 auto RegInfo = STI.getRegisterInfo();

3438 RegInfo->emitLoadConstPool(*McrMBB, MBBI, DL, ScratchReg0, 0,

3439 AlignedStackSize);

3440 BuildMI(McrMBB, DL, TII.get(ARM::SUBrr), ScratchReg1)

3442 .addReg(ScratchReg0)

3445 }

3446 }

3447

3448 if (Thumb && ST->isThumb1Only()) {

3449 if (ST->genExecuteOnly()) {

3450 BuildMI(GetMBB, DL, TII.get(MovOp), ScratchReg0)

3452 } else {

3458

3459

3460 BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0)

3463 }

3464

3465

3466 BuildMI(GetMBB, DL, TII.get(ARM::tLDRi), ScratchReg0)

3467 .addReg(ScratchReg0)

3470 } else {

3471

3472

3473 BuildMI(McrMBB, DL, TII.get(Thumb ? ARM::t2MRC : ARM::MRC),

3474 ScratchReg0)

3481

3482

3483 assert(ST->isTargetAndroid() || ST->isTargetLinux());

3484 unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;

3485

3486

3487

3488 BuildMI(GetMBB, DL, TII.get(Thumb ? ARM::t2LDRi12 : ARM::LDRi12),

3489 ScratchReg0)

3490 .addReg(ScratchReg0)

3491 .addImm(4 * TlsOffset)

3493 }

3494

3495

3496

3497 Opcode = Thumb ? ARM::tCMPr : ARM::CMPrr;

3499 .addReg(ScratchReg0)

3500 .addReg(ScratchReg1)

3502

3503

3504 Opcode = Thumb ? ARM::tBcc : ARM::Bcc;

3506 .addMBB(PostStackMBB)

3509

3510

3511

3512

3513

3514

3515

3516 if (Thumb) {

3517 if (AlignedStackSize < 256) {

3518 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg0)

3520 .addImm(AlignedStackSize)

3522 } else {

3523 if (Thumb2 || ST->genExecuteOnly()) {

3524 BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg0)

3525 .addImm(AlignedStackSize);

3526 } else {

3527 auto MBBI = AllocMBB->end();

3528 auto RegInfo = STI.getRegisterInfo();

3529 RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,

3530 AlignedStackSize);

3531 }

3532 }

3533 } else {

3534 if (AlignedStackSize < 256) {

3535 BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg0)

3536 .addImm(AlignedStackSize)

3539 } else {

3540 auto MBBI = AllocMBB->end();

3541 auto RegInfo = STI.getRegisterInfo();

3542 RegInfo->emitLoadConstPool(*AllocMBB, MBBI, DL, ScratchReg0, 0,

3543 AlignedStackSize);

3544 }

3545 }

3546

3547

3548

3549 if (Thumb) {

3551 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVi8), ScratchReg1)

3555 } else {

3556 if (Thumb2 || ST->genExecuteOnly()) {

3557 BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg1)

3559 } else {

3560 auto MBBI = AllocMBB->end();

3561 auto RegInfo = STI.getRegisterInfo();

3562 RegInfo->emitLoadConstPool(

3563 *AllocMBB, MBBI, DL, ScratchReg1, 0,

3565 }

3566 }

3567 } else {

3569 BuildMI(AllocMBB, DL, TII.get(ARM::MOVi), ScratchReg1)

3573 } else {

3574 auto MBBI = AllocMBB->end();

3575 auto RegInfo = STI.getRegisterInfo();

3576 RegInfo->emitLoadConstPool(

3577 *AllocMBB, MBBI, DL, ScratchReg1, 0,

3579 }

3580 }

3581

3582

3583 if (Thumb) {

3587 } else {

3588 BuildMI(AllocMBB, DL, TII.get(ARM::STMDB_UPD))

3593 }

3594

3595

3596

3601 }

3602

3603

3604 if (Thumb) {

3608 } else {

3611 }

3612

3613

3614 if (Thumb) {

3615 if (ST->isThumb1Only()) {

3618 .addReg(ScratchReg0);

3619 BuildMI(AllocMBB, DL, TII.get(ARM::tMOVr), ARM::LR)

3620 .addReg(ScratchReg0)

3622 } else {

3623 BuildMI(AllocMBB, DL, TII.get(ARM::t2LDR_POST))

3629 }

3630 } else {

3631 BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))

3636 }

3637

3638

3639

3640

3641

3642 if (Thumb) {

3645 .addReg(ScratchReg0)

3646 .addReg(ScratchReg1);

3647 } else {

3648 BuildMI(AllocMBB, DL, TII.get(ARM::LDMIA_UPD))

3652 .addReg(ScratchReg0)

3653 .addReg(ScratchReg1);

3654 }

3655

3656

3659

3660

3662

3663

3664

3665 if (Thumb) {

3666 BuildMI(PostStackMBB, DL, TII.get(ARM::tPOP))

3668 .addReg(ScratchReg0)

3669 .addReg(ScratchReg1);

3670 } else {

3671 BuildMI(PostStackMBB, DL, TII.get(ARM::LDMIA_UPD))

3675 .addReg(ScratchReg0)

3676 .addReg(ScratchReg1);

3677 }

3678

3679

3683

3684

3685

3688 }

3689

3690

3692

3694

3697

3699

3701

3702#ifdef EXPENSIVE_CHECKS

3704#endif

3705}

unsigned const MachineRegisterInfo * MRI

static unsigned estimateRSStackSizeLimit(MachineFunction &MF)

Look at each instruction that references stack frames and return the stack size limit beyond which so...

static bool needsWinCFI(const MachineFunction *MF)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static bool isThumb(const MCSubtargetInfo &STI)

static MachineBasicBlock::iterator skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs)

Skip past the code inserted by emitAlignedDPRCS2Spills, and return an iterator to the following instr...

Definition ARMFrameLowering.cpp:2082

static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI, const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const unsigned Reg, const Align Alignment, const bool MustBeSingleInstruction)

Emit an instruction sequence that will align the address in register Reg by zero-ing out the lower bi...

Definition ARMFrameLowering.cpp:796

static uint32_t alignToARMConstant(uint32_t Value)

Get the minimum constant for ARM that is greater than or equal to the argument.

Definition ARMFrameLowering.cpp:3221

static void checkNumAlignedDPRCS2Regs(MachineFunction &MF, BitVector &SavedRegs)

Definition ARMFrameLowering.cpp:2423

static void insertSEHRange(MachineBasicBlock &MBB, MachineBasicBlock::iterator Start, const MachineBasicBlock::iterator &End, const ARMBaseInstrInfo &TII, unsigned MIFlags)

Definition ARMFrameLowering.cpp:649

static void emitAlignedDPRCS2Restores(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)

Emit aligned reload instructions for NumAlignedDPRCS2Regs D-registers starting from d8.

Definition ARMFrameLowering.cpp:2112

static void emitAlignedDPRCS2Spills(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned NumAlignedDPRCS2Regs, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI)

Emit aligned spill instructions for NumAlignedDPRCS2Regs D-registers starting from d8.

Definition ARMFrameLowering.cpp:1939

static int getArgumentStackToRestore(MachineFunction &MF, MachineBasicBlock &MBB)

Definition ARMFrameLowering.cpp:390

static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)

Definition ARMFrameLowering.cpp:686

static unsigned EstimateFunctionSizeInBytes(const MachineFunction &MF, const ARMBaseInstrInfo &TII)

Definition ARMFrameLowering.cpp:2321

static MachineBasicBlock::iterator insertSEH(MachineBasicBlock::iterator MBBI, const TargetInstrInfo &TII, unsigned Flags)

Definition ARMFrameLowering.cpp:429

SpillArea getSpillArea(Register Reg, ARMSubtarget::PushPopSplitVariation Variation, unsigned NumAlignedDPRCS2Regs, const ARMBaseRegisterInfo *RegInfo)

Get the spill area that Reg should be saved into in the prologue.

Definition ARMFrameLowering.cpp:183

static bool canSpillOnFrameIndexAccess(const MachineFunction &MF, const TargetFrameLowering &TFI)

Definition ARMFrameLowering.cpp:2492

static bool WindowsRequiresStackProbe(const MachineFunction &MF, size_t StackSizeInBytes)

Definition ARMFrameLowering.cpp:721

static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI, const MachineFunction &MF)

We need the offset of the frame pointer relative to other MachineFrameInfo offsets which are encoded ...

Definition ARMFrameLowering.cpp:862

static MachineBasicBlock::iterator initMBBRange(MachineBasicBlock &MBB, const MachineBasicBlock::iterator &MBBI)

Definition ARMFrameLowering.cpp:643

static int sizeOfSPAdjustment(const MachineInstr &MI)

Definition ARMFrameLowering.cpp:696

static const uint64_t kSplitStackAvailable

Definition ARMFrameLowering.cpp:3248

SpillArea

Definition ARMFrameLowering.cpp:172

@ FPCXT

Definition ARMFrameLowering.cpp:179

@ GPRCS3

Definition ARMFrameLowering.cpp:178

@ DPRCS1

Definition ARMFrameLowering.cpp:176

@ DPRCS2

Definition ARMFrameLowering.cpp:177

@ GPRCS2

Definition ARMFrameLowering.cpp:174

@ GPRCS1

Definition ARMFrameLowering.cpp:173

@ FPStatus

Definition ARMFrameLowering.cpp:175

static cl::opt< bool > SpillAlignedNEONRegs("align-neon-spills", cl::Hidden, cl::init(true), cl::desc("Align ARM NEON spills in prolog and epilog"))

static void emitRegPlusImmediate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, const ARMBaseInstrInfo &TII, unsigned DestReg, unsigned SrcReg, int NumBytes, unsigned MIFlags=MachineInstr::NoFlags, ARMCC::CondCodes Pred=ARMCC::AL, unsigned PredReg=0)

Definition ARMFrameLowering.cpp:673

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

This file contains the simple types necessary to represent the attributes associated with functions a...

This file implements the BitVector class.

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Analysis containing CSE Info

const size_t AbstractManglingParser< Derived, Alloc >::NumOps

This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...

Register const TargetRegisterInfo * TRI

Promote Memory to Register

This file declares the machine register scavenger class.

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

static const unsigned FramePtr

bool canRealignStack(const MachineFunction &MF) const override

static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)

ARMConstantPoolValue - ARM specific constantpool value.

bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override

restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...

Definition ARMFrameLowering.cpp:2268

StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override

getFrameIndexReference - Provide a base+offset reference to an FI slot for debug info.

Definition ARMFrameLowering.cpp:1563

bool keepFramePointer(const MachineFunction &MF) const

Definition ARMFrameLowering.cpp:313

static void updateLRRestored(MachineFunction &MF)

Update the IsRestored flag on LR if it is spilled, based on the return instructions.

Definition ARMFrameLowering.cpp:3058

void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override

emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.

Definition ARMFrameLowering.cpp:885

ARMFrameLowering(const ARMSubtarget &sti)

Definition ARMFrameLowering.cpp:309

bool enableShrinkWrapping(const MachineFunction &MF) const override

Returns true if the target will correctly handle shrink wrapping.

Definition ARMFrameLowering.cpp:2466

void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override

Definition ARMFrameLowering.cpp:1393

bool requiresAAPCSFrameRecord(const MachineFunction &MF) const

Definition ARMFrameLowering.cpp:2483

bool isFPReserved(const MachineFunction &MF) const

isFPReserved - Return true if the frame pointer register should be considered a reserved register on ...

Definition ARMFrameLowering.cpp:354

bool canSimplifyCallFramePseudos(const MachineFunction &MF) const override

canSimplifyCallFramePseudos - If there is a reserved call frame, the call frame pseudos can be simpli...

Definition ARMFrameLowering.cpp:381

void adjustForSegmentedStacks(MachineFunction &MF, MachineBasicBlock &MBB) const override

Adjust the prologue to have the function use segmented stacks.

Definition ARMFrameLowering.cpp:3274

bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override

spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...

Definition ARMFrameLowering.cpp:2202

bool hasReservedCallFrame(const MachineFunction &MF) const override

hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...

Definition ARMFrameLowering.cpp:363

const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override

getCalleeSavedSpillSlots - This method returns a pointer to an array of pairs, that contains an entry...

Definition ARMFrameLowering.cpp:3157

void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override

processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...

Definition ARMFrameLowering.cpp:3082

bool hasFPImpl(const MachineFunction &MF) const override

hasFPImpl - Return true if the specified function should have a dedicated frame pointer register.

Definition ARMFrameLowering.cpp:335

int ResolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, int SPAdj) const

Definition ARMFrameLowering.cpp:1569

void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const override

Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.

Definition ARMFrameLowering.cpp:3088

void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override

This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...

Definition ARMFrameLowering.cpp:2513

bool enableCalleeSaveSkip(const MachineFunction &MF) const override

Returns true if the target can safely skip saving callee-saved registers for noreturn nounwind functi...

Definition ARMFrameLowering.cpp:322

bool assignCalleeSavedSpillSlots(MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector< CalleeSavedInfo > &CSI) const override

assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.

Definition ARMFrameLowering.cpp:3100

ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...

bool hasStackFrame() const

bool isThumb2Function() const

unsigned getFPCXTSaveAreaSize() const

unsigned getGPRCalleeSavedArea1Size() const

unsigned getDPRCalleeSavedGapSize() const

unsigned getDPRCalleeSavedArea1Size() const

unsigned createPICLabelUId()

void setLRIsSpilled(bool s)

void setDPRCalleeSavedArea1Offset(unsigned o)

void setGPRCalleeSavedArea2Size(unsigned s)

bool isThumb1OnlyFunction() const

void setHasStackFrame(bool s)

bool isThumbFunction() const

void setFramePtrSpillOffset(unsigned o)

unsigned getGPRCalleeSavedArea2Size() const

unsigned getNumAlignedDPRCS2Regs() const

bool shouldSignReturnAddress() const

void setGPRCalleeSavedArea1Size(unsigned s)

unsigned getArgumentStackToRestore() const

void setFPCXTSaveAreaSize(unsigned s)

bool isCmseNSEntryFunction() const

unsigned getGPRCalleeSavedArea3Size() const

unsigned getFramePtrSpillOffset() const

bool shouldRestoreSPFromFP() const

unsigned getArgRegsSaveSize() const

void setGPRCalleeSavedArea2Offset(unsigned o)

void setGPRCalleeSavedArea1Offset(unsigned o)

void setDPRCalleeSavedArea1Size(unsigned s)

void setDPRCalleeSavedGapSize(unsigned s)

void setFPStatusSavesSize(unsigned s)

unsigned getArgumentStackSize() const

void setShouldRestoreSPFromFP(bool s)

unsigned getReturnRegsCount() const

void setGPRCalleeSavedArea3Size(unsigned s)

bool getPreservesR0() const

unsigned getFPStatusSavesSize() const

const ARMBaseRegisterInfo * getRegisterInfo() const override

enum PushPopSplitVariation getPushPopSplitVariation(const MachineFunction &MF) const

PushPopSplitVariation

How the push and pop instructions of callee saved general-purpose registers should be split.

@ SplitR11WindowsSEH

When the stack frame size is not known (because of variable-sized objects or realignment),...

@ SplitR7

R7 and LR must be adjacent, because R7 is the frame pointer, and must point to a frame record consist...

@ SplitR11AAPCSSignRA

When generating AAPCS-compilant frame chains, R11 is the frame pointer, and must be pushed adjacent t...

@ NoSplit

All GPRs can be pushed in a single instruction.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

bool test(unsigned Idx) const

Helper class for creating CFI instructions and inserting them into MIR.

void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const

void buildDefCFARegister(MCRegister Reg) const

void buildSameValue(MCRegister Reg) const

void buildOffset(MCRegister Reg, int64_t Offset) const

void buildDefCFA(MCRegister Reg, int64_t Offset) const

The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...

CallingConv::ID getCallingConv() const

getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

bool isVarArg() const

isVarArg - Return true if this function takes a variable number of arguments.

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

bool usesWindowsCFI() const

Describe properties that are true of each instruction in the target description file.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

Wrapper class representing physical registers. Should be passed by value.

iterator_range< livein_iterator > liveins() const

LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())

Add Succ as a successor of this MachineBasicBlock.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

iterator_range< pred_iterator > predecessors()

MachineInstrBundleIterator< MachineInstr > iterator

The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...

const std::vector< MachineConstantPoolEntry > & getConstants() const

unsigned getConstantPoolIndex(const Constant *C, Align Alignment)

getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

bool needsSplitStackProlog() const

Return true if this function requires a split stack prolog, even if it uses no stack space.

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

uint64_t getStackSize() const

Return the number of bytes that must be allocated to hold all of the fixed size frame objects.

bool isReturnAddressTaken() const

This method may be called any time after instruction selection is complete to determine if there is a...

bool isFrameAddressTaken() const

This method may be called any time after instruction selection is complete to determine if there is a...

Align getMaxAlign() const

Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...

uint64_t getMaxCallFrameSize() const

Return the maximum size of a call frame that must be allocated for an outgoing function call.

int getStackProtectorIndex() const

Return the index for the stack protector object.

int64_t getOffsetAdjustment() const

Return the correction for frame offsets.

bool isCalleeSavedInfoValid() const

Has the callee saved info been calculated yet?

LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const

Return a set of physical registers that are pristine.

const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const

Returns a reference to call saved info vector for the current function.

int64_t getObjectOffset(int ObjectIdx) const

Return the assigned stack offset of the specified object from the incoming stack pointer.

bool isFixedObjectIndex(int ObjectIdx) const

Returns true if the specified index corresponds to a fixed stack object.

void setObjectAlignment(int ObjectIdx, Align Alignment)

setObjectAlignment - Change the alignment of the specified stack object.

void setOffsetAdjustment(int64_t Adj)

Set the correction for frame offsets.

void setHasWinCFI(bool v)

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

bool verify(Pass *p=nullptr, const char *Banner=nullptr, raw_ostream *OS=nullptr, bool AbortOnError=true) const

Run the current MachineFunction through the machine code verifier, useful for debugger use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineConstantPool * getConstantPool()

getConstantPool - Return the constant pool object for the current function.

const MachineJumpTableInfo * getJumpTableInfo() const

getJumpTableInfo - Return the jump table info object for the current function.

MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)

CreateMachineInstr - Allocate a new MachineInstr.

void insert(iterator MBBI, MachineBasicBlock *MBB)

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const

const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addFrameIndex(int Idx) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const

Copy all the implicit operands from OtherMI onto this one.

bool isValid() const

Check for null.

Representation of each machine instruction.

LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)

We have determined MI kills a register.

const std::vector< MachineJumpTableEntry > & getJumpTables() const

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

Register getReg() const

getReg - Returns the register number.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

LLVM_ABI bool isLiveIn(Register Reg) const

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

Wrapper class representing virtual and physical registers.

bool erase(PtrType Ptr)

Remove pointer from the set.

void insert_range(Range &&R)

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

iterator erase(const_iterator CI)

typename SuperClass::iterator iterator

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StackOffset holds a fixed and a scalable offset in bytes.

int64_t getFixed() const

Returns the fixed component of the stack.

Information about stack frame layout on the target.

unsigned getStackAlignment() const

getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...

bool hasFP(const MachineFunction &MF) const

hasFP - Return true if the specified function should have a dedicated frame pointer register.

virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const

This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...

virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const

processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...

virtual void getCalleeSaves(const MachineFunction &MF, BitVector &SavedRegs) const

Returns the callee-saved registers as computed by determineCalleeSaves in the BitVector SavedRegs.

TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)

Align getStackAlign() const

getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...

int alignSPAdjust(int SPAdj) const

alignSPAdjust - This method aligns the stack adjustment to the correct alignment.

virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const

getFrameIndexReference - This method should return the base register and offset used to reference a f...

TargetInstrInfo - Interface to description of machine instruction set.

Primary interface to the complete machine description for the target machine.

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

LLVM_ABI bool FramePointerIsReserved(const MachineFunction &MF) const

FramePointerIsReserved - This returns true if the frame pointer must always either point to a new fra...

LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const

DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...

bool contains(Register Reg) const

Return true if the specified register is included in this register class.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual const TargetFrameLowering * getFrameLowering() const

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

LLVM Value Representation.

An efficient, type-erasing, non-owning reference to a callable.

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)

unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)

@ D16

Only 16 D registers.

@ GHC

Used by the Glasgow Haskell Compiler (GHC).

@ C

The default llvm calling convention, compatible with C.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Define

Register definition.

@ Kill

The last use of a register.

initializer< Ty > init(const Ty &Val)

NodeAddr< FuncNode * > Func

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

static bool isARMLowRegister(MCRegister Reg)

isARMLowRegister - Returns true if the register is a low register (r0-r7).

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

static bool isSEHInstruction(const MachineInstr &MI)

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)

Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...

auto reverse(ContainerTy &&C)

MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

unsigned getDefRegState(bool B)

unsigned getKillRegState(bool B)

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

FunctionAddr VTableAddr Next

auto count(R &&Range, const E &Element)

Wrapper function around std::count to count the number of times an element Element occurs in the give...

DWARFExpression::Operation Op

static MachineOperand t1CondCodeOp(bool isDead=false)

Get the operand corresponding to the conditional code result for Thumb1.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

static MachineOperand condCodeOp(unsigned CCReg=0)

Get the operand corresponding to the conditional code result.

unsigned Log2(Align A)

Returns the log2 of the alignment.

void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)

emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.

void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)

This struct is a compact representation of a valid (non-zero power of two) alignment.

constexpr uint64_t value() const

This is a hole in the type system and should not be abused.