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

1

2

3

4

5

6

7

8

24

25using namespace llvm;

26

27namespace {

28

29

31 { SystemZ::R2D, 0x10 },

32 { SystemZ::R3D, 0x18 },

33 { SystemZ::R4D, 0x20 },

34 { SystemZ::R5D, 0x28 },

35 { SystemZ::R6D, 0x30 },

36 { SystemZ::R7D, 0x38 },

37 { SystemZ::R8D, 0x40 },

38 { SystemZ::R9D, 0x48 },

39 { SystemZ::R10D, 0x50 },

40 { SystemZ::R11D, 0x58 },

41 { SystemZ::R12D, 0x60 },

42 { SystemZ::R13D, 0x68 },

43 { SystemZ::R14D, 0x70 },

44 { SystemZ::R15D, 0x78 },

45 { SystemZ::F0D, 0x80 },

46 { SystemZ::F2D, 0x88 },

47 { SystemZ::F4D, 0x90 },

48 { SystemZ::F6D, 0x98 }

49};

50

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

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

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

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

56}

57

59 int LAO, Align TransAl,

60 bool StackReal, unsigned PointerSize)

62 PointerSize(PointerSize) {}

63

64std::unique_ptr

66 unsigned PtrSz =

69 return std::make_unique(PtrSz);

70 return std::make_unique(PtrSz);

71}

72

73namespace {

74struct SZFrameSortingObj {

75 bool IsValid = false;

76 uint32_t ObjectIndex = 0;

77 uint64_t ObjectSize = 0;

78 uint32_t D12Count = 0;

79 uint32_t DPairCount = 0;

80};

81typedef std::vector SZFrameObjVec;

82}

83

84

89

90

91

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

93 return;

95 for (auto &Obj : ObjectsToAllocate) {

96 SortingObjects[Obj].IsValid = true;

97 SortingObjects[Obj].ObjectIndex = Obj;

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

99 }

100

101

102

103 for (auto &MBB : MF)

104 for (auto &MI : MBB) {

105 if (MI.isDebugInstr())

106 continue;

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

109 if (!MO.isFI())

110 continue;

113 SortingObjects[Index].IsValid) {

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

115 SortingObjects[Index].DPairCount++;

117 SortingObjects[Index].D12Count++;

118 }

119 }

120 }

121

122

123

124

125

126

127

128

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

130

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

132 return A.IsValid;

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

134 return A.ObjectSize > 0;

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

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

137 if (ADensityCmp != BDensityCmp)

138 return ADensityCmp < BDensityCmp;

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

140 };

142

143

144

145 unsigned Idx = 0;

146 for (auto &Obj : SortingObjects) {

147

148 if (!Obj.IsValid)

149 break;

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

151 }

152}

153

156

157

158

159

160

161 return true;

162}

163

166 std::vector &CSI) const {

170 if (CSI.empty())

171 return true;

172

173 unsigned LowGPR = 0;

174 unsigned HighGPR = SystemZ::R15D;

176 for (auto &CS : CSI) {

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

181 LowGPR = Reg;

182 StartSPOffset = Offset;

183 }

185 int FrameIdx =

187 CS.setFrameIdx(FrameIdx);

188 } else

189 CS.setFrameIdx(INT32_MAX);

190 }

191

192

193

195 if (IsVarArg) {

196

197

198

203 if (StartSPOffset > Offset) {

204 LowGPR = Reg; StartSPOffset = Offset;

205 }

206 }

207 }

209

210

213 CurrOffset += StartSPOffset;

214

215 for (auto &CS : CSI) {

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

217 continue;

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

221 CurrOffset -= Size;

222 assert(CurrOffset % 8 == 0 &&

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

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

225 CS.setFrameIdx(FrameIdx);

226 }

227

228 return true;

229}

230

235

238 bool HasFP = hasFP(MF);

241

242

243

244

245

246 if (IsVarArg)

249

250

252 SavedRegs.set(SystemZ::R6D);

253 SavedRegs.set(SystemZ::R7D);

254 }

255

256

257

258 if (HasFP)

259 SavedRegs.set(SystemZ::R11D);

260

261

262

264 SavedRegs.set(SystemZ::R14D);

265

266

267

268

269

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

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

272 unsigned Reg = CSRegs[I];

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

274 SavedRegs.set(SystemZ::R15D);

275 break;

276 }

277 }

278}

279

282 Align(8), false, PointerSize),

283 RegSpillOffsets(0) {

284

285

286

287

288

289

290

291

292

293 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);

294 for (const auto &Entry : ELFSpillOffsetTable)

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

296}

297

298

299

300

301

303 unsigned GPR64, bool IsImplicit) {

305 MBB.getParent()->getSubtarget().getRegisterInfo();

307 bool IsLive = MBB.isLiveIn(GPR64) || MBB.isLiveIn(GPR32);

308 if (!IsLive || !IsImplicit) {

310 if (!IsLive)

311 MBB.addLiveIn(GPR64);

312 }

313}

314

319 return false;

320

326

327

329 if (SpillGPRs.LowGPR) {

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

332

333

335

336

339

340

342

343

344

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

349 }

350

351

352 if (IsVarArg)

355 }

356

357

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

361 MBB.addLiveIn(Reg);

362 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),

363 &SystemZ::FP64BitRegClass, Register());

364 }

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

366 MBB.addLiveIn(Reg);

367 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),

368 &SystemZ::VR128BitRegClass, Register());

369 }

370 }

371

372 return true;

373}

374

379 return false;

380

384 bool HasFP = hasFP(MF);

386

387

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

391 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),

392 &SystemZ::FP64BitRegClass, Register());

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

394 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),

395 &SystemZ::VR128BitRegClass, Register());

396 }

397

398

399

401 if (RestoreGPRs.LowGPR) {

402

403

404

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

407

408

410

411

414

415

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

418

419

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

423 SystemZ::GR64BitRegClass.contains(Reg))

425 }

426 }

427

428 return true;

429}

430

437

439

441

442

445

446

447 int64_t MaxArgOffset = 0;

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

453 }

454

455 uint64_t MaxReach = StackSize + MaxArgOffset;

457

458

459

460

461 RS->addScavengingFrameIndex(

463 RS->addScavengingFrameIndex(

465 }

466

467

468

469

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

473 MO.setIsKill(false);

474}

475

476

481 while (NumBytes) {

482 unsigned Opcode;

483 int64_t ThisVal = NumBytes;

485 Opcode = SystemZ::AGHI;

486 else {

487 Opcode = SystemZ::AGFI;

488

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

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

491 if (ThisVal < MinVal)

492 ThisVal = MinVal;

493 else if (ThisVal > MaxVal)

494 ThisVal = MaxVal;

495 }

498

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

500 NumBytes -= ThisVal;

501 }

502}

503

504

509 unsigned CFIIndex = MBB.getParent()->addFrameInst(

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

513}

514

515

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

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

527}

528

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

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

540 bool HasFP = hasFP(MF);

541

542

543

544

545

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

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

550 }

551 if (HasFP) {

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

554 }

556 return;

557 }

558

559

560

562

566

567

569 .addReg(SystemZ::R14D)

570 .addReg(SystemZ::R15D)

573

574

575

577 .getSpecialRegisters()

582

583

586 .addReg(SystemZ::R15D)

589 }

590

591

593

595

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

598 else

600

601

602 for (auto &Save : CSI) {

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

605 int FI = Save.getFrameIdx();

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

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

611 }

612 }

613 }

614

616

617

618

619 bool HasStackObject = false;

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

622 HasStackObject = true;

623 break;

624 }

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

627

630 : 0;

632

633 if (StackSize) {

634

635 int64_t Delta = -int64_t(StackSize);

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

639 if (!FreeProbe &&

641

642

643

644

647 }

648 else {

650

651

652 if (StoreBackchain)

657 if (StoreBackchain)

661 }

662 SPOffsetFromCFA += Delta;

663 }

664

665 if (HasFP) {

666

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

668 .addReg(SystemZ::R15D);

669

670

672

673

674

675

677 MBBJ.addLiveIn(SystemZ::R11D);

678 }

679

680

682 for (auto &Save : CSI) {

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

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

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

689 else

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

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

695 else

697 } else

698 continue;

699

700

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

706

708 nullptr, DwarfReg, SPOffsetFromCFA + Offset));

710 }

711

712

713 for (auto CFIIndex : CFIIndexes) {

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

716 }

717}

718

722 auto *ZII =

726

727

729 return;

730

731

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

733

734 uint64_t StackSize = MFFrame.getStackSize();

737 unsigned Opcode = MBBI->getOpcode();

738 if (Opcode != SystemZ::LMG)

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

740

741 unsigned AddrOpNo = 2;

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

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

745

746

747

748 if (!NewOpcode) {

751 NumBytes, ZII);

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

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

755 }

756

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

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

759 } else if (StackSize) {

762 }

763}

764

767 auto *ZII =

771

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

775 StackAllocMI = &MI;

776 break;

777 }

778 if (StackAllocMI == nullptr)

779 return;

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

782 uint64_t NumFullBlocks = StackSize / ProbeSize;

783 uint64_t Residual = StackSize % ProbeSize;

788

789

792 bool EmitCFI) -> void {

794 if (EmitCFI) {

795 SPOffsetFromCFA -= Size;

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

797 }

798

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

805 };

806

808 if (StoreBackchain)

811

814 if (NumFullBlocks < 3) {

815

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

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

818 } else {

819

820 uint64_t LoopAlloc = ProbeSize * NumFullBlocks;

821 SPOffsetFromCFA -= LoopAlloc;

822

823

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

825 .addReg(SystemZ::R15D);

829 ZII);

830

833 MBB->addSuccessor(LoopMBB);

836

837 MBB = LoopMBB;

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

843

844 MBB = DoneMBB;

847 }

848

849 if (Residual)

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

851

852 if (StoreBackchain)

856

858 if (DoneMBB != nullptr) {

859

861 }

862}

863

868

877

882 bool BackChain = Subtarget.hasBackChain();

883 bool SoftFloat = Subtarget.hasSoftFloat();

884 unsigned Offset = RegSpillOffsets[Reg];

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

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

887

888

889 Offset += BackChain ? 24 : 32;

890 else

892 }

894}

895

900 if (!FI) {

905 }

906 return FI;

907}

908

912 bool BackChain = Subtarget.hasBackChain();

913 bool SoftFloat = Subtarget.hasSoftFloat();

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

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

917 return HasPackedStackAttr && CallConv;

918}

919

922 Align(32), false,

923 PointerSize),

924 RegSpillOffsets(-1) {

925

926

927

928 RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);

929 for (const auto &Entry : XPLINKSpillOffsetTable)

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

931}

932

937 if (!FI) {

942 }

943 return FI;

944}

945

946

951 auto *Regs =

953

954

955

957 return false;

958

959

961 return false;

962

963

965 return false;

966

967

968

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

970 return false;

971

972

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

974 return false;

975

976

977

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

979 return false;

980

981

983 return false;

984

985

986

987

989 return false;

990

991 return true;

992}

993

996 std::vector &CSI) const {

1001 auto &GRRegClass = SystemZ::GR64BitRegClass;

1002

1003

1004

1005

1006

1007

1008

1009

1010

1012 if (IsLeaf)

1013 return true;

1014

1015

1016

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

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

1019

1020

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

1022

1023

1024

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

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

1027

1028

1029

1032

1033

1035 int LowRestoreOffset = INT32_MAX;

1037 int LowSpillOffset = INT32_MAX;

1039 int HighOffset = -1;

1040

1041

1043

1044 for (auto &CS : CSI) {

1046 int Offset = RegSpillOffsets[Reg];

1048 if (GRRegClass.contains(Reg)) {

1049 if (LowSpillOffset > Offset) {

1050 LowSpillOffset = Offset;

1051 LowSpillGPR = Reg;

1052 }

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

1054 LowRestoreOffset = Offset;

1055 LowRestoreGPR = Reg;

1056 }

1057

1058 if (Offset > HighOffset) {

1059 HighOffset = Offset;

1060 HighGPR = Reg;

1061 }

1062

1063

1064

1066 int FrameIdx =

1067 (FPSI && Offset == 0)

1068 ? FPSI

1070 CS.setFrameIdx(FrameIdx);

1072 }

1073 } else {

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

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

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

1080 CS.setFrameIdx(FrameIdx);

1081 }

1082 }

1083

1084

1085

1086 if (LowRestoreGPR)

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

1088

1089

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

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

1092

1093 return true;

1094}

1095

1100

1101 bool HasFP = hasFP(MF);

1104

1105

1106

1107 if (HasFP)

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

1109}

1110

1114 if (CSI.empty())

1115 return true;

1116

1124

1125

1126 if (SpillGPRs.LowGPR) {

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

1128 "Should be saving multiple registers");

1129

1130

1132

1133

1136

1137

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

1139

1140

1141

1142 MIB.addImm(SpillGPRs.GPROffset);

1143

1144

1145

1146 auto &GRRegClass = SystemZ::GR64BitRegClass;

1149 if (GRRegClass.contains(Reg))

1151 }

1152 }

1153

1154

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

1158 MBB.addLiveIn(Reg);

1159 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),

1160 &SystemZ::FP64BitRegClass, Register());

1161 }

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

1163 MBB.addLiveIn(Reg);

1164 TII->storeRegToStackSlot(MBB, MBBI, Reg, true, I.getFrameIdx(),

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

1166 }

1167 }

1168

1169 return true;

1170}

1171

1175

1176 if (CSI.empty())

1177 return false;

1178

1184

1186

1187

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

1191 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),

1192 &SystemZ::FP64BitRegClass, Register());

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

1194 TII->loadRegFromStackSlot(MBB, MBBI, Reg, I.getFrameIdx(),

1195 &SystemZ::VR128BitRegClass, Register());

1196 }

1197

1198

1199

1201 if (RestoreGPRs.LowGPR) {

1204

1206 .addReg(Regs.getStackPointerRegister())

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

1209 else {

1210

1212

1213

1216

1217

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

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

1220

1221

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

1226 }

1227 }

1228 }

1229

1230 return true;

1231}

1232

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

1243

1245

1246 bool HasFP = hasFP(MF);

1247

1248

1251

1252 const uint64_t StackSize = MFFrame.getStackSize();

1253

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

1255

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

1257 const int Operand = 3;

1258

1259

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

1261

1263 Offset -= StackSize;

1264 else

1265 StoreInstr = &*MBBI;

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

1268 } else

1270 }

1271

1272 if (StackSize) {

1274

1275 int64_t Delta = -int64_t(StackSize);

1276

1277

1278

1279

1280

1281 if (StoreInstr && HasFP) {

1282

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

1285 .addReg(SystemZ::R4D);

1286

1289 .addReg(SystemZ::R4D)

1292 }

1293

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

1295 ZII);

1296

1297

1298

1299

1300

1301

1302

1303 const uint64_t GuardPageSize = 1024 * 1024;

1304 if (StackSize > GuardPageSize) {

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

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

1307 }

1308 }

1309

1310 if (HasFP) {

1311

1313 Regs.getFramePointerRegister())

1314 .addReg(Regs.getStackPointerRegister());

1315

1316

1317

1318

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

1321 }

1322

1323

1326

1327 if (IsVarArg) {

1328

1329

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

1333 uint64_t StartOffset = MFFrame.getOffsetAdjustment() +

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

1336 unsigned Reg = GPRs[I];

1339 .addReg(Regs.getStackPointerRegister())

1340 .addImm(StartOffset)

1342 if (MBB.isLiveIn(Reg))

1343 MBB.addLiveIn(Reg);

1344 }

1345 }

1346}

1347

1356

1357

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

1359

1360 uint64_t StackSize = MFFrame.getStackSize();

1361 if (StackSize) {

1362 unsigned SPReg = Regs.getStackPointerRegister();

1366 }

1367 }

1368}

1369

1370

1371

1374 auto *ZII =

1376

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

1380 StackAllocMI = &MI;

1381 break;

1382 }

1383 if (StackAllocMI == nullptr)

1384 return;

1385

1386 bool NeedSaveSP = hasFP(MF);

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

1388 const int64_t SaveSlotR3 = 2192;

1389

1392

1393

1395

1396

1400

1401

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

1403 .addReg(SystemZ::R3D)

1406

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

1408 .addReg(SystemZ::R3D);

1409 if (NeedSaveArg) {

1410 if (!NeedSaveSP) {

1411

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

1414 .addReg(SystemZ::R3D);

1415 } else {

1416

1417

1418

1419

1420

1422 .addReg(SystemZ::R3D)

1423 .addReg(SystemZ::R4D)

1426 }

1427 }

1428

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

1433

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

1435 .addReg(SystemZ::R4D)

1436 .addReg(SystemZ::R3D)

1439

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

1443 .addMBB(StackExtMBB);

1444

1446 MBB.addSuccessor(NextMBB);

1447 MBB.addSuccessor(StackExtMBB);

1448 if (NeedSaveArg) {

1449 if (!NeedSaveSP) {

1450

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

1454 } else {

1455

1456

1457

1458

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

1461 .addReg(SystemZ::R0D);

1462

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

1465 .addReg(SystemZ::R3D)

1468 }

1469 }

1470

1471

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

1474

1476

1477

1479}

1480

1484

1490

1491

1493

1494

1497 return;

1498

1499

1500

1501

1502

1505

1506

1507

1508

1509

1510 int64_t LargestArgOffset = 0;

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

1515 }

1516 }

1517

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

1519 Regs.getStackPointerBias() + LargestArgOffset);

1520

1522

1523

1526 }

1527}

1528

1529

1534 auto *Regs =

1536

1538 if (StackSize == 0)

1539 return;

1540

1541

1542 StackSize += Regs->getCallFrameSize();

1544

1545

1546

1547

1548

1550 ++FrameIdx) {

1553 SPOffset -= StackSize;

1555 }

1556 }

1557}

unsigned const MachineRegisterInfo * MRI

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

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

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

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

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

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

Register const TargetRegisterInfo * TRI

static constexpr MCPhysReg SPReg

This file declares the machine register scavenger class.

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)

Definition SystemZFrameLowering.cpp:477

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

Definition SystemZFrameLowering.cpp:516

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

Definition SystemZFrameLowering.cpp:505

static bool isXPLeafCandidate(const MachineFunction &MF)

Definition SystemZFrameLowering.cpp:947

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

Definition SystemZFrameLowering.cpp:302

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.

LLVM_ABI StringRef getValueAsString() const

Return the attribute's value as a string.

bool test(unsigned Idx) const

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

Attribute getFnAttribute(Attribute::AttrKind Kind) const

Return the attribute for the given attribute kind.

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.

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

MCRegister getSubReg(MCRegister Reg, unsigned Idx) const

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

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

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

Add Succ as a successor of this MachineBasicBlock.

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.

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

void setMaxCallFrameSize(uint64_t S)

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

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

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

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.

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.

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.

LLVM_ABI 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)

CreateMachineInstr - Allocate a new MachineInstr.

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 & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const

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

Add a new virtual register operand.

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

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

Representation of each machine instruction.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

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

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

Definition SystemZFrameLowering.cpp:375

int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override

Definition SystemZFrameLowering.cpp:896

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

Order the symbols in the local stack frame.

Definition SystemZFrameLowering.cpp:85

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

assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.

Definition SystemZFrameLowering.cpp:164

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.

Definition SystemZFrameLowering.cpp:765

bool hasFPImpl(const MachineFunction &MF) const override

Definition SystemZFrameLowering.cpp:864

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

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

Definition SystemZFrameLowering.cpp:529

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

Definition SystemZFrameLowering.cpp:719

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 SystemZFrameLowering.cpp:869

bool usePackedStack(MachineFunction &MF) const

Definition SystemZFrameLowering.cpp:909

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

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

Definition SystemZFrameLowering.cpp:231

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

Definition SystemZFrameLowering.cpp:315

SystemZELFFrameLowering(unsigned PointerSize)

Definition SystemZFrameLowering.cpp:280

unsigned getRegSpillOffset(MachineFunction &MF, Register Reg) const

Definition SystemZFrameLowering.cpp:878

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

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

Definition SystemZFrameLowering.cpp:431

bool hasReservedCallFrame(const MachineFunction &MF) const override

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

Definition SystemZFrameLowering.cpp:154

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

Definition SystemZFrameLowering.cpp:65

unsigned getPointerSize() const

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

Definition SystemZFrameLowering.cpp:58

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.

Definition SystemZFrameLowering.cpp:1372

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

Definition SystemZFrameLowering.cpp:1172

int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const override

Definition SystemZFrameLowering.cpp:933

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

Definition SystemZFrameLowering.cpp:1348

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

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

Definition SystemZFrameLowering.cpp:1233

void determineFrameLayout(MachineFunction &MF) const

Definition SystemZFrameLowering.cpp:1530

SystemZXPLINKFrameLowering(unsigned PointerSize)

Definition SystemZFrameLowering.cpp:920

bool hasFPImpl(const MachineFunction &MF) const override

Definition SystemZFrameLowering.cpp:1481

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

Definition SystemZFrameLowering.cpp:1111

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

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

Definition SystemZFrameLowering.cpp:1485

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

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

Definition SystemZFrameLowering.cpp:1096

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

assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.

Definition SystemZFrameLowering.cpp:994

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

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

Align getStackAlign() const

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

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.

LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const

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

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

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

virtual const TargetLowering * getTargetLowering() const

#define llvm_unreachable(msg)

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

@ AnyReg

OBSOLETED - Used for stack based JavaScript calls.

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

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.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

unsigned getImplRegState(bool B)

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

constexpr bool isUInt(uint64_t x)

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

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.

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