LLVM: lib/Target/SystemZ/SystemZFrameLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

22

23using namespace llvm;

24

25namespace {

26

27

29 { SystemZ::R2D, 0x10 },

30 { SystemZ::R3D, 0x18 },

31 { SystemZ::R4D, 0x20 },

32 { SystemZ::R5D, 0x28 },

33 { SystemZ::R6D, 0x30 },

34 { SystemZ::R7D, 0x38 },

35 { SystemZ::R8D, 0x40 },

36 { SystemZ::R9D, 0x48 },

37 { SystemZ::R10D, 0x50 },

38 { SystemZ::R11D, 0x58 },

39 { SystemZ::R12D, 0x60 },

40 { SystemZ::R13D, 0x68 },

41 { SystemZ::R14D, 0x70 },

42 { SystemZ::R15D, 0x78 },

43 { SystemZ::F0D, 0x80 },

44 { SystemZ::F2D, 0x88 },

45 { SystemZ::F4D, 0x90 },

46 { SystemZ::F6D, 0x98 }

47};

48

50 {SystemZ::R4D, 0x00}, {SystemZ::R5D, 0x08}, {SystemZ::R6D, 0x10},

51 {SystemZ::R7D, 0x18}, {SystemZ::R8D, 0x20}, {SystemZ::R9D, 0x28},

52 {SystemZ::R10D, 0x30}, {SystemZ::R11D, 0x38}, {SystemZ::R12D, 0x40},

53 {SystemZ::R13D, 0x48}, {SystemZ::R14D, 0x50}, {SystemZ::R15D, 0x58}};

54}

55

57 int LAO, Align TransAl,

58 bool StackReal, unsigned PointerSize)

60 PointerSize(PointerSize) {}

61

62std::unique_ptr

64 unsigned PtrSz =

67 return std::make_unique(PtrSz);

68 return std::make_unique(PtrSz);

69}

70

71namespace {

72struct SZFrameSortingObj {

73 bool IsValid = false;

74 uint32_t ObjectIndex = 0;

75 uint64_t ObjectSize = 0;

76 uint32_t D12Count = 0;

77 uint32_t DPairCount = 0;

78};

79typedef std::vector SZFrameObjVec;

80}

81

82

87

88

89

90 if (ObjectsToAllocate.size() <= 1)

91 return;

93 for (auto &Obj : ObjectsToAllocate) {

94 SortingObjects[Obj].IsValid = true;

95 SortingObjects[Obj].ObjectIndex = Obj;

96 SortingObjects[Obj].ObjectSize = MFI.getObjectSize(Obj);

97 }

98

99

100

101 for (auto &MBB : MF)

102 for (auto &MI : MBB) {

103 if (MI.isDebugInstr())

104 continue;

105 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {

107 if (!MO.isFI())

108 continue;

111 SortingObjects[Index].IsValid) {

112 if (TII->hasDisplacementPairInsn(MI.getOpcode()))

113 SortingObjects[Index].DPairCount++;

115 SortingObjects[Index].D12Count++;

116 }

117 }

118 }

119

120

121

122

123

124

125

126

127 auto CmpD12 = [](const SZFrameSortingObj &A, const SZFrameSortingObj &B) {

128

129 if (A.IsValid || B.IsValid)

130 return A.IsValid;

131 if (A.ObjectSize || B.ObjectSize)

132 return A.ObjectSize > 0;

133 uint64_t ADensityCmp = A.D12Count * B.ObjectSize;

134 uint64_t BDensityCmp = B.D12Count * A.ObjectSize;

135 if (ADensityCmp != BDensityCmp)

136 return ADensityCmp < BDensityCmp;

137 return A.DPairCount * B.ObjectSize < B.DPairCount * A.ObjectSize;

138 };

139 std::stable_sort(SortingObjects.begin(), SortingObjects.end(), CmpD12);

140

141

142

143 unsigned Idx = 0;

144 for (auto &Obj : SortingObjects) {

145

146 if (!Obj.IsValid)

147 break;

148 ObjectsToAllocate[Idx++] = Obj.ObjectIndex;

149 }

150}

151

154

155

156

157

158

159 return true;

160}

161

164 std::vector &CSI) const {

168 if (CSI.empty())

169 return true;

170

171 unsigned LowGPR = 0;

172 unsigned HighGPR = SystemZ::R15D;

174 for (auto &CS : CSI) {

178 if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {

179 LowGPR = Reg;

180 StartSPOffset = Offset;

181 }

183 int FrameIdx =

185 CS.setFrameIdx(FrameIdx);

186 } else

187 CS.setFrameIdx(INT32_MAX);

188 }

189

190

191

193 if (IsVarArg) {

194

195

196

201 if (StartSPOffset > Offset) {

202 LowGPR = Reg; StartSPOffset = Offset;

203 }

204 }

205 }

207

208

211 CurrOffset += StartSPOffset;

212

213 for (auto &CS : CSI) {

214 if (CS.getFrameIdx() != INT32_MAX)

215 continue;

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

219 CurrOffset -= Size;

220 assert(CurrOffset % 8 == 0 &&

221 "8-byte alignment required for for all register save slots");

222 int FrameIdx = MFFrame.CreateFixedSpillStackObject(Size, CurrOffset);

223 CS.setFrameIdx(FrameIdx);

224 }

225

226 return true;

227}

228

233

236 bool HasFP = hasFP(MF);

239

240

241

242

243

244 if (IsVarArg)

247

248

250 SavedRegs.set(SystemZ::R6D);

251 SavedRegs.set(SystemZ::R7D);

252 }

253

254

255

256 if (HasFP)

257 SavedRegs.set(SystemZ::R11D);

258

259

260

262 SavedRegs.set(SystemZ::R14D);

263

264

265

266

267

268 const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);

269 for (unsigned I = 0; CSRegs[I]; ++I) {

270 unsigned Reg = CSRegs[I];

271 if (SystemZ::GR64BitRegClass.contains(Reg) && SavedRegs.test(Reg)) {

272 SavedRegs.set(SystemZ::R15D);

273 break;

274 }

275 }

276}

277

280 Align(8), false, PointerSize),

281 RegSpillOffsets(0) {

282

283

284

285

286

287

288

289

290

291 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);

292 for (const auto &Entry : ELFSpillOffsetTable)

293 RegSpillOffsets[Entry.Reg] = Entry.Offset;

294}

295

296

297

298

299

301 unsigned GPR64, bool IsImplicit) {

306 if (!IsLive || !IsImplicit) {

308 if (!IsLive)

310 }

311}

312

317 return false;

318

324

325

327 if (SpillGPRs.LowGPR) {

329 "Should be saving %r15 and something else");

330

331

333

334

337

338

340

341

342

345 if (SystemZ::GR64BitRegClass.contains(Reg))

347 }

348

349

350 if (IsVarArg)

353 }

354

355

358 if (SystemZ::FP64BitRegClass.contains(Reg)) {

361 &SystemZ::FP64BitRegClass, TRI, Register());

362 }

363 if (SystemZ::VR128BitRegClass.contains(Reg)) {

366 &SystemZ::VR128BitRegClass, TRI, Register());

367 }

368 }

369

370 return true;

371}

372

377 return false;

378

382 bool HasFP = hasFP(MF);

384

385

388 if (SystemZ::FP64BitRegClass.contains(Reg))

390 &SystemZ::FP64BitRegClass, TRI, Register());

391 if (SystemZ::VR128BitRegClass.contains(Reg))

393 &SystemZ::VR128BitRegClass, TRI, Register());

394 }

395

396

397

399 if (RestoreGPRs.LowGPR) {

400

401

402

404 "Should be loading %r15 and something else");

405

406

408

409

412

413

414 MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D);

416

417

420 if (Reg != RestoreGPRs.LowGPR && Reg != RestoreGPRs.HighGPR &&

421 SystemZ::GR64BitRegClass.contains(Reg))

423 }

424 }

425

426 return true;

427}

428

435

437

439

440

443

444

445 int64_t MaxArgOffset = 0;

450 MaxArgOffset = std::max(MaxArgOffset, ArgOffset);

451 }

452

453 uint64_t MaxReach = StackSize + MaxArgOffset;

454 if (!isUInt<12>(MaxReach)) {

455

456

457

458

463 }

464

465

466

467

470 for (auto &MO : MRI->use_nodbg_operands(SystemZ::R6D))

471 MO.setIsKill(false);

472}

473

474

477 Register Reg, int64_t NumBytes,

479 while (NumBytes) {

480 unsigned Opcode;

481 int64_t ThisVal = NumBytes;

482 if (isInt<16>(NumBytes))

483 Opcode = SystemZ::AGHI;

484 else {

485 Opcode = SystemZ::AGFI;

486

487 int64_t MinVal = -uint64_t(1) << 31;

488 int64_t MaxVal = (int64_t(1) << 31) - 8;

489 if (ThisVal < MinVal)

490 ThisVal = MinVal;

491 else if (ThisVal > MaxVal)

492 ThisVal = MaxVal;

493 }

496

497 MI->getOperand(3).setIsDead();

498 NumBytes -= ThisVal;

499 }

500}

501

502

509 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))

511}

512

513

520 unsigned RegNum = MRI->getDwarfRegNum(Reg, true);

523 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))

525}

526

529 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");

537 const std::vector &CSI = MFFrame.getCalleeSavedInfo();

538 bool HasFP = hasFP(MF);

539

540

541

542

543

545 if (MFFrame.getStackSize() > 2048 * sizeof(long)) {

547 "Pre allocated stack space for GHC function is too small");

548 }

549 if (HasFP) {

551 "In GHC calling convention a frame pointer is not supported");

552 }

554 return;

555 }

556

557

558

560

561

563

565

566 if (MBBI != MBB.end() && MBBI->getOpcode() == SystemZ::STMG)

568 else

570

571

572 for (auto &Save : CSI) {

573 Register Reg = Save.getReg();

574 if (SystemZ::GR64BitRegClass.contains(Reg)) {

575 int FI = Save.getFrameIdx();

578 nullptr, MRI->getDwarfRegNum(Reg, true), Offset));

579 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))

581 }

582 }

583 }

584

586

587

588

589 bool HasStackObject = false;

590 for (unsigned i = 0, e = MFFrame.getObjectIndexEnd(); i != e; ++i)

592 HasStackObject = true;

593 break;

594 }

595 if (HasStackObject || MFFrame.hasCalls())

597

600 : 0;

602

603 if (StackSize) {

604

605 int64_t Delta = -int64_t(StackSize);

606 const unsigned ProbeSize = TLI.getStackProbeSize(MF);

609 if (!FreeProbe &&

611

612

613

614

617 }

618 else {

620

621

622 if (StoreBackchain)

627 if (StoreBackchain)

631 }

632 SPOffsetFromCFA += Delta;

633 }

634

635 if (HasFP) {

636

637 BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R11D)

638 .addReg(SystemZ::R15D);

639

640

642

643

644

645

647 MBBJ.addLiveIn(SystemZ::R11D);

648 }

649

650

652 for (auto &Save : CSI) {

653 Register Reg = Save.getReg();

654 if (SystemZ::FP64BitRegClass.contains(Reg)) {

656 (MBBI->getOpcode() == SystemZ::STD ||

657 MBBI->getOpcode() == SystemZ::STDY))

659 else

661 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {

663 MBBI->getOpcode() == SystemZ::VST)

665 else

667 } else

668 continue;

669

670

671 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);

676

678 nullptr, DwarfReg, SPOffsetFromCFA + Offset));

680 }

681

682

683 for (auto CFIIndex : CFIIndexes) {

684 BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION))

686 }

687}

688

692 auto *ZII =

696

697

699 return;

700

701

702 assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");

703

704 uint64_t StackSize = MFFrame.getStackSize();

707 unsigned Opcode = MBBI->getOpcode();

708 if (Opcode != SystemZ::LMG)

709 llvm_unreachable("Expected to see callee-save register restore code");

710

711 unsigned AddrOpNo = 2;

713 uint64_t Offset = StackSize + MBBI->getOperand(AddrOpNo + 1).getImm();

714 unsigned NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);

715

716

717

718 if (!NewOpcode) {

721 NumBytes, ZII);

723 NewOpcode = ZII->getOpcodeForOffset(Opcode, Offset);

724 assert(NewOpcode && "No restore instruction available");

725 }

726

727 MBBI->setDesc(ZII->get(NewOpcode));

728 MBBI->getOperand(AddrOpNo + 1).ChangeToImmediate(Offset);

729 } else if (StackSize) {

732 }

733}

734

737 auto *ZII =

741

744 if (MI.getOpcode() == SystemZ::PROBED_STACKALLOC) {

745 StackAllocMI = &MI;

746 break;

747 }

748 if (StackAllocMI == nullptr)

749 return;

751 const unsigned ProbeSize = TLI.getStackProbeSize(MF);

752 uint64_t NumFullBlocks = StackSize / ProbeSize;

753 uint64_t Residual = StackSize % ProbeSize;

758

759

762 bool EmitCFI) -> void {

764 if (EmitCFI) {

765 SPOffsetFromCFA -= Size;

766 buildCFAOffs(InsMBB, InsPt, DL, SPOffsetFromCFA, ZII);

767 }

768

771 BuildMI(InsMBB, InsPt, DL, ZII->get(SystemZ::CG))

775 };

776

778 if (StoreBackchain)

781

784 if (NumFullBlocks < 3) {

785

786 for (unsigned int i = 0; i < NumFullBlocks; i++)

787 allocateAndProbe(*MBB, MBBI, ProbeSize, true);

788 } else {

789

790 uint64_t LoopAlloc = ProbeSize * NumFullBlocks;

791 SPOffsetFromCFA -= LoopAlloc;

792

793

794 BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR), SystemZ::R0D)

795 .addReg(SystemZ::R15D);

799 ZII);

800

806

807 MBB = LoopMBB;

808 allocateAndProbe(*MBB, MBB->end(), ProbeSize, false);

813

814 MBB = DoneMBB;

817 }

818

819 if (Residual)

820 allocateAndProbe(*MBB, MBBI, Residual, true);

821

822 if (StoreBackchain)

826

828 if (DoneMBB != nullptr) {

829

831 }

832}

833

837}

838

841

842

846}

847

852 bool BackChain = Subtarget.hasBackChain();

853 bool SoftFloat = Subtarget.hasSoftFloat();

854 unsigned Offset = RegSpillOffsets[Reg];

855 if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {

856 if (SystemZ::GR64BitRegClass.contains(Reg))

857

858

859 Offset += BackChain ? 24 : 32;

860 else

862 }

864}

865

870 if (!FI) {

875 }

876 return FI;

877}

878

882 bool BackChain = Subtarget.hasBackChain();

883 bool SoftFloat = Subtarget.hasSoftFloat();

884 if (HasPackedStackAttr && BackChain && !SoftFloat)

885 report_fatal_error("packed-stack + backchain + hard-float is unsupported.");

887 return HasPackedStackAttr && CallConv;

888}

889

892 Align(32), false,

893 PointerSize),

894 RegSpillOffsets(-1) {

895

896

897

898 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);

899 for (const auto &Entry : XPLINKSpillOffsetTable)

900 RegSpillOffsets[Entry.Reg] = Entry.Offset;

901}

902

907 if (!FI) {

912 }

913 return FI;

914}

915

916

921 auto *Regs =

923

924

925

927 return false;

928

929

931 return false;

932

933

935 return false;

936

937

938

939 if (MRI.isPhysRegModified(Regs->getStackPointerRegister()))

940 return false;

941

942

943 if (MRI.isPhysRegModified(Regs->getAddressOfCalleeRegister()))

944 return false;

945

946

947

948 if (MRI.isPhysRegModified(Regs->getReturnFunctionAddressRegister()))

949 return false;

950

951

953 return false;

954

955

956

957

959 return false;

960

961 return true;

962}

963

966 std::vector &CSI) const {

971 auto &GRRegClass = SystemZ::GR64BitRegClass;

972

973

974

975

976

977

978

979

980

982 if (IsLeaf)

983 return true;

984

985

986

987 CSI.push_back(CalleeSavedInfo(Regs.getAddressOfCalleeRegister()));

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

989

990

991 CSI.push_back(CalleeSavedInfo(Regs.getReturnFunctionAddressRegister()));

992

993

994

995 if (hasFP(MF) || Subtarget.hasBackChain())

996 CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));

997

998

999

1002

1003

1005 int LowRestoreOffset = INT32_MAX;

1007 int LowSpillOffset = INT32_MAX;

1009 int HighOffset = -1;

1010

1011

1013

1014 for (auto &CS : CSI) {

1016 int Offset = RegSpillOffsets[Reg];

1018 if (GRRegClass.contains(Reg)) {

1019 if (LowSpillOffset > Offset) {

1020 LowSpillOffset = Offset;

1021 LowSpillGPR = Reg;

1022 }

1023 if (CS.isRestored() && LowRestoreOffset > Offset) {

1024 LowRestoreOffset = Offset;

1025 LowRestoreGPR = Reg;

1026 }

1027

1028 if (Offset > HighOffset) {

1029 HighOffset = Offset;

1030 HighGPR = Reg;

1031 }

1032

1033

1034

1036 int FrameIdx =

1037 (FPSI && Offset == 0)

1038 ? FPSI

1040 CS.setFrameIdx(FrameIdx);

1042 }

1043 } else {

1046 Align Alignment = TRI->getSpillAlign(*RC);

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

1048 Alignment = std::min(Alignment, getStackAlign());

1050 CS.setFrameIdx(FrameIdx);

1051 }

1052 }

1053

1054

1055

1056 if (LowRestoreGPR)

1057 MFI->setRestoreGPRRegs(LowRestoreGPR, HighGPR, LowRestoreOffset);

1058

1059

1060 assert(LowSpillGPR && "Expected registers to spill");

1061 MFI->setSpillGPRRegs(LowSpillGPR, HighGPR, LowSpillOffset);

1062

1063 return true;

1064}

1065

1070

1071 bool HasFP = hasFP(MF);

1074

1075

1076

1077 if (HasFP)

1078 SavedRegs.set(Regs.getFramePointerRegister());

1079}

1080

1084 if (CSI.empty())

1085 return true;

1086

1094

1095

1096 if (SpillGPRs.LowGPR) {

1097 assert(SpillGPRs.LowGPR != SpillGPRs.HighGPR &&

1098 "Should be saving multiple registers");

1099

1100

1102

1103

1106

1107

1108 MIB.addReg(Regs.getStackPointerRegister());

1109

1110

1111

1112 MIB.addImm(SpillGPRs.GPROffset);

1113

1114

1115

1116 auto &GRRegClass = SystemZ::GR64BitRegClass;

1119 if (GRRegClass.contains(Reg))

1121 }

1122 }

1123

1124

1127 if (SystemZ::FP64BitRegClass.contains(Reg)) {

1130 &SystemZ::FP64BitRegClass, TRI, Register());

1131 }

1132 if (SystemZ::VR128BitRegClass.contains(Reg)) {

1135 &SystemZ::VR128BitRegClass, TRI, Register());

1136 }

1137 }

1138

1139 return true;

1140}

1141

1145

1146 if (CSI.empty())

1147 return false;

1148

1154

1156

1157

1160 if (SystemZ::FP64BitRegClass.contains(Reg))

1162 &SystemZ::FP64BitRegClass, TRI, Register());

1163 if (SystemZ::VR128BitRegClass.contains(Reg))

1165 &SystemZ::VR128BitRegClass, TRI, Register());

1166 }

1167

1168

1169

1171 if (RestoreGPRs.LowGPR) {

1172 assert(isInt<20>(Regs.getStackPointerBias() + RestoreGPRs.GPROffset));

1174

1176 .addReg(Regs.getStackPointerRegister())

1177 .addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset)

1179 else {

1180

1182

1183

1186

1187

1188 MIB.addReg(Regs.getStackPointerRegister());

1189 MIB.addImm(Regs.getStackPointerBias() + RestoreGPRs.GPROffset);

1190

1191

1194 if (Reg > RestoreGPRs.LowGPR && Reg < RestoreGPRs.HighGPR)

1196 }

1197 }

1198 }

1199

1200 return true;

1201}

1202

1205 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");

1213

1215

1216 bool HasFP = hasFP(MF);

1217

1218

1221

1222 const uint64_t StackSize = MFFrame.getStackSize();

1223

1224 if (ZFI->getSpillGPRRegs().LowGPR) {

1225

1226 if ((MBBI != MBB.end()) && ((MBBI->getOpcode() == SystemZ::STMG))) {

1227 const int Operand = 3;

1228

1229

1230 Offset = Regs.getStackPointerBias() + MBBI->getOperand(Operand).getImm();

1231

1232 if (isInt<20>(Offset - StackSize))

1233 Offset -= StackSize;

1234 else

1235 StoreInstr = &*MBBI;

1236 MBBI->getOperand(Operand).setImm(Offset);

1238 } else

1240 }

1241

1242 if (StackSize) {

1244

1245 int64_t Delta = -int64_t(StackSize);

1246

1247

1248

1249

1250

1251 if (StoreInstr && HasFP) {

1252

1253 BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::LGR))

1255 .addReg(SystemZ::R4D);

1256

1259 .addReg(SystemZ::R4D)

1262 }

1263

1264 emitIncrement(MBB, InsertPt, DL, Regs.getStackPointerRegister(), Delta,

1265 ZII);

1266

1267

1268

1269

1270

1271

1272

1273 const uint64_t GuardPageSize = 1024 * 1024;

1274 if (StackSize > GuardPageSize) {

1275 assert(StoreInstr && "Wrong insertion point");

1276 BuildMI(MBB, InsertPt, DL, ZII->get(SystemZ::XPLINK_STACKALLOC));

1277 }

1278 }

1279

1280 if (HasFP) {

1281

1283 Regs.getFramePointerRegister())

1284 .addReg(Regs.getStackPointerRegister());

1285

1286

1287

1288

1290 B.addLiveIn(Regs.getFramePointerRegister());

1291 }

1292

1293

1296

1297 if (IsVarArg) {

1298

1299

1300 unsigned FixedRegs = ZFI->getVarArgsFirstGPR() + ZFI->getVarArgsFirstFPR();

1303 uint64_t StartOffset = MFFrame.getOffsetAdjustment() +

1304 MFFrame.getStackSize() + Regs.getCallFrameSize() +

1306 unsigned Reg = GPRs[I];

1309 .addReg(Regs.getStackPointerRegister())

1310 .addImm(StartOffset)

1314 }

1315 }

1316}

1317

1326

1327

1328 assert(MBBI->isReturn() && "Can only insert epilogue into returning blocks");

1329

1330 uint64_t StackSize = MFFrame.getStackSize();

1331 if (StackSize) {

1332 unsigned SPReg = Regs.getStackPointerRegister();

1336 }

1337 }

1338}

1339

1340

1341

1344 auto *ZII =

1346

1349 if (MI.getOpcode() == SystemZ::XPLINK_STACKALLOC) {

1350 StackAllocMI = &MI;

1351 break;

1352 }

1353 if (StackAllocMI == nullptr)

1354 return;

1355

1356 bool NeedSaveSP = hasFP(MF);

1357 bool NeedSaveArg = PrologMBB.isLiveIn(SystemZ::R3D);

1358 const int64_t SaveSlotR3 = 2192;

1359

1362

1363

1365

1366

1370

1371

1372 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::LG), SystemZ::R3D)

1373 .addReg(SystemZ::R3D)

1376

1377 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::CallBASR_STACKEXT))

1378 .addReg(SystemZ::R3D);

1379 if (NeedSaveArg) {

1380 if (!NeedSaveSP) {

1381

1382 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))

1384 .addReg(SystemZ::R3D);

1385 } else {

1386

1387

1388

1389

1390

1392 .addReg(SystemZ::R3D)

1393 .addReg(SystemZ::R4D)

1396 }

1397 }

1398

1399 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::LLGT), SystemZ::R3D)

1403

1404 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::CG))

1405 .addReg(SystemZ::R4D)

1406 .addReg(SystemZ::R3D)

1409

1410 BuildMI(MBB, StackAllocMI, DL, ZII->get(SystemZ::BRC))

1413 .addMBB(StackExtMBB);

1414

1418 if (NeedSaveArg) {

1419 if (!NeedSaveSP) {

1420

1421 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))

1424 } else {

1425

1426

1427

1428

1429 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LGR))

1431 .addReg(SystemZ::R0D);

1432

1433 BuildMI(*NextMBB, StackAllocMI, DL, ZII->get(SystemZ::LG))

1435 .addReg(SystemZ::R3D)

1438 }

1439 }

1440

1441

1442 BuildMI(StackExtMBB, DL, ZII->get(SystemZ::J)).addMBB(NextMBB);

1444

1446

1447

1449}

1450

1453}

1454

1460

1461

1463

1464

1467 return;

1468

1469

1470

1471

1472

1475

1476

1477

1478

1479

1480 int64_t LargestArgOffset = 0;

1484 LargestArgOffset = std::max(ObjOffset, LargestArgOffset);

1485 }

1486 }

1487

1488 uint64_t MaxReach = (StackSize + Regs.getCallFrameSize() +

1489 Regs.getStackPointerBias() + LargestArgOffset);

1490

1491 if (!isUInt<12>(MaxReach)) {

1492

1493

1496 }

1497}

1498

1499

1504 auto *Regs =

1506

1508 if (StackSize == 0)

1509 return;

1510

1511

1512 StackSize += Regs->getCallFrameSize();

1514

1515

1516

1517

1518

1520 ++FrameIdx) {

1523 SPOffset -= StackSize;

1525 }

1526 }

1527}

unsigned const MachineRegisterInfo * MRI

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

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

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

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

const HexagonInstrInfo * TII

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

unsigned const TargetRegisterInfo * TRI

static constexpr Register SPReg

This file declares the machine register scavenger class.

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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

static void emitIncrement(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &DL, Register Reg, int64_t NumBytes, const TargetInstrInfo *TII)

static void buildDefCFAReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned Reg, const SystemZInstrInfo *ZII)

static void buildCFAOffs(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, int Offset, const SystemZInstrInfo *ZII)

static bool isXPLeafCandidate(const MachineFunction &MF)

static void addSavedGPR(MachineBasicBlock &MBB, MachineInstrBuilder &MIB, unsigned GPR64, bool IsImplicit)

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

bool empty() const

empty - Check if the array is empty.

bool test(unsigned Idx) const

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

CallingConv::ID getCallingConv() const

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

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.

void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override

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

void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override

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

static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})

.cfi_def_cfa_register modifies a rule for computing CFA.

static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})

.cfi_offset Previous value of Register is saved at offset Offset from CFA.

static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})

.cfi_def_cfa_offset modifies a rule for computing CFA.

const MCRegisterInfo * getRegisterInfo() const

MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...

const BasicBlock * getBasicBlock() const

Return the LLVM basic block that this instance corresponded to originally.

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

Add Succ as a successor of this MachineBasicBlock.

iterator getLastNonDebugInstr(bool SkipPseudoOp=true)

Returns an iterator to the last non-debug instruction in the basic block, or end().

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.

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

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

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

void setMaxCallFrameSize(uint64_t S)

int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)

Create a new object at a fixed location on the stack.

bool hasVarSizedObjects() const

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

uint64_t getStackSize() const

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

bool adjustsStack() const

Return true if this function adjusts the stack – e.g., when calling another function.

int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)

Create a new statically sized stack object, returning a nonnegative identifier to represent it.

bool hasCalls() const

Return true if the current function has any function calls.

void setObjectOffset(int ObjectIdx, int64_t SPOffset)

Set the stack frame offset of the specified object.

uint64_t getMaxCallFrameSize() const

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

int CreateSpillStackObject(uint64_t Size, Align Alignment)

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

uint64_t estimateStackSize(const MachineFunction &MF) const

Estimate and return the size of the stack frame.

void setStackID(int ObjectIdx, uint8_t ID)

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.

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

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

uint8_t getStackID(int ObjectIdx) const

int64_t getObjectOffset(int ObjectIdx) const

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

void setStackSize(uint64_t Size)

Set the size of the stack.

int getObjectIndexBegin() const

Return the minimum frame object index.

bool isDeadObjectIndex(int ObjectIdx) const

Returns true if the specified index corresponds to a dead object.

void setOffsetAdjustment(int64_t Adj)

Set the correction for frame offsets.

unsigned addFrameInst(const MCCFIInstruction &Inst)

const TargetSubtargetInfo & getSubtarget() const

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

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.

MachineFrameInfo & getFrameInfo()

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

void push_back(MachineBasicBlock *MBB)

MCContext & getContext() const

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const std::vector< LandingPadInfo > & getLandingPads() const

Return a reference to the landing pad info for the current function.

Ty * getInfo()

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

const MachineBasicBlock & front() const

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

CreateMachineBasicBlock - Allocate a new MachineBasicBlock.

const TargetMachine & getTarget() const

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

const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

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

Add a new virtual register operand.

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

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

Representation of each machine instruction.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

const MachineOperand & getOperand(unsigned i) const

A description of a memory reference used in the backend.

@ MOVolatile

The memory access is volatile.

@ MOLoad

The memory access reads data.

MachineOperand class - Representation of each machine instruction operand.

bool isFI() const

isFI - Tests if this is a MO_FrameIndex operand.

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

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

void addScavengingFrameIndex(int FI)

Add a scavenging frame index.

Wrapper class representing virtual and physical registers.

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.

StackOffset holds a fixed and a scalable offset in bytes.

int64_t getFixed() const

Returns the fixed component of the stack.

static StackOffset getFixed(int64_t Fixed)

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

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

int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override

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

Order the symbols in the local stack frame.

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

unsigned getBackchainOffset(MachineFunction &MF) const override

void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override

Replace a StackProbe stub (if any) with the actual probe code inline.

bool hasFPImpl(const MachineFunction &MF) const override

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

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

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

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

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

bool usePackedStack(MachineFunction &MF) const

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

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

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

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

SystemZELFFrameLowering(unsigned PointerSize)

unsigned getRegSpillOffset(MachineFunction &MF, Register Reg) const

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

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

bool hasReservedCallFrame(const MachineFunction &MF) const override

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

static std::unique_ptr< SystemZFrameLowering > create(const SystemZSubtarget &STI)

unsigned getPointerSize() const

SystemZFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl, bool StackReal, unsigned PointerSize)

Register getVarArgsFirstGPR() const

int getFramePointerSaveIndex() const

SystemZ::GPRRegs getRestoreGPRRegs() const

void setRestoreGPRRegs(Register Low, Register High, unsigned Offs)

void setFramePointerSaveIndex(int Idx)

SystemZ::GPRRegs getSpillGPRRegs() const

void setSpillGPRRegs(Register Low, Register High, unsigned Offs)

const SystemZInstrInfo * getInstrInfo() const override

const SystemZTargetLowering * getTargetLowering() const override

bool isTargetXPLINK64() const

SystemZCallingConventionRegisters * getSpecialRegisters() const

XPLINK64 calling convention specific use registers Particular to z/OS when in 64 bit mode.

void inlineStackProbe(MachineFunction &MF, MachineBasicBlock &PrologMBB) const override

Replace a StackProbe stub (if any) with the actual probe code inline.

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

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

int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override

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

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

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

void determineFrameLayout(MachineFunction &MF) const

SystemZXPLINKFrameLowering(unsigned PointerSize)

bool hasFPImpl(const MachineFunction &MF) const override

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

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

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

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

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

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

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

Information about stack frame layout on the target.

bool hasFP(const MachineFunction &MF) const

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

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

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

int getOffsetOfLocalArea() const

getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...

Align getStackAlign() const

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

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.

const TargetMachine & getTargetMachine() const

virtual bool hasInlineStackProbe(const MachineFunction &MF) const

unsigned getPointerSize(unsigned AS) const

Get the pointer size for this target.

bool DisableFramePointerElim(const MachineFunction &MF) const

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

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

MCRegister getSubReg(MCRegister Reg, unsigned Idx) const

Returns the physical register number of sub-register "Index" for physical register RegNo.

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetLowering * getTargetLowering() const

#define llvm_unreachable(msg)

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

@ GHC

Used by the Glasgow Haskell Compiler (GHC).

@ Define

Register definition.

@ Kill

The last use of a register.

@ Undef

Value of the register doesn't matter.

const int64_t ELFCallFrameSize

const int64_t ELFCFAOffsetFromInitialSP

MachineBasicBlock * splitBlockBefore(MachineBasicBlock::iterator MI, MachineBasicBlock *MBB)

const unsigned CCMASK_CMP_GT

MachineBasicBlock * emitBlockAfter(MachineBasicBlock *MBB)

const unsigned CCMASK_ICMP

const unsigned XPLINK64NumArgGPRs

const MCPhysReg ELFArgGPRs[ELFNumArgGPRs]

const unsigned CCMASK_CMP_LT

const unsigned ELFNumArgGPRs

const MCPhysReg XPLINK64ArgGPRs[XPLINK64NumArgGPRs]

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.

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

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

unsigned getImplRegState(bool B)

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

unsigned getKillRegState(bool B)

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)

Convenience function for recomputing live-in's for a set of MBBs until the computation converges.

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

This class contains a discriminated union of information about pointers in memory operands,...