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)
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 (.IsValid ||
.IsValid)
132 return A.IsValid;
133 if (.ObjectSize ||
.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
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 (.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,...