bool IsLargeFrame = !isInt<16>(NegFrameSize);
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned MaxAlign = MFI.getMaxAlignment();
+ bool HasRedZone = Subtarget.isPPC64() || !Subtarget.isSVR4ABI();
- return IsLargeFrame && HasBP && MaxAlign > 1;
+ return (IsLargeFrame || !HasRedZone) && HasBP && MaxAlign > 1;
}
bool PPCFrameLowering::canUseAsPrologue(const MachineBasicBlock &MBB) const {
// Do we have a frame pointer and/or base pointer for this function?
bool HasFP = hasFP(MF);
bool HasBP = RegInfo->hasBasePointer(MF);
+ bool HasRedZone = isPPC64 || !isSVR4ABI;
unsigned SPReg = isPPC64 ? PPC::X1 : PPC::R1;
unsigned BPReg = RegInfo->getBaseRegister(MF);
MIB.addReg(MustSaveCRs[i], CrState);
}
- if (HasFP)
- // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
- BuildMI(MBB, MBBI, dl, StoreInst)
- .addReg(FPReg)
- .addImm(FPOffset)
- .addReg(SPReg);
-
- if (FI->usesPICBase())
- // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
- BuildMI(MBB, MBBI, dl, StoreInst)
- .addReg(PPC::R30)
- .addImm(PBPOffset)
- .addReg(SPReg);
-
- if (HasBP)
- // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
- BuildMI(MBB, MBBI, dl, StoreInst)
- .addReg(BPReg)
- .addImm(BPOffset)
- .addReg(SPReg);
+ if (HasRedZone) {
+ if (HasFP)
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(FPReg)
+ .addImm(FPOffset)
+ .addReg(SPReg);
+ if (FI->usesPICBase())
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(PPC::R30)
+ .addImm(PBPOffset)
+ .addReg(SPReg);
+ if (HasBP)
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(BPReg)
+ .addImm(BPOffset)
+ .addReg(SPReg);
+ }
if (MustSaveLR)
- // FIXME: On PPC32 SVR4, we must not spill before claiming the stackframe.
BuildMI(MBB, MBBI, dl, StoreInst)
.addReg(ScratchReg, getKillRegState(true))
.addImm(LROffset)
.addReg(SPReg);
if (MustSaveCR &&
- !(SingleScratchReg && MustSaveLR)) // will only occur for PPC64
+ !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64
+ assert(HasRedZone && "A red zone is always available on PPC64");
BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8))
.addReg(TempReg, getKillRegState(true))
.addImm(8)
.addReg(SPReg);
+ }
// Skip the rest if this is a leaf function & all spills fit in the Red Zone.
- if (!FrameSize) return;
+ if (!FrameSize)
+ return;
// Adjust stack pointer: r1 += NegFrameSize.
// If there is a preferred stack alignment, align R1 now
- if (HasBP) {
+ if (HasBP && HasRedZone) {
// Save a copy of r1 as the base pointer.
BuildMI(MBB, MBBI, dl, OrInst, BPReg)
.addReg(SPReg)
.addReg(SPReg);
}
+ // Have we generated a STUX instruction to claim stack frame? If so,
+ // the frame size will be placed in ScratchReg.
+ bool HasSTUX = false;
+
// This condition must be kept in sync with canUseAsPrologue.
if (HasBP && MaxAlign > 1) {
if (isPPC64)
.addReg(ScratchReg, RegState::Kill)
.addReg(TempReg, RegState::Kill);
}
+
BuildMI(MBB, MBBI, dl, StoreUpdtIdxInst, SPReg)
.addReg(SPReg, RegState::Kill)
.addReg(SPReg)
.addReg(ScratchReg);
+ HasSTUX = true;
} else if (!isLargeFrame) {
BuildMI(MBB, MBBI, dl, StoreUpdtInst, SPReg)
.addReg(SPReg, RegState::Kill)
.addReg(SPReg)
.addReg(ScratchReg);
+ HasSTUX = true;
+ }
+
+ if (!HasRedZone) {
+ assert(!isPPC64 && "A red zone is always available on PPC64");
+ if (HasSTUX) {
+ // The frame size is in ScratchReg, and the SPReg has been advanced
+ // (downwards) by the frame size: SPReg = old SPReg + ScratchReg.
+ // Set ScratchReg to the original SPReg: ScratchReg = SPReg - ScratchReg.
+ BuildMI(MBB, MBBI, dl, TII.get(PPC::SUBF), ScratchReg)
+ .addReg(ScratchReg, RegState::Kill)
+ .addReg(SPReg);
+
+ // Now that the stack frame has been allocated, save all the necessary
+ // registers using ScratchReg as the base address.
+ if (HasFP)
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(FPReg)
+ .addImm(FPOffset)
+ .addReg(ScratchReg);
+ if (FI->usesPICBase())
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(PPC::R30)
+ .addImm(PBPOffset)
+ .addReg(ScratchReg);
+ if (HasBP) {
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(BPReg)
+ .addImm(BPOffset)
+ .addReg(ScratchReg);
+ BuildMI(MBB, MBBI, dl, OrInst, BPReg)
+ .addReg(ScratchReg, RegState::Kill)
+ .addReg(ScratchReg);
+ }
+ } else {
+ // The frame size is a known 16-bit constant (fitting in the immediate
+ // field of STWU). To be here we have to be compiling for PPC32.
+ // Since the SPReg has been decreased by FrameSize, add it back to each
+ // offset.
+ if (HasFP)
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(FPReg)
+ .addImm(FrameSize + FPOffset)
+ .addReg(SPReg);
+ if (FI->usesPICBase())
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(PPC::R30)
+ .addImm(FrameSize + PBPOffset)
+ .addReg(SPReg);
+ if (HasBP) {
+ BuildMI(MBB, MBBI, dl, StoreInst)
+ .addReg(BPReg)
+ .addImm(FrameSize + BPOffset)
+ .addReg(SPReg);
+ BuildMI(MBB, MBBI, dl, TII.get(PPC::ADDI), BPReg)
+ .addReg(SPReg)
+ .addImm(FrameSize);
+ }
+ }
}
// Add Call Frame Information for the instructions we generated above.
; CHECK-FP: blr
; CHECK-32-LABEL: @goo
-; CHECK-32-DAG: mflr {{[0-9]+}}
+; CHECK-32-DAG: mflr [[LR:[0-9]+]]
; CHECK-32-DAG: clrlwi [[REG:[0-9]+]], 1, 27
-; CHECK-32-DAG: stw 30, -8(1)
-; CHECK-32-DAG: mr 30, 1
-; CHECK-32-DAG: stw 0, 4(1)
+; CHECK-32-DAG: stw [[LR]], 4(1)
; CHECK-32-DAG: subfic 0, [[REG]], -64
; CHECK-32: stwux 1, 1, 0
+; CHECK-32: subf 0, 0, 1
+; CHECK-32: stw 30, -8(0)
+; CHECK-32: mr 30, 0
; CHECK-32-PIC-LABEL: @goo
-; CHECK-32-PIC-DAG: mflr {{[0-9]+}}
+; CHECK-32-PIC-DAG: mflr [[LR:[0-9]+]]
; CHECK-32-PIC-DAG: clrlwi [[REG:[0-9]+]], 1, 27
-; CHECK-32-PIC-DAG: stw 29, -12(1)
-; CHECK-32-PIC-DAG: mr 29, 1
-; CHECK-32-PIC-DAG: stw 0, 4(1)
+; CHECK-32-PIC-DAG: stw [[LR]], 4(1)
; CHECK-32-PIC-DAG: subfic 0, [[REG]], -64
; CHECK-32-PIC: stwux 1, 1, 0
+; CHECK-32-PIC: subf 0, 0, 1
+; CHECK-32-PIC: stw 29, -12(0)
+; CHECK-32-PIC-DAG: mr 29, 0
; The large-frame-size case.
define void @hoo(%struct.s* byval nocapture readonly %a) {
; CHECK-32-DAG: lis [[REG1:[0-9]+]], -13
; CHECK-32-DAG: clrlwi [[REG3:[0-9]+]], 1, 27
-; CHECK-32-DAG: mflr {{[0-9]+}}
+; CHECK-32-DAG: mflr [[LR:[0-9]+]]
; CHECK-32-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
-; CHECK-32-DAG: stw 30, -8(1)
-; CHECK-32-DAG: mr 30, 1
-; CHECK-32-DAG: stw 0, 4(1)
+; CHECK-32-DAG: stw [[LR]], 4(1)
; CHECK-32-DAG: subfc 0, [[REG3]], [[REG2]]
-; CHECK-32: stwux 1, 1, 0
+; CHECK-32: stwux 1, 1, 0
+; CHECK-32: subf 0, 0, 1
+; CHECK-32-DAG: stw 31, -4(0)
+; CHECK-32-DAG: stw 30, -8(0)
+; CHECK-32: mr 30, 0
; CHECK-32: blr
; CHECK-32-PIC-DAG: clrlwi [[REG3:[0-9]+]], 1, 27
; CHECK-32-PIC-DAG: mflr {{[0-9]+}}
; CHECK-32-PIC-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
-; CHECK-32-PIC-DAG: stw 29, -12(1)
-; CHECK-32-PIC-DAG: mr 29, 1
; CHECK-32-PIC-DAG: stw 0, 4(1)
; CHECK-32-PIC-DAG: subfc 0, [[REG3]], [[REG2]]
-; CHECK-32: stwux 1, 1, 0
+; CHECK-32-PIC: stwux 1, 1, 0
+; CHECK-32-PIC: stw 29, -12(0)
+; CHECK-32-PIC: subf 0, 0, 1
+; CHECK-32-PIC: mr 29, 0
; CHECK-32: blr