LLVM: lib/Target/Hexagon/HexagonFrameLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

55#include

56#include

57#include

58#include

59#include

60#include

61#include

62#include

63#include

64

65#define DEBUG_TYPE "hexagon-pei"

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

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149using namespace llvm;

150

153

156 cl::desc("Set the number of scavenger slots"),

158

161 cl::desc("Specify O2(not Os) spill func threshold"),

163

166 cl::desc("Specify Os spill func threshold"),

168

170 "enable-stackovf-sanitizer", cl::Hidden,

171 cl::desc("Enable runtime checks for stack overflow."), cl::init(false));

172

175 cl::desc("Enable stack frame shrink wrapping"));

176

180 cl::desc("Max count of stack frame shrink-wraps"));

181

184 cl::desc("Enable long calls for save-restore stubs."),

186

189

192

193#ifndef NDEBUG

195 cl::init(std::numeric_limits::max()));

197#endif

198

199namespace {

200

202 public:

203 static char ID;

204

206

208

211 }

212 };

213

214 char HexagonCallFrameInformation::ID = 0;

215

216}

217

218bool HexagonCallFrameInformation::runOnMachineFunction(MachineFunction &MF) {

219 auto &HFI = *MF.getSubtarget().getFrameLowering();

221

222 if (!NeedCFI)

223 return false;

224 HFI.insertCFIInstructions(MF);

225 return true;

226}

227

229 "Hexagon call frame information", false, false)

230

232 return new HexagonCallFrameInformation();

233}

234

235

236

239 bool hireg = true) {

241 return Reg;

242

245 if (hireg) {

248 } else {

249 if (!RegNo || SubReg < RegNo)

251 }

252 }

253 return RegNo;

254}

255

256

259 static_assert(Hexagon::R1 > 0,

260 "Assume physical registers are encoded as positive integers");

262 return 0;

263

265 for (unsigned I = 1, E = CSI.size(); I < E; ++I) {

267 if (Reg > Max)

268 Max = Reg;

269 }

270 return Max;

271}

272

273

274

278 if (MI.isCall())

279 return true;

280 unsigned Opc = MI.getOpcode();

281 switch (Opc) {

282 case Hexagon::PS_alloca:

283 case Hexagon::PS_aligna:

284 return true;

285 default:

286 break;

287 }

288

290

291

292

293

294

295 if (MO.isFI())

296 return true;

297 if (MO.isReg()) {

299

300 if (!R)

301 continue;

302

303

304 if (R.isVirtual())

305 return true;

306 for (MCPhysReg S : HRI.subregs_inclusive(R))

307 if (CSR[S])

308 return true;

309 continue;

310 }

311 if (MO.isRegMask()) {

312

313

314

315

316 const uint32_t *BM = MO.getRegMask();

318 unsigned R = x;

319

320 if (!(BM[R/32] & (1u << (R%32))))

321 return true;

322 }

323 }

324 }

325 }

326 return false;

327}

328

329

330

333 if (I == MBB.end())

334 return false;

335 unsigned RetOpc = I->getOpcode();

336 return RetOpc == Hexagon::PS_tailcall_i || RetOpc == Hexagon::PS_tailcall_r;

337}

338

339

342 if (MI.isReturn())

343 return true;

344 return false;

345}

346

347

348

350 for (auto &I : MBB)

351 if (I.isReturn())

352 return &I;

353 return nullptr;

354}

355

357 switch (Opc) {

358 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:

359 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:

360 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT:

361 case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC:

362 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT:

363 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC:

364 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:

365 case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:

366 return true;

367 }

368 return false;

369}

370

375

378 return F.hasOptSize() && F.hasMinSize();

379}

380

384

385

386

387

388

389void HexagonFrameLowering::findShrunkPrologEpilog(MachineFunction &MF,

390 MachineBasicBlock *&PrologB, MachineBasicBlock *&EpilogB) const {

391 static unsigned ShrinkCounter = 0;

392

393 if (MF.getSubtarget().isEnvironmentMusl() &&

395 return;

398 return;

399 ShrinkCounter++;

400 }

401

402 auto &HRI = *MF.getSubtarget().getRegisterInfo();

403

404 MachineDominatorTree MDT;

406 MachinePostDominatorTree MPT;

408

409 using UnsignedMap = DenseMap<unsigned, unsigned>;

410 using RPOTType = ReversePostOrderTraversal<const MachineFunction *>;

411

412 UnsignedMap RPO;

413 RPOTType RPOT(&MF);

414 unsigned RPON = 0;

415 for (auto &I : RPOT)

416 RPO[I->getNumber()] = RPON++;

417

418

419

420

421 for (auto &I : MF) {

422 unsigned BN = RPO[I.getNumber()];

423 for (MachineBasicBlock *Succ : I.successors())

424

425 if (RPO[Succ->getNumber()] <= BN)

426 return;

427 }

428

429

430

432 BitVector CSR(Hexagon::NUM_TARGET_REGS);

433 for (const MCPhysReg *P = HRI.getCalleeSavedRegs(&MF); *P; ++P)

434 for (MCPhysReg S : HRI.subregs_inclusive(*P))

435 CSR[S] = true;

436

437 for (auto &I : MF)

440

442 dbgs() << "Blocks needing SF: {";

443 for (auto &B : SFBlocks)

445 dbgs() << " }\n";

446 });

447

448 if (SFBlocks.empty())

449 return;

450

451

452 MachineBasicBlock *DomB = SFBlocks[0];

453 for (unsigned i = 1, n = SFBlocks.size(); i < n; ++i) {

455 if (!DomB)

456 break;

457 }

458 MachineBasicBlock *PDomB = SFBlocks[0];

459 for (unsigned i = 1, n = SFBlocks.size(); i < n; ++i) {

461 if (!PDomB)

462 break;

463 }

465 dbgs() << "Computed dom block: ";

466 if (DomB)

468 else

469 dbgs() << "";

470 dbgs() << ", computed pdom block: ";

471 if (PDomB)

473 else

474 dbgs() << "";

475 dbgs() << "\n";

476 });

477 if (!DomB || !PDomB)

478 return;

479

480

481 if (!MDT.dominates(DomB, PDomB)) {

482 LLVM_DEBUG(dbgs() << "Dom block does not dominate pdom block\n");

483 return;

484 }

485 if (!MPT.dominates(PDomB, DomB)) {

486 LLVM_DEBUG(dbgs() << "PDom block does not post-dominate dom block\n");

487 return;

488 }

489

490

491 PrologB = DomB;

492 EpilogB = PDomB;

493}

494

495

496

497

498

499

503

506

509 findShrunkPrologEpilog(MF, PrologB, EpilogB);

510

511 bool PrologueStubs = false;

512 insertCSRSpillsInBlock(*PrologB, CSI, HRI, PrologueStubs);

513 insertPrologueInBlock(*PrologB, PrologueStubs);

514 updateEntryPaths(MF, *PrologB);

515

516 if (EpilogB) {

517 insertCSRRestoresInBlock(*EpilogB, CSI, HRI);

518 insertEpilogueInBlock(*EpilogB);

519 } else {

520 for (auto &B : MF)

521 if (B.isReturnBlock())

522 insertCSRRestoresInBlock(B, CSI, HRI);

523

524 for (auto &B : MF)

525 if (B.isReturnBlock())

526 insertEpilogueInBlock(B);

527

528 for (auto &B : MF) {

529 if (B.empty())

530 continue;

533 continue;

534 for (auto &R : CSI)

536 }

537 }

538

539 if (EpilogB) {

540

541

542

544 BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);

545 updateExitPaths(*EpilogB, *EpilogB, DoneT, DoneF, Path);

546 }

547}

548

549

550

554 assert(F.hasFnAttribute(Attribute::NoReturn) &&

555 F.getFunction().hasFnAttribute(Attribute::NoUnwind) &&

556 F.getFunction().hasFnAttribute(Attribute::UWTable));

557 (void)F;

558

559

561}

562

563

564

565

566

567

572 assert(!MFI.hasVarSizedObjects() &&

573 !HST.getRegisterInfo()->hasStackRealignment(MF));

574 return F.hasFnAttribute(Attribute::NoReturn) &&

575 F.hasFnAttribute(Attribute::NoUnwind) &&

576 F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() &&

577 MFI.getStackSize() == 0;

578}

579

580void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB,

581 bool PrologueStubs) const {

584 auto &HST = MF.getSubtarget();

587

588 Align MaxAlign = std::max(MFI.getMaxAlign(), getStackAlign());

589

590

591

593

596

597 FrameSize = MaxCFA + alignTo(FrameSize, MaxAlign);

599

600 bool AlignStack = (MaxAlign > getStackAlign());

601

602

604 Register SP = HRI.getStackRegister();

607

608 SmallVector<MachineInstr *, 4> AdjustRegs;

609 for (auto &MBB : MF)

610 for (auto &MI : MBB)

611 if (MI.getOpcode() == Hexagon::PS_alloca)

613

614 for (auto *MI : AdjustRegs) {

615 assert((MI->getOpcode() == Hexagon::PS_alloca) && "Expected alloca");

616 expandAlloca(MI, HII, SP, MaxCF);

617 MI->eraseFromParent();

618 }

619

621

622 if (MF.getFunction().isVarArg() &&

623 MF.getSubtarget().isEnvironmentMusl()) {

624

625 int NumVarArgRegs = 6 - FirstVarArgSavedReg;

626 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0)

627 ? NumVarArgRegs * 4

628 : NumVarArgRegs * 4 + 4;

629 if (RegisterSavedAreaSizePlusPadding > 0) {

630

631

632 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)

634 .addImm(-RegisterSavedAreaSizePlusPadding)

636

637 int NumBytes = 0;

638

639 auto &HMFI = *MF.getInfo();

640 for (int i = HMFI.getFirstNamedArgFrameIndex(),

641 e = HMFI.getLastNamedArgFrameIndex(); i >= e; --i) {

644

645

646 unsigned LDOpc, STOpc;

647 uint64_t OpcodeChecker = ObjAlign.value();

648

649

650 if (ObjAlign > ObjSize) {

651 if (ObjSize <= 1)

652 OpcodeChecker = 1;

653 else if (ObjSize <= 2)

654 OpcodeChecker = 2;

655 else if (ObjSize <= 4)

656 OpcodeChecker = 4;

657 else if (ObjSize > 4)

658 OpcodeChecker = 8;

659 }

660

661 switch (OpcodeChecker) {

662 case 1:

663 LDOpc = Hexagon::L2_loadrb_io;

664 STOpc = Hexagon::S2_storerb_io;

665 break;

666 case 2:

667 LDOpc = Hexagon::L2_loadrh_io;

668 STOpc = Hexagon::S2_storerh_io;

669 break;

670 case 4:

671 LDOpc = Hexagon::L2_loadri_io;

672 STOpc = Hexagon::S2_storeri_io;

673 break;

674 case 8:

675 default:

676 LDOpc = Hexagon::L2_loadrd_io;

677 STOpc = Hexagon::S2_storerd_io;

678 break;

679 }

680

681 Register RegUsed = LDOpc == Hexagon::L2_loadrd_io ? Hexagon::D3

682 : Hexagon::R6;

683 int LoadStoreCount = ObjSize / OpcodeChecker;

684

685 if (ObjSize % OpcodeChecker)

686 ++LoadStoreCount;

687

688

689

690

691

692 if (NumBytes != 0)

693 NumBytes = alignTo(NumBytes, ObjAlign);

694

696 while (Count < LoadStoreCount) {

697

698 BuildMI(MBB, InsertPt, dl, HII.get(LDOpc), RegUsed)

700 .addImm(RegisterSavedAreaSizePlusPadding +

703

704

705 BuildMI(MBB, InsertPt, dl, HII.get(STOpc))

710

712 }

714 }

715

716

717 NumBytes = alignTo(NumBytes, 8);

718

719

720

721

722 NumBytes = (NumVarArgRegs % 2 == 0) ? NumBytes : NumBytes + 4;

723

724 for (int j = FirstVarArgSavedReg, i = 0; j < 6; ++j, ++i) {

725 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_storeri_io))

727 .addImm(NumBytes + 4 * i)

728 .addReg(Hexagon::R0 + j)

730 }

731 }

732 }

733

734 if (hasFP(MF)) {

735 insertAllocframe(MBB, InsertPt, NumBytes);

736 if (AlignStack) {

737 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_andir), SP)

740 }

741

742

743

745 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::PS_call_stk))

747 } else if (NumBytes > 0) {

749 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)

751 .addImm(-int(NumBytes));

752 }

753}

754

755void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {

757 auto &HST = MF.getSubtarget();

760 Register SP = HRI.getStackRegister();

761

764

765 if (!hasFP(MF)) {

769 MF.getSubtarget().isEnvironmentMusl()) {

770

771 int NumVarArgRegs = 6 - FirstVarArgSavedReg;

772 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?

773 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);

774 NumBytes += RegisterSavedAreaSizePlusPadding;

775 }

776 if (NumBytes) {

777 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)

780 }

781 return;

782 }

783

785 unsigned RetOpc = RetI ? RetI->getOpcode() : 0;

786

787

788 if (RetOpc == Hexagon::EH_RETURN_JMPR) {

789 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))

790 .addDef(Hexagon::D15)

791 .addReg(Hexagon::R30);

792 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_add), SP)

794 .addReg(Hexagon::R28);

795 return;

796 }

797

798

799

800 if (RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4 ||

801 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC ||

802 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT ||

803 RetOpc == Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC) {

805 ++It;

806

807 while (It != MBB.end()) {

808 if (!It->isLabel())

810 else

811 ++It;

812 }

813 return;

814 }

815

816

817

818

819 bool NeedsDeallocframe = true;

822 unsigned COpc = PrevIt->getOpcode();

823 if (COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 ||

824 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC ||

825 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT ||

826 COpc == Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC ||

827 COpc == Hexagon::PS_call_nr || COpc == Hexagon::PS_callr_nr)

828 NeedsDeallocframe = false;

829 }

830

831 if (!MF.getSubtarget().isEnvironmentMusl() ||

833 if (!NeedsDeallocframe)

834 return;

835

836

837

839 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))

840 .addDef(Hexagon::D15)

841 .addReg(Hexagon::R30);

842 return;

843 }

844 unsigned NewOpc = Hexagon::L4_return;

845 MachineInstr *NewI = BuildMI(MBB, RetI, dl, HII.get(NewOpc))

846 .addDef(Hexagon::D15)

847 .addReg(Hexagon::R30);

848

851 } else {

852

853

854 int NumVarArgRegs = 6 - FirstVarArgSavedReg;

855 int RegisterSavedAreaSizePlusPadding = (NumVarArgRegs % 2 == 0) ?

856 (NumVarArgRegs * 4) : (NumVarArgRegs * 4 + 4);

857

860 : std::prev(Term);

862 (I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT &&

863 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC &&

864 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4 &&

865 I->getOpcode() != Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC))

866 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::L2_deallocframe))

867 .addDef(Hexagon::D15)

868 .addReg(Hexagon::R30);

869 if (RegisterSavedAreaSizePlusPadding != 0)

870 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)

872 .addImm(RegisterSavedAreaSizePlusPadding);

873 }

874}

875

876void HexagonFrameLowering::insertAllocframe(MachineBasicBlock &MBB,

879 auto &HST = MF.getSubtarget();

882

883

884

885 const unsigned int ALLOCFRAME_MAX = 16384;

886

887

888

891

893 Register SP = HRI.getStackRegister();

894

895 if (NumBytes >= ALLOCFRAME_MAX) {

896

897 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))

903

904

905 Register SP = HRI.getStackRegister();

906 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::A2_addi), SP)

908 .addImm(-int(NumBytes))

910 } else {

911 BuildMI(MBB, InsertPt, dl, HII.get(Hexagon::S2_allocframe))

917 }

918}

919

920void HexagonFrameLowering::updateEntryPaths(MachineFunction &MF,

921 MachineBasicBlock &SaveB) const {

922 SetVector Worklist;

923

924 MachineBasicBlock &EntryB = MF.front();

926

927 unsigned SaveN = SaveB.getNumber();

929

930 for (unsigned i = 0; i < Worklist.size(); ++i) {

931 unsigned BN = Worklist[i];

933 for (auto &R : CSI)

936 if (BN != SaveN)

938 Worklist.insert(SB->getNumber());

939 }

940}

941

942bool HexagonFrameLowering::updateExitPaths(MachineBasicBlock &MBB,

943 MachineBasicBlock &RestoreB, BitVector &DoneT, BitVector &DoneF,

944 BitVector &Path) const {

947 if (Path[BN] || DoneF[BN])

948 return false;

949 if (DoneT[BN])

950 return true;

951

953

954 Path[BN] = true;

955 bool ReachedExit = false;

957 ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);

958

960

961

962

963 MachineInstr &RetI = MBB.back();

965 for (auto &R : CSI)

967 ReachedExit = true;

968 }

969

970

971

972

973 if (ReachedExit && &MBB != &RestoreB) {

974 for (auto &R : CSI)

977 DoneT[BN] = true;

978 }

979 if (!ReachedExit)

980 DoneF[BN] = true;

981

982 Path[BN] = false;

983 return ReachedExit;

984}

985

986static std::optionalMachineBasicBlock::iterator

988

989

990

991

992

993 auto End = B.instr_end();

994

997 if (I.isBundle()) {

998 if (I.getOpcode() == Hexagon::S2_allocframe)

999 return std::next(It);

1000 continue;

1001 }

1002

1003 bool HasCall = false, HasAllocFrame = false;

1005 while (++T != End && T->isBundled()) {

1006 if (T->getOpcode() == Hexagon::S2_allocframe)

1007 HasAllocFrame = true;

1008 else if (T->isCall())

1009 HasCall = true;

1010 }

1011 if (HasAllocFrame)

1012 return HasCall ? It : std::next(It);

1013 }

1014 return std::nullopt;

1015}

1016

1018 for (auto &B : MF)

1020 insertCFIInstructionsAt(B, *At);

1021}

1022

1030

1031

1032

1033

1035 const MCInstrDesc &CFID = HII.get(TargetOpcode::CFI_INSTRUCTION);

1036

1038 bool HasFP = hasFP(MF);

1039

1040 if (HasFP) {

1041 unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(), true);

1042 unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(), true);

1043

1044

1045

1046

1047

1048

1049

1050

1051

1052

1053

1054

1058

1062

1066 }

1067

1068 static const MCPhysReg RegsToMove[] = {

1069 Hexagon::R1, Hexagon::R0, Hexagon::R3, Hexagon::R2,

1070 Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,

1071 Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,

1072 Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,

1073 Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9,

1074 Hexagon::D10, Hexagon::D11, Hexagon::D12, Hexagon::D13

1075 };

1076

1078

1080 auto IfR = [Reg] (const CalleeSavedInfo &C) -> bool {

1081 return C.getReg() == Reg;

1082 };

1084 if (F == CSI.end())

1085 continue;

1086

1088 if (HasFP) {

1089

1090

1091

1092

1093

1094

1095

1097 } else {

1100 getFrameIndexReference(MF, F->getFrameIdx(), FrameReg).getFixed();

1101 }

1102

1104

1106 unsigned DwarfReg = HRI.getDwarfRegNum(Reg, true);

1111 } else {

1112

1113

1114

1115

1116

1117

1118 Register HiReg = HRI.getSubReg(Reg, Hexagon::isub_hi);

1119 Register LoReg = HRI.getSubReg(Reg, Hexagon::isub_lo);

1120 unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg, true);

1121 unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg, true);

1130 }

1131 }

1132}

1133

1137 bool HasExtraAlign = HRI.hasStackRealignment(MF);

1139

1140

1141

1142

1143

1144

1146 return true;

1147

1148

1149

1150

1151

1152

1153 if (HasAlloca || HasExtraAlign)

1154 return true;

1155

1157

1160 return true;

1162 return true;

1163 }

1164

1167 return true;

1168

1169 return false;

1170}

1171

1177

1179 bool Stkchk = false) {

1180 const char * V4SpillToMemoryFunctions[] = {

1181 "__save_r16_through_r17",

1182 "__save_r16_through_r19",

1183 "__save_r16_through_r21",

1184 "__save_r16_through_r23",

1185 "__save_r16_through_r25",

1186 "__save_r16_through_r27" };

1187

1188 const char * V4SpillToMemoryStkchkFunctions[] = {

1189 "__save_r16_through_r17_stkchk",

1190 "__save_r16_through_r19_stkchk",

1191 "__save_r16_through_r21_stkchk",

1192 "__save_r16_through_r23_stkchk",

1193 "__save_r16_through_r25_stkchk",

1194 "__save_r16_through_r27_stkchk" };

1195

1196 const char * V4SpillFromMemoryFunctions[] = {

1197 "__restore_r16_through_r17_and_deallocframe",

1198 "__restore_r16_through_r19_and_deallocframe",

1199 "__restore_r16_through_r21_and_deallocframe",

1200 "__restore_r16_through_r23_and_deallocframe",

1201 "__restore_r16_through_r25_and_deallocframe",

1202 "__restore_r16_through_r27_and_deallocframe" };

1203

1204 const char * V4SpillFromMemoryTailcallFunctions[] = {

1205 "__restore_r16_through_r17_and_deallocframe_before_tailcall",

1206 "__restore_r16_through_r19_and_deallocframe_before_tailcall",

1207 "__restore_r16_through_r21_and_deallocframe_before_tailcall",

1208 "__restore_r16_through_r23_and_deallocframe_before_tailcall",

1209 "__restore_r16_through_r25_and_deallocframe_before_tailcall",

1210 "__restore_r16_through_r27_and_deallocframe_before_tailcall"

1211 };

1212

1213 const char **SpillFunc = nullptr;

1214

1215 switch(SpillType) {

1217 SpillFunc = Stkchk ? V4SpillToMemoryStkchkFunctions

1218 : V4SpillToMemoryFunctions;

1219 break;

1221 SpillFunc = V4SpillFromMemoryFunctions;

1222 break;

1224 SpillFunc = V4SpillFromMemoryTailcallFunctions;

1225 break;

1226 }

1227 assert(SpillFunc && "Unknown spill kind");

1228

1229

1230 switch (MaxReg) {

1231 case Hexagon::R17:

1232 return SpillFunc[0];

1233 case Hexagon::R19:

1234 return SpillFunc[1];

1235 case Hexagon::R21:

1236 return SpillFunc[2];

1237 case Hexagon::R23:

1238 return SpillFunc[3];

1239 case Hexagon::R25:

1240 return SpillFunc[4];

1241 case Hexagon::R27:

1242 return SpillFunc[5];

1243 default:

1245 }

1246 return nullptr;

1247}

1248

1249StackOffset

1254

1257 bool HasExtraAlign = HRI.hasStackRealignment(MF);

1259

1262 Register SP = HRI.getStackRegister();

1263 Register FP = HRI.getFrameRegister();

1264 Register AP = HMFI.getStackAlignBaseReg();

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279 bool UseFP = false, UseAP = false;

1280

1281

1282

1283

1284 if (NoOpt && !HasExtraAlign)

1285 UseFP = true;

1287

1288

1289 UseFP |= (HasAlloca || HasExtraAlign);

1290 } else {

1291 if (HasAlloca) {

1292 if (HasExtraAlign)

1293 UseAP = true;

1294 else

1295 UseFP = true;

1296 }

1297 }

1298

1299

1300 bool HasFP = hasFP(MF);

1301 assert((HasFP || !UseFP) && "This function must have frame pointer");

1302

1303

1304

1305

1306

1307

1308

1309

1310

1311

1312

1313

1314

1315

1316

1317

1318

1319

1320

1321

1322

1323

1324

1325

1326

1327 if (Offset > 0 && !HasFP)

1329

1330 if (UseFP)

1331 FrameReg = FP;

1332 else if (UseAP)

1333 FrameReg = AP;

1334 else

1335 FrameReg = SP;

1336

1337

1338

1339

1340

1341 int RealOffset = Offset;

1342 if (!UseFP && !UseAP)

1343 RealOffset = FrameSize+Offset;

1345}

1346

1349 bool &PrologueStubs) const {

1350 if (CSI.empty())

1351 return true;

1352

1354 PrologueStubs = false;

1358

1359 if (useSpillFunction(MF, CSI)) {

1360 PrologueStubs = true;

1364 StkOvrFlowEnabled);

1368

1369

1371 unsigned SpillOpc;

1372 if (StkOvrFlowEnabled) {

1373 if (LongCalls)

1374 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT_PIC

1375 : Hexagon::SAVE_REGISTERS_CALL_V4STK_EXT;

1376 else

1377 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4STK_PIC

1378 : Hexagon::SAVE_REGISTERS_CALL_V4STK;

1379 } else {

1380 if (LongCalls)

1381 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC

1382 : Hexagon::SAVE_REGISTERS_CALL_V4_EXT;

1383 else

1384 SpillOpc = IsPIC ? Hexagon::SAVE_REGISTERS_CALL_V4_PIC

1385 : Hexagon::SAVE_REGISTERS_CALL_V4;

1386 }

1387

1388 MachineInstr *SaveRegsCall =

1391

1392

1393 addCalleeSaveRegistersAsImpOperand(SaveRegsCall, CSI, false, true);

1394

1395 for (const CalleeSavedInfo &I : CSI)

1397 return true;

1398 }

1399

1400 for (const CalleeSavedInfo &I : CSI) {

1401 MCRegister Reg = I.getReg();

1402

1403

1404

1406 int FI = I.getFrameIdx();

1407 const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);

1408 HII.storeRegToStackSlot(MBB, MI, Reg, IsKill, FI, RC, Register());

1409 if (IsKill)

1411 }

1412 return true;

1413}

1414

1415bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &MBB,

1416 const CSIVect &CSI, const HexagonRegisterInfo &HRI) const {

1417 if (CSI.empty())

1418 return false;

1419

1422 auto &HST = MF.getSubtarget();

1424

1425 if (useRestoreFunction(MF, CSI)) {

1430 auto &HTM = static_cast<const HexagonTargetMachine&>(MF.getTarget());

1431 bool IsPIC = HTM.isPositionIndependent();

1433

1434

1437 MachineInstr *DeallocCall = nullptr;

1438

1439 if (HasTC) {

1440 unsigned RetOpc;

1441 if (LongCalls)

1442 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC

1443 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT;

1444 else

1445 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC

1446 : Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;

1449 } else {

1450

1452 assert(It->isReturn() && std::next(It) == MBB.end());

1453 unsigned RetOpc;

1454 if (LongCalls)

1455 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT_PIC

1456 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4_EXT;

1457 else

1458 RetOpc = IsPIC ? Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC

1459 : Hexagon::RESTORE_DEALLOC_RET_JMP_V4;

1460 DeallocCall = BuildMI(MBB, It, DL, HII.get(RetOpc))

1462

1464 }

1465 addCalleeSaveRegistersAsImpOperand(DeallocCall, CSI, true, false);

1466 return true;

1467 }

1468

1469 for (const CalleeSavedInfo &I : CSI) {

1470 MCRegister Reg = I.getReg();

1471 const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);

1472 int FI = I.getFrameIdx();

1474 }

1475

1476 return true;

1477}

1478

1483 unsigned Opc = MI.getOpcode();

1484 (void)Opc;

1485 assert((Opc == Hexagon::ADJCALLSTACKDOWN || Opc == Hexagon::ADJCALLSTACKUP) &&

1486 "Cannot handle this call frame pseudo instruction");

1487 return MBB.erase(I);

1488}

1489

1492

1493

1494

1495

1499

1500 if (!HasAlloca || !NeedsAlign)

1501 return;

1502

1503

1506 AP = AI->getOperand(0).getReg();

1509 HMFI.setStackAlignBaseReg(AP);

1510}

1511

1512

1516

1519 if (MRI.isPhysRegUsed(*AI))

1520 return true;

1521 return false;

1522 };

1523

1524

1525

1527 if (!IsUsed(*P))

1528 return false;

1529

1530

1531 return true;

1532}

1533

1534#ifndef NDEBUG

1536 dbgs() << '{';

1540 }

1541 dbgs() << " }";

1542}

1543#endif

1544

1549 BitVector SRegs(Hexagon::NUM_TARGET_REGS);

1550

1551

1552

1553

1554

1555

1556

1561 for (MCPhysReg SR : TRI->subregs_inclusive(R))

1562 SRegs[SR] = true;

1563 }

1566 dbgs() << "\n");

1567

1568

1569

1571

1572

1577

1579 bool HasResSub = false;

1582 continue;

1583 HasResSub = true;

1584 break;

1585 }

1586 if (!HasResSub)

1588 }

1589 }

1590

1591 for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x)) {

1593 for (MCPhysReg SR : TRI->superregs_inclusive(R))

1594 SRegs[SR] = false;

1595 }

1597 dbgs() << "\n");

1599 dbgs() << "\n");

1600

1601

1602

1603

1604

1605 BitVector TmpSup(Hexagon::NUM_TARGET_REGS);

1609 TmpSup[SR] = true;

1610 }

1611 for (int x = TmpSup.find_first(); x >= 0; x = TmpSup.find_next(x)) {

1613 for (MCPhysReg SR : TRI->subregs_inclusive(R)) {

1615 continue;

1616 TmpSup[R] = false;

1617 break;

1618 }

1619 }

1621 dbgs() << "\n");

1622

1623

1624 SRegs |= TmpSup;

1626 dbgs() << "\n");

1627

1628

1629

1633 if (!SRegs[SR])

1634 continue;

1635 SRegs[R] = false;

1636 break;

1637 }

1638 }

1640 dbgs() << "\n");

1641

1642

1643

1644 CSI.clear();

1645

1647

1648 unsigned NumFixed;

1649 int64_t MinOffset = 0;

1651 for (const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) {

1652 if (!SRegs[S->Reg])

1653 continue;

1656 MinOffset = std::min(MinOffset, S->Offset);

1658 SRegs[S->Reg] = false;

1659 }

1660

1661

1662

1663

1667 unsigned Size = TRI->getSpillSize(*RC);

1668 int64_t Off = MinOffset - Size;

1670 Off &= -Alignment.value();

1672 MinOffset = std::min(MinOffset, Off);

1674 SRegs[R] = false;

1675 }

1676

1678 dbgs() << "CS information: {";

1680 int FI = I.getFrameIdx();

1682 dbgs() << ' ' << printReg(I.getReg(), TRI) << ":fi#" << FI << ":sp";

1683 if (Off >= 0)

1684 dbgs() << '+';

1685 dbgs() << Off;

1686 }

1687 dbgs() << " }\n";

1688 });

1689

1690#ifndef NDEBUG

1691

1692 bool MissedReg = false;

1696 MissedReg = true;

1697 }

1698 if (MissedReg)

1699 llvm_unreachable("...there are unhandled callee-saved registers!");

1700#endif

1701

1702 return true;

1703}

1704

1710 Register DstR = MI->getOperand(0).getReg();

1711 Register SrcR = MI->getOperand(1).getReg();

1712 if (!Hexagon::ModRegsRegClass.contains(DstR) ||

1713 !Hexagon::ModRegsRegClass.contains(SrcR))

1714 return false;

1715

1716 Register TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

1717 BuildMI(B, It, DL, HII.get(TargetOpcode::COPY), TmpR).add(MI->getOperand(1));

1718 BuildMI(B, It, DL, HII.get(TargetOpcode::COPY), DstR)

1720

1722 B.erase(It);

1723 return true;

1724}

1725

1730 if (MI->getOperand(0).isFI())

1731 return false;

1732

1734 unsigned Opc = MI->getOpcode();

1735 Register SrcR = MI->getOperand(2).getReg();

1736 bool IsKill = MI->getOperand(2).isKill();

1737 int FI = MI->getOperand(0).getIndex();

1738

1739

1740

1741 Register TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

1742 unsigned TfrOpc = (Opc == Hexagon::STriw_pred) ? Hexagon::C2_tfrpr

1744 BuildMI(B, It, DL, HII.get(TfrOpc), TmpR)

1746

1747

1748 BuildMI(B, It, DL, HII.get(Hexagon::S2_storeri_io))

1753

1755 B.erase(It);

1756 return true;

1757}

1758

1759bool HexagonFrameLowering::expandLoadInt(MachineBasicBlock &B,

1761 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1762 MachineInstr *MI = &*It;

1763 if (MI->getOperand(1).isFI())

1764 return false;

1765

1767 unsigned Opc = MI->getOpcode();

1768 Register DstR = MI->getOperand(0).getReg();

1769 int FI = MI->getOperand(1).getIndex();

1770

1771

1772 Register TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

1773 BuildMI(B, It, DL, HII.get(Hexagon::L2_loadri_io), TmpR)

1777

1778

1779

1780 unsigned TfrOpc = (Opc == Hexagon::LDriw_pred) ? Hexagon::C2_tfrrp

1781 : Hexagon::A2_tfrrcr;

1782 BuildMI(B, It, DL, HII.get(TfrOpc), DstR)

1784

1786 B.erase(It);

1787 return true;

1788}

1789

1790bool HexagonFrameLowering::expandStoreVecPred(MachineBasicBlock &B,

1792 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1793 MachineInstr *MI = &*It;

1794 if (MI->getOperand(0).isFI())

1795 return false;

1796

1798 Register SrcR = MI->getOperand(2).getReg();

1799 bool IsKill = MI->getOperand(2).isKill();

1800 int FI = MI->getOperand(0).getIndex();

1801 auto *RC = &Hexagon::HvxVRRegClass;

1802

1803

1804

1805

1806

1807 Register TmpR0 = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

1808 Register TmpR1 = MRI.createVirtualRegister(RC);

1809

1810 BuildMI(B, It, DL, HII.get(Hexagon::A2_tfrsi), TmpR0)

1811 .addImm(0x01010101);

1812

1813 BuildMI(B, It, DL, HII.get(Hexagon::V6_vandqrt), TmpR1)

1816

1818 expandStoreVec(B, std::prev(It), MRI, HII, NewRegs);

1819

1822 B.erase(It);

1823 return true;

1824}

1825

1826bool HexagonFrameLowering::expandLoadVecPred(MachineBasicBlock &B,

1828 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1829 MachineInstr *MI = &*It;

1830 if (MI->getOperand(1).isFI())

1831 return false;

1832

1834 Register DstR = MI->getOperand(0).getReg();

1835 int FI = MI->getOperand(1).getIndex();

1836 auto *RC = &Hexagon::HvxVRRegClass;

1837

1838

1839

1840

1841 Register TmpR0 = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

1842 Register TmpR1 = MRI.createVirtualRegister(RC);

1843

1844 BuildMI(B, It, DL, HII.get(Hexagon::A2_tfrsi), TmpR0)

1845 .addImm(0x01010101);

1847 expandLoadVec(B, std::prev(It), MRI, HII, NewRegs);

1848

1849 BuildMI(B, It, DL, HII.get(Hexagon::V6_vandvrt), DstR)

1852

1855 B.erase(It);

1856 return true;

1857}

1858

1859bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,

1861 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1862 MachineFunction &MF = *B.getParent();

1864 auto &HRI = *MF.getSubtarget().getRegisterInfo();

1865 MachineInstr *MI = &*It;

1866 if (MI->getOperand(0).isFI())

1867 return false;

1868

1869

1870

1871

1872

1873 LivePhysRegs LPR(HRI);

1874 LPR.addLiveIns(B);

1876 for (auto R = B.begin(); R != It; ++R) {

1877 Clobbers.clear();

1878 LPR.stepForward(*R, Clobbers);

1879 }

1880

1882 Register SrcR = MI->getOperand(2).getReg();

1883 Register SrcLo = HRI.getSubReg(SrcR, Hexagon::vsub_lo);

1884 Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);

1885 bool IsKill = MI->getOperand(2).isKill();

1886 int FI = MI->getOperand(0).getIndex();

1887

1888 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);

1889 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);

1891 unsigned StoreOpc;

1892

1893

1894 if (LPR.contains(SrcLo)) {

1895 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai

1896 : Hexagon::V6_vS32Ub_ai;

1897 BuildMI(B, It, DL, HII.get(StoreOpc))

1902 }

1903

1904

1905 if (LPR.contains(SrcHi)) {

1906 StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai

1907 : Hexagon::V6_vS32Ub_ai;

1908 BuildMI(B, It, DL, HII.get(StoreOpc))

1913 }

1914

1915 B.erase(It);

1916 return true;

1917}

1918

1919bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &B,

1921 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1922 MachineFunction &MF = *B.getParent();

1924 auto &HRI = *MF.getSubtarget().getRegisterInfo();

1925 MachineInstr *MI = &*It;

1926 if (MI->getOperand(1).isFI())

1927 return false;

1928

1930 Register DstR = MI->getOperand(0).getReg();

1931 Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);

1932 Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);

1933 int FI = MI->getOperand(1).getIndex();

1934

1935 unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);

1936 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);

1938 unsigned LoadOpc;

1939

1940

1941 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai

1942 : Hexagon::V6_vL32Ub_ai;

1943 BuildMI(B, It, DL, HII.get(LoadOpc), DstLo)

1947

1948

1949 LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai

1950 : Hexagon::V6_vL32Ub_ai;

1951 BuildMI(B, It, DL, HII.get(LoadOpc), DstHi)

1955

1956 B.erase(It);

1957 return true;

1958}

1959

1960bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,

1962 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1963 MachineFunction &MF = *B.getParent();

1965 MachineInstr *MI = &*It;

1966 if (MI->getOperand(0).isFI())

1967 return false;

1968

1969 auto &HRI = *MF.getSubtarget().getRegisterInfo();

1971 Register SrcR = MI->getOperand(2).getReg();

1972 bool IsKill = MI->getOperand(2).isKill();

1973 int FI = MI->getOperand(0).getIndex();

1974

1975 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);

1977 unsigned StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai

1978 : Hexagon::V6_vS32Ub_ai;

1979 BuildMI(B, It, DL, HII.get(StoreOpc))

1984

1985 B.erase(It);

1986 return true;

1987}

1988

1989bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,

1991 const HexagonInstrInfo &HII, SmallVectorImpl &NewRegs) const {

1992 MachineFunction &MF = *B.getParent();

1994 MachineInstr *MI = &*It;

1995 if (MI->getOperand(1).isFI())

1996 return false;

1997

1998 auto &HRI = *MF.getSubtarget().getRegisterInfo();

2000 Register DstR = MI->getOperand(0).getReg();

2001 int FI = MI->getOperand(1).getIndex();

2002

2003 Align NeedAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);

2005 unsigned LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai

2006 : Hexagon::V6_vL32Ub_ai;

2007 BuildMI(B, It, DL, HII.get(LoadOpc), DstR)

2011

2012 B.erase(It);

2013 return true;

2014}

2015

2016bool HexagonFrameLowering::expandSpillMacros(MachineFunction &MF,

2017 SmallVectorImpl &NewRegs) const {

2018 auto &HII = *MF.getSubtarget().getInstrInfo();

2021

2022 for (auto &B : MF) {

2023

2025 for (auto I = B.begin(), E = B.end(); I != E; I = NextI) {

2026 MachineInstr *MI = &*I;

2027 NextI = std::next(I);

2028 unsigned Opc = MI->getOpcode();

2029

2030 switch (Opc) {

2031 case TargetOpcode::COPY:

2032 Changed |= expandCopy(B, I, MRI, HII, NewRegs);

2033 break;

2034 case Hexagon::STriw_pred:

2035 case Hexagon::STriw_ctr:

2036 Changed |= expandStoreInt(B, I, MRI, HII, NewRegs);

2037 break;

2038 case Hexagon::LDriw_pred:

2039 case Hexagon::LDriw_ctr:

2040 Changed |= expandLoadInt(B, I, MRI, HII, NewRegs);

2041 break;

2042 case Hexagon::PS_vstorerq_ai:

2043 Changed |= expandStoreVecPred(B, I, MRI, HII, NewRegs);

2044 break;

2045 case Hexagon::PS_vloadrq_ai:

2046 Changed |= expandLoadVecPred(B, I, MRI, HII, NewRegs);

2047 break;

2048 case Hexagon::PS_vloadrw_ai:

2049 Changed |= expandLoadVec2(B, I, MRI, HII, NewRegs);

2050 break;

2051 case Hexagon::PS_vstorerw_ai:

2052 Changed |= expandStoreVec2(B, I, MRI, HII, NewRegs);

2053 break;

2054 }

2055 }

2056 }

2057

2059}

2060

2065

2066 SavedRegs.resize(HRI.getNumRegs());

2067

2068

2069

2072 SavedRegs.set(*R);

2073

2074

2076 expandSpillMacros(MF, NewRegs);

2078 optimizeSpillSlots(MF, NewRegs);

2079

2080

2081

2082 if (!NewRegs.empty() || mayOverflowFrameOffset(MF)) {

2086

2087

2088 SpillRCs.insert(&Hexagon::IntRegsRegClass);

2089

2091 SpillRCs.insert(MRI.getRegClass(VR));

2092

2093 for (const auto *RC : SpillRCs) {

2095 continue;

2096 unsigned Num = 1;

2097 switch (RC->getID()) {

2098 case Hexagon::IntRegsRegClassID:

2100 break;

2101 case Hexagon::HvxQRRegClassID:

2102 Num = 2;

2103 break;

2104 }

2105 unsigned S = HRI.getSpillSize(*RC);

2106 Align A = HRI.getSpillAlign(*RC);

2107 for (unsigned i = 0; i < Num; i++) {

2109 RS->addScavengingFrameIndex(NewFI);

2110 }

2111 }

2112 }

2113

2115}

2116

2124

2125 auto isDead = [&FIR,&DeadMap] (Register Reg) -> bool {

2126 auto F = DeadMap.find({Reg,0});

2127 if (F == DeadMap.end())

2128 return false;

2129 for (auto &DR : F->second)

2130 if (DR.contains(FIR))

2131 return true;

2132 return false;

2133 };

2134

2136 bool Dead = true;

2139 continue;

2140 Dead = false;

2141 break;

2142 }

2143 if (Dead)

2144 return Reg;

2145 }

2146 return 0;

2147}

2148

2149void HexagonFrameLowering::optimizeSpillSlots(MachineFunction &MF,

2150 SmallVectorImpl &VRegs) const {

2151 auto &HST = MF.getSubtarget();

2152 auto &HII = *HST.getInstrInfo();

2153 auto &HRI = *HST.getRegisterInfo();

2155 HexagonBlockRanges HBR(MF);

2156

2157 using BlockIndexMap =

2158 std::map<MachineBasicBlock *, HexagonBlockRanges::InstrIndexMap>;

2159 using BlockRangeMap =

2160 std::map<MachineBasicBlock *, HexagonBlockRanges::RangeList>;

2161 using IndexType = HexagonBlockRanges::IndexType;

2162

2163 struct SlotInfo {

2164 BlockRangeMap Map;

2165 unsigned Size = 0;

2166 const TargetRegisterClass *RC = nullptr;

2167

2168 SlotInfo() = default;

2169 };

2170

2171 BlockIndexMap BlockIndexes;

2172 SmallSet<int,4> BadFIs;

2173 std::map<int,SlotInfo> FIRangeMap;

2174

2175

2176

2177

2178

2179 auto getCommonRC =

2180 [](const TargetRegisterClass *HaveRC,

2181 const TargetRegisterClass *NewRC) -> const TargetRegisterClass * {

2182 if (HaveRC == nullptr || HaveRC == NewRC)

2183 return NewRC;

2184

2186 return HaveRC;

2187 if (NewRC->hasSubClassEq(HaveRC))

2188 return NewRC;

2189 return nullptr;

2190 };

2191

2192

2193

2194 for (auto &B : MF) {

2195 std::map<int,IndexType> LastStore, LastLoad;

2196 auto P = BlockIndexes.emplace(&B, HexagonBlockRanges::InstrIndexMap(B));

2197 auto &IndexMap = P.first->second;

2199 << IndexMap << '\n');

2200

2201 for (auto &In : B) {

2202 int LFI, SFI;

2203 bool Load = HII.isLoadFromStackSlot(In, LFI) && !HII.isPredicated(In);

2204 bool Store = HII.isStoreToStackSlot(In, SFI) && !HII.isPredicated(In);

2205 if (Load && Store) {

2206

2209 continue;

2210 }

2211

2212

2213

2214

2215

2216

2217 if (Load || Store) {

2218 int TFI = Load ? LFI : SFI;

2219 unsigned AM = HII.getAddrMode(In);

2220 SlotInfo &SI = FIRangeMap[TFI];

2222 if (!Bad) {

2223

2224 unsigned OpNum = Load ? 0 : 2;

2225 auto *RC = HII.getRegClass(In.getDesc(), OpNum);

2226 RC = getCommonRC(SI.RC, RC);

2227 if (RC == nullptr)

2228 Bad = true;

2229 else

2230 SI.RC = RC;

2231 }

2232 if (!Bad) {

2233

2234 unsigned S = HII.getMemAccessSize(In);

2235 if (SI.Size != 0 && SI.Size != S)

2236 Bad = true;

2237 else

2238 SI.Size = S;

2239 }

2240 if (!Bad) {

2241 for (auto *Mo : In.memoperands()) {

2242 if (!Mo->isVolatile() && !Mo->isAtomic())

2243 continue;

2244 Bad = true;

2245 break;

2246 }

2247 }

2248 if (Bad)

2250 }

2251

2252

2253 for (unsigned i = 0, n = In.getNumOperands(); i < n; ++i) {

2254 const MachineOperand &Op = In.getOperand(i);

2255 if (Op.isFI())

2256 continue;

2257 int FI = Op.getIndex();

2258

2259

2260 if (i+1 >= n || In.getOperand(i+1).isImm() ||

2261 In.getOperand(i+1).getImm() != 0)

2263 if (BadFIs.count(FI))

2264 continue;

2265

2267 auto &LS = LastStore[FI];

2268 auto &LL = LastLoad[FI];

2269 if (Load) {

2270 if (LS == IndexType::None)

2271 LS = IndexType::Entry;

2273 } else if (Store) {

2274 HexagonBlockRanges::RangeList &RL = FIRangeMap[FI].Map[&B];

2275 if (LS != IndexType::None)

2276 RL.add(LS, LL, false, false);

2277 else if (LL != IndexType::None)

2278 RL.add(IndexType::Entry, LL, false, false);

2279 LL = IndexType::None;

2281 } else {

2283 }

2284 }

2285 }

2286

2287 for (auto &I : LastLoad) {

2288 IndexType LL = I.second;

2289 if (LL == IndexType::None)

2290 continue;

2291 auto &RL = FIRangeMap[I.first].Map[&B];

2292 IndexType &LS = LastStore[I.first];

2293 if (LS != IndexType::None)

2294 RL.add(LS, LL, false, false);

2295 else

2296 RL.add(IndexType::Entry, LL, false, false);

2297 LS = IndexType::None;

2298 }

2299 for (auto &I : LastStore) {

2300 IndexType LS = I.second;

2301 if (LS == IndexType::None)

2302 continue;

2303 auto &RL = FIRangeMap[I.first].Map[&B];

2304 RL.add(LS, IndexType::None, false, false);

2305 }

2306 }

2307

2309 for (auto &P : FIRangeMap) {

2310 dbgs() << "fi#" << P.first;

2311 if (BadFIs.count(P.first))

2312 dbgs() << " (bad)";

2313 dbgs() << " RC: ";

2314 if (P.second.RC != nullptr)

2315 dbgs() << HRI.getRegClassName(P.second.RC) << '\n';

2316 else

2317 dbgs() << "\n";

2318 for (auto &R : P.second.Map)

2320 << "}\n";

2321 }

2322 });

2323

2324

2325

2326

2327 SmallSet<int,4> LoxFIs;

2328

2329 std::map<MachineBasicBlock*,std::vector> BlockFIMap;

2330

2331 for (auto &P : FIRangeMap) {

2332

2333 if (BadFIs.count(P.first))

2334 continue;

2335 for (auto &B : MF) {

2336 auto F = P.second.Map.find(&B);

2337

2338 if (F == P.second.Map.end() || F->second.empty())

2339 continue;

2340 HexagonBlockRanges::IndexRange &IR = F->second.front();

2341 if (IR.start() == IndexType::Entry)

2342 LoxFIs.insert(P.first);

2343 BlockFIMap[&B].push_back(P.first);

2344 }

2345 }

2346

2348 dbgs() << "Block-to-FI map (* -- live-on-exit):\n";

2349 for (auto &P : BlockFIMap) {

2350 auto &FIs = P.second;

2351 if (FIs.empty())

2352 continue;

2354 for (auto I : FIs) {

2355 dbgs() << " fi#" << I;

2356 if (LoxFIs.count(I))

2357 dbgs() << '*';

2358 }

2359 dbgs() << " }\n";

2360 }

2361 });

2362

2363#ifndef NDEBUG

2364 bool HasOptLimit = SpillOptMax.getPosition();

2365#endif

2366

2367

2368 for (auto &B : MF) {

2369 auto F = BlockIndexes.find(&B);

2370 assert(F != BlockIndexes.end());

2371 HexagonBlockRanges::InstrIndexMap &IM = F->second;

2375 << HexagonBlockRanges::PrintRangeMap(DM, HRI));

2376

2377 for (auto FI : BlockFIMap[&B]) {

2378 if (BadFIs.count(FI))

2379 continue;

2380 LLVM_DEBUG(dbgs() << "Working on fi#" << FI << '\n');

2381 HexagonBlockRanges::RangeList &RL = FIRangeMap[FI].Map[&B];

2382 for (auto &Range : RL) {

2383 LLVM_DEBUG(dbgs() << "--Examining range:" << RL << '\n');

2384 if (!IndexType::isInstr(Range.start()) ||

2385 !IndexType::isInstr(Range.end()))

2386 continue;

2389 assert(SI.mayStore() && "Unexpected start instruction");

2390 assert(EI.mayLoad() && "Unexpected end instruction");

2391 MachineOperand &SrcOp = SI.getOperand(2);

2392

2393 HexagonBlockRanges::RegisterRef SrcRR = { SrcOp.getReg(),

2395 auto *RC = HII.getRegClass(SI.getDesc(), 2);

2396

2397 Register FoundR = this->findPhysReg(MF, Range, IM, DM, RC);

2399 << '\n');

2400 if (FoundR == 0)

2401 continue;

2402#ifndef NDEBUG

2403 if (HasOptLimit) {

2405 return;

2407 }

2408#endif

2409

2410

2412 MachineInstr *CopyIn = nullptr;

2413 if (SrcRR.Reg != FoundR || SrcRR.Sub != 0) {

2415 CopyIn = BuildMI(B, StartIt, DL, HII.get(TargetOpcode::COPY), FoundR)

2416 .add(SrcOp);

2417 }

2418

2419 ++StartIt;

2420

2421 if (LoxFIs.count(FI) && (&Range == &RL.back())) {

2422

2423 if (unsigned SR = SrcOp.getSubReg())

2424 SrcOp.setReg(HRI.getSubReg(FoundR, SR));

2425 else

2426 SrcOp.setReg(FoundR);

2428

2430 } else {

2431 B.erase(&SI);

2433 }

2434

2435 auto EndIt = std::next(EI.getIterator());

2436 for (auto It = StartIt; It != EndIt; It = NextIt) {

2437 MachineInstr &MI = *It;

2438 NextIt = std::next(It);

2439 int TFI;

2440 if (!HII.isLoadFromStackSlot(MI, TFI) || TFI != FI)

2441 continue;

2442 Register DstR = MI.getOperand(0).getReg();

2443 assert(MI.getOperand(0).getSubReg() == 0);

2444 MachineInstr *CopyOut = nullptr;

2445 if (DstR != FoundR) {

2447 unsigned MemSize = HII.getMemAccessSize(MI);

2449 unsigned CopyOpc = TargetOpcode::COPY;

2450 if (HII.isSignExtendingLoad(MI))

2451 CopyOpc = (MemSize == 1) ? Hexagon::A2_sxtb : Hexagon::A2_sxth;

2452 else if (HII.isZeroExtendingLoad(MI))

2453 CopyOpc = (MemSize == 1) ? Hexagon::A2_zxtb : Hexagon::A2_zxth;

2454 CopyOut = BuildMI(B, It, DL, HII.get(CopyOpc), DstR)

2456 }

2458 B.erase(It);

2459 }

2460

2461

2462 HexagonBlockRanges::RegisterRef FoundRR = { FoundR, 0 };

2465 }

2466 }

2467 }

2468}

2469

2470void HexagonFrameLowering::expandAlloca(MachineInstr *AI,

2471 const HexagonInstrInfo &HII, Register SP, unsigned CF) const {

2472 MachineBasicBlock &MB = *AI->getParent();

2475

2476

2477

2478

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491 MachineOperand &RdOp = AI->getOperand(0);

2492 MachineOperand &RsOp = AI->getOperand(1);

2494

2495

2496 BuildMI(MB, AI, DL, HII.get(Hexagon::A2_sub), Rd)

2499 if (Rs != Rd) {

2500

2501 BuildMI(MB, AI, DL, HII.get(Hexagon::A2_sub), SP)

2504 }

2505 if (A > 8) {

2506

2507 BuildMI(MB, AI, DL, HII.get(Hexagon::A2_andir), Rd)

2510 if (Rs != Rd)

2511 BuildMI(MB, AI, DL, HII.get(Hexagon::A2_andir), SP)

2514 }

2515 if (Rs == Rd) {

2516

2517 BuildMI(MB, AI, DL, HII.get(TargetOpcode::COPY), SP)

2519 }

2520 if (CF > 0) {

2521

2522 BuildMI(MB, AI, DL, HII.get(Hexagon::A2_addi), Rd)

2525 }

2526}

2527

2531 return false;

2532

2533

2534

2535 return true;

2536}

2537

2540 for (auto &B : MF)

2541 for (auto &I : B)

2542 if (I.getOpcode() == Hexagon::PS_aligna)

2543 return &I;

2544 return nullptr;

2545}

2546

2547

2548

2549void HexagonFrameLowering::addCalleeSaveRegistersAsImpOperand(MachineInstr *MI,

2550 const CSIVect &CSI, bool IsDef, bool IsKill) const {

2551

2552 for (auto &R : CSI)

2554}

2555

2556

2557

2558

2559

2560bool HexagonFrameLowering::shouldInlineCSR(const MachineFunction &MF,

2561 const CSIVect &CSI) const {

2563 return true;

2565 return true;

2566 if (!hasFP(MF))

2567 return true;

2570 return true;

2571

2572

2573

2574 BitVector Regs(Hexagon::NUM_TARGET_REGS);

2577 if (!Hexagon::DoubleRegsRegClass.contains(R))

2578 return true;

2579 Regs[R] = true;

2580 }

2581 int F = Regs.find_first();

2582 if (F != Hexagon::D8)

2583 return true;

2584 while (F >= 0) {

2585 int N = Regs.find_next(F);

2586 if (N >= 0 && N != F+1)

2587 return true;

2588 F = N;

2589 }

2590

2591 return false;

2592}

2593

2594bool HexagonFrameLowering::useSpillFunction(const MachineFunction &MF,

2595 const CSIVect &CSI) const {

2596 if (shouldInlineCSR(MF, CSI))

2597 return false;

2598 unsigned NumCSI = CSI.size();

2599 if (NumCSI <= 1)

2600 return false;

2601

2604 return Threshold < NumCSI;

2605}

2606

2607bool HexagonFrameLowering::useRestoreFunction(const MachineFunction &MF,

2608 const CSIVect &CSI) const {

2609 if (shouldInlineCSR(MF, CSI))

2610 return false;

2611

2612

2613

2614

2615

2616

2618 return true;

2619 unsigned NumCSI = CSI.size();

2620 if (NumCSI <= 1)

2621 return false;

2622

2625 return Threshold < NumCSI;

2626}

2627

2628bool HexagonFrameLowering::mayOverflowFrameOffset(MachineFunction &MF) const {

2630 auto &HST = MF.getSubtarget();

2631

2632

2633 if (HST.useHVXOps() && StackSize > 256)

2634 return true;

2635

2636

2637

2638

2639

2640 bool HasImmStack = false;

2641 unsigned MinLS = ~0u;

2642

2643 for (const MachineBasicBlock &B : MF) {

2644 for (const MachineInstr &MI : B) {

2645 unsigned LS = 0;

2646 switch (MI.getOpcode()) {

2647 case Hexagon::S4_storeirit_io:

2648 case Hexagon::S4_storeirif_io:

2649 case Hexagon::S4_storeiri_io:

2650 ++LS;

2651 [[fallthrough]];

2652 case Hexagon::S4_storeirht_io:

2653 case Hexagon::S4_storeirhf_io:

2654 case Hexagon::S4_storeirh_io:

2655 ++LS;

2656 [[fallthrough]];

2657 case Hexagon::S4_storeirbt_io:

2658 case Hexagon::S4_storeirbf_io:

2659 case Hexagon::S4_storeirb_io:

2660 if (MI.getOperand(0).isFI())

2661 HasImmStack = true;

2662 MinLS = std::min(MinLS, LS);

2663 break;

2664 }

2665 }

2666 }

2667

2668 if (HasImmStack)

2669 return isUInt<6>(StackSize >> MinLS);

2670

2671 return false;

2672}

2673

2674namespace {

2675

2676struct HexagonFrameSortingObject {

2677 bool IsValid = false;

2678 unsigned Index = 0;

2679 unsigned Size = 0;

2680 Align ObjectAlignment = Align(1);

2681};

2682

2683struct HexagonFrameSortingComparator {

2684 inline bool operator()(const HexagonFrameSortingObject &A,

2685 const HexagonFrameSortingObject &B) const {

2686 return std::make_tuple(A.IsValid, A.ObjectAlignment, A.Size) <

2687 std::make_tuple(B.IsValid, B.ObjectAlignment, B.Size);

2688 }

2689};

2690}

2691

2692

2693

2696

2697 if (ObjectsToAllocate.empty())

2698 return;

2699

2701 int NObjects = ObjectsToAllocate.size();

2702

2703

2706

2707 for (int i = 0, j = 0, e = MFI.getObjectIndexEnd(); i < e && j != NObjects;

2708 ++i) {

2709 if (i != ObjectsToAllocate[j])

2710 continue;

2711 j++;

2712

2713

2714

2715

2717 if (Size == 0)

2718 return;

2719

2720 SortingObjects[i].IsValid = true;

2721 SortingObjects[i].Index = i;

2722 SortingObjects[i].Size = Size;

2723 SortingObjects[i].ObjectAlignment = MFI.getObjectAlign(i);

2724 }

2725

2726

2727 llvm::stable_sort(SortingObjects, HexagonFrameSortingComparator());

2728

2729

2730 int i = NObjects;

2731 for (auto &Obj : SortingObjects) {

2732 if (i == 0)

2733 break;

2734 ObjectsToAllocate[--i] = Obj.Index;

2735 }

2736}

unsigned const MachineRegisterInfo * MRI

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

This file implements the BitVector class.

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

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

static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")

This file defines the DenseMap class.

static MachineInstr * getReturn(MachineBasicBlock &MBB)

Returns the "return" instruction from this block, or nullptr if there isn't any.

Definition HexagonFrameLowering.cpp:349

static cl::opt< unsigned > ShrinkLimit("shrink-frame-limit", cl::init(std::numeric_limits< unsigned >::max()), cl::Hidden, cl::desc("Max count of stack frame shrink-wraps"))

static bool isOptNone(const MachineFunction &MF)

Definition HexagonFrameLowering.cpp:371

static cl::opt< int > SpillFuncThreshold("spill-func-threshold", cl::Hidden, cl::desc("Specify O2(not Os) spill func threshold"), cl::init(6))

static std::optional< MachineBasicBlock::iterator > findCFILocation(MachineBasicBlock &B)

Definition HexagonFrameLowering.cpp:987

static cl::opt< bool > EliminateFramePointer("hexagon-fp-elim", cl::init(true), cl::Hidden, cl::desc("Refrain from using FP whenever possible"))

SpillKind

Definition HexagonFrameLowering.cpp:1172

@ SK_FromMemTailcall

Definition HexagonFrameLowering.cpp:1175

@ SK_ToMem

Definition HexagonFrameLowering.cpp:1173

@ SK_FromMem

Definition HexagonFrameLowering.cpp:1174

static bool enableAllocFrameElim(const MachineFunction &MF)

Definition HexagonFrameLowering.cpp:568

static const char * getSpillFunctionFor(Register MaxReg, SpillKind SpillType, bool Stkchk=false)

Definition HexagonFrameLowering.cpp:1178

static bool hasReturn(const MachineBasicBlock &MBB)

Returns true if MBB contains an instruction that returns.

Definition HexagonFrameLowering.cpp:340

static cl::opt< bool > EnableSaveRestoreLong("enable-save-restore-long", cl::Hidden, cl::desc("Enable long calls for save-restore stubs."), cl::init(false))

static bool needToReserveScavengingSpillSlots(MachineFunction &MF, const HexagonRegisterInfo &HRI, const TargetRegisterClass *RC)

Returns true if there are no caller-saved registers available in class RC.

Definition HexagonFrameLowering.cpp:1513

static bool isOptSize(const MachineFunction &MF)

Definition HexagonFrameLowering.cpp:376

static Register getMax32BitSubRegister(Register Reg, const TargetRegisterInfo &TRI, bool hireg=true)

Map a register pair Reg to the subregister that has the greater "number", i.e.

Definition HexagonFrameLowering.cpp:237

static cl::opt< int > SpillFuncThresholdOs("spill-func-threshold-Os", cl::Hidden, cl::desc("Specify Os spill func threshold"), cl::init(1))

static bool needsStackFrame(const MachineBasicBlock &MBB, const BitVector &CSR, const HexagonRegisterInfo &HRI)

Checks if the basic block contains any instruction that needs a stack frame to be already in place.

Definition HexagonFrameLowering.cpp:275

static cl::opt< bool > DisableDeallocRet("disable-hexagon-dealloc-ret", cl::Hidden, cl::desc("Disable Dealloc Return for Hexagon target"))

static cl::opt< bool > EnableShrinkWrapping("hexagon-shrink-frame", cl::init(true), cl::Hidden, cl::desc("Enable stack frame shrink wrapping"))

static bool hasTailCall(const MachineBasicBlock &MBB)

Returns true if MBB has a machine instructions that indicates a tail call in the block.

Definition HexagonFrameLowering.cpp:331

static cl::opt< unsigned > NumberScavengerSlots("number-scavenger-slots", cl::Hidden, cl::desc("Set the number of scavenger slots"), cl::init(2))

static Register getMaxCalleeSavedReg(ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo &TRI)

Returns the callee saved register with the largest id in the vector.

Definition HexagonFrameLowering.cpp:257

static bool isMinSize(const MachineFunction &MF)

Definition HexagonFrameLowering.cpp:381

static cl::opt< unsigned > SpillOptMax("spill-opt-max", cl::Hidden, cl::init(std::numeric_limits< unsigned >::max()))

static unsigned SpillOptCount

Definition HexagonFrameLowering.cpp:196

static void dump_registers(BitVector &Regs, const TargetRegisterInfo &TRI)

Definition HexagonFrameLowering.cpp:1535

static bool isRestoreCall(unsigned Opc)

Definition HexagonFrameLowering.cpp:356

static cl::opt< bool > OptimizeSpillSlots("hexagon-opt-spill", cl::Hidden, cl::init(true), cl::desc("Optimize spill slots"))

static cl::opt< bool > EnableStackOVFSanitizer("enable-stackovf-sanitizer", cl::Hidden, cl::desc("Enable runtime checks for stack overflow."), cl::init(false))

Legalize the Machine IR a function s Machine IR

This file implements the LivePhysRegs utility for tracking liveness of physical registers.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

This file declares the machine register scavenger class.

bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)

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

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallSet class.

This file defines the SmallVector class.

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.

int find_first() const

find_first - Returns the index of the first set bit, -1 if none of the bits are set.

void resize(unsigned N, bool t=false)

resize - Grow or shrink the bitvector.

int find_next(unsigned Prev) const

find_next - Returns the index of the next set bit following the "Prev" bit.

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

NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const

Find nearest common dominator basic block for basic block A and B.

bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const

dominates - Returns true iff A dominates B.

void recalculate(ParentType &Func)

recalculate - compute a dominator tree for the given function

FunctionPass class - This class is used to implement most global optimizations.

bool hasMinSize() const

Optimize this function for minimum size (-Oz).

bool hasOptNone() const

Do not optimize this function (-O0).

bool isVarArg() const

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

void replaceInstr(MachineInstr *OldMI, MachineInstr *NewMI)

IndexType getIndex(MachineInstr *MI) const

MachineInstr * getInstr(IndexType Idx) const

void add(IndexType Start, IndexType End, bool Fixed, bool TiedEnd)

const MachineInstr * getAlignaInstr(const MachineFunction &MF) const

Definition HexagonFrameLowering.cpp:2538

void insertCFIInstructions(MachineFunction &MF) const

Definition HexagonFrameLowering.cpp:1017

bool hasFPImpl(const MachineFunction &MF) const override

Definition HexagonFrameLowering.cpp:1134

bool enableCalleeSaveSkip(const MachineFunction &MF) const override

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

Definition HexagonFrameLowering.cpp:551

MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...

Definition HexagonFrameLowering.cpp:1479

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

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

Definition HexagonFrameLowering.cpp:1250

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

Perform most of the PEI work here:

Definition HexagonFrameLowering.cpp:500

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

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

Definition HexagonFrameLowering.cpp:2061

void orderFrameObjects(const MachineFunction &MF, SmallVectorImpl< int > &ObjectsToAllocate) const override

Order the symbols in the local stack frame.

Definition HexagonFrameLowering.cpp:2694

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

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

Definition HexagonFrameLowering.cpp:1490

const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const override

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

bool needsAligna(const MachineFunction &MF) const

Definition HexagonFrameLowering.cpp:2528

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

assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.

Definition HexagonFrameLowering.cpp:1545

void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override

Store the specified register of the given register class to the specified stack frame index.

const HexagonRegisterInfo & getRegisterInfo() const

void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override

Load the specified register of the given register class from the specified stack frame index.

Hexagon target-specific information for each MachineFunction.

bool isEHReturnCalleeSaveReg(Register Reg) const

const MCPhysReg * getCalleeSavedRegs(const MachineFunction *MF) const override

Code Generation virtual methods...

const MCPhysReg * getCallerSavedRegs(const MachineFunction *MF, const TargetRegisterClass *RC) const

const HexagonInstrInfo * getInstrInfo() const override

bool isEnvironmentMusl() const

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.

LLVM_ABI MCSymbol * createTempSymbol()

Create a temporary symbol with a unique name.

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

MCRegAliasIterator enumerates all registers aliasing Reg.

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

constexpr bool isValid() const

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

MachineInstrBundleIterator< const MachineInstr > const_iterator

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)

Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.

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.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

iterator_range< succ_iterator > successors()

MachineInstrBundleIterator< MachineInstr > iterator

LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const

Return true if the specified register is in the live in set.

bool dominates(const MachineInstr *A, const MachineInstr *B) const

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

void setMaxCallFrameSize(uint64_t S)

bool hasVarSizedObjects() const

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

bool isObjectPreAllocated(int ObjectIdx) const

Return true if the object was pre-allocated into the local block.

uint64_t getStackSize() const

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

bool hasCalls() const

Return true if the current function has any function calls.

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.

LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment)

Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...

LLVM_ABI uint64_t estimateStackSize(const MachineFunction &MF) const

Estimate and return the size of the stack frame.

Align getObjectAlign(int ObjectIdx) const

Return the alignment of the specified stack object.

int64_t getObjectSize(int ObjectIdx) const

Return the size of the specified object.

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.

LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)

Create a spill slot at a fixed location on the stack.

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.

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

Properties which a MachineFunction may have at a given point in time.

unsigned addFrameInst(const MCCFIInstruction &Inst)

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.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

bool needsFrameMoves() const

True if this function needs frame moves for debug or exceptions.

MachineFrameInfo & getFrameInfo()

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

MCContext & getContext() const

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

MachineBasicBlock * getBlockNumbered(unsigned N) const

getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...

Function & getFunction()

Return the LLVM function that this machine code represents.

unsigned getNumBlockIDs() const

getNumBlockIDs - Return the number of MBB ID's allocated.

Ty * getInfo()

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

const MachineBasicBlock & front() const

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 & add(const MachineOperand &MO) const

const MachineInstrBuilder & addFrameIndex(int Idx) const

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

Add a new virtual register operand.

const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

instr_iterator getInstrIterator() const

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

bool isReturn(QueryType Type=AnyInBundle) const

const MachineBasicBlock * getParent() const

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

LLVM_ABI void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)

Copy implicit register operands from specified instruction to this instruction.

bool mayLoad(QueryType Type=AnyInBundle) const

Return true if this instruction could possibly read memory.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

@ MOStore

The memory access writes data.

MachineOperand class - Representation of each machine instruction operand.

void setSubReg(unsigned subReg)

unsigned getSubReg() const

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

void setIsKill(bool Val=true)

Register getReg() const

getReg - Returns the register number.

static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)

LLVM_ABI MachineBasicBlock * findNearestCommonDominator(ArrayRef< MachineBasicBlock * > Blocks) const

Returns the nearest common dominator of the given blocks.

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

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

A vector that has set insertion semantics.

size_type size() const

Determine the number of elements in the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

size_type count(const T &V) const

count - Return 1 if the element is in the set, 0 otherwise.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

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

int64_t getFixed() const

Returns the fixed component of the stack.

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...

Align getStackAlign() const

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

const TargetRegisterInfo & getRegisterInfo() const

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

CodeGenOptLevel getOptLevel() const

Returns the optimization level: None, Less, Default, or Aggressive.

bool isPositionIndependent() const

LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const

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

unsigned getID() const

Return the register class ID number.

ArrayRef< MCPhysReg > getRawAllocationOrder(const MachineFunction &MF, bool Rev=false) const

Returns the preferred order for allocating registers from this register class in MF.

bool hasSubClassEq(const TargetRegisterClass *RC) const

Returns true if RC is a sub-class of or equal to this class.

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

virtual const TargetInstrInfo * getInstrInfo() const

self_iterator getIterator()

#define llvm_unreachable(msg)

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

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ Kill

The last use of a register.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

void stable_sort(R &&Range)

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

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

LLVM_ABI raw_ostream & dbgs()

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

FunctionPass * createHexagonCallFrameInformation()

FunctionAddr VTableAddr Count

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.

class LLVM_GSL_OWNER SmallVector

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

unsigned getKillRegState(bool B)

uint16_t MCPhysReg

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

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

DWARFExpression::Operation Op

auto find_if(R &&Range, UnaryPredicate P)

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

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.

LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.

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

constexpr uint64_t value() const

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

static RegisterSet expandToSubRegs(RegisterRef R, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)

std::map< RegisterRef, RangeList > RegToRangeMap

static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)

Stack pointer relative access.