diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -626,8 +626,6 @@ // Work out frame sizes. uint64_t FrameSize = determineFrameLayoutAndUpdate(MF); int64_t NegFrameSize = -FrameSize; - if (!isInt<32>(FrameSize) || !isInt<32>(NegFrameSize)) - llvm_unreachable("Unhandled stack size!"); if (MFI.isFrameAddressTaken()) replaceFPWithRealFP(MF); @@ -667,6 +665,8 @@ : PPC::ORI ); const MCInstrDesc& OrInst = TII.get(isPPC64 ? PPC::OR8 : PPC::OR ); + const MCInstrDesc& OrImmShiftedInst = TII.get(isPPC64 ? PPC::ORIS8 + : PPC::ORIS); const MCInstrDesc& SubtractCarryingInst = TII.get(isPPC64 ? PPC::SUBFC8 : PPC::SUBFC); const MCInstrDesc& SubtractImmCarryingInst = TII.get(isPPC64 ? PPC::SUBFIC8 @@ -934,11 +934,30 @@ .addImm(NegFrameSize); } else { assert(!SingleScratchReg && "Only a single scratch reg available"); - BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, TempReg) + if (isInt<32>(NegFrameSize)) { + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, TempReg) .addImm(NegFrameSize >> 16); - BuildMI(MBB, MBBI, dl, OrImmInst, TempReg) + BuildMI(MBB, MBBI, dl, OrImmInst, TempReg) .addReg(TempReg, RegState::Kill) .addImm(NegFrameSize & 0xFFFF); + } else { + assert(isPPC64 && "Huge frame is only supported on PPC64"); + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, TempReg) + .addImm(NegFrameSize >> 48); + BuildMI(MBB, MBBI, dl, OrImmInst, TempReg) + .addReg(TempReg, RegState::Kill) + .addImm((NegFrameSize >> 32) & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICR), TempReg) + .addReg(TempReg, RegState::Kill) + .addImm(32) + .addImm(31); + BuildMI(MBB, MBBI, dl, OrImmShiftedInst, TempReg) + .addReg(TempReg, RegState::Kill) + .addImm((NegFrameSize >> 16) & 0xFFFF); + BuildMI(MBB, MBBI, dl, OrImmInst, TempReg) + .addReg(TempReg, RegState::Kill) + .addImm(NegFrameSize & 0xFFFF); + } BuildMI(MBB, MBBI, dl, SubtractCarryingInst, ScratchReg) .addReg(ScratchReg, RegState::Kill) .addReg(TempReg, RegState::Kill); @@ -957,11 +976,30 @@ .addReg(SPReg); } else { - BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) + if (isInt<32>(NegFrameSize)) { + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) .addImm(NegFrameSize >> 16); - BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) .addReg(ScratchReg, RegState::Kill) .addImm(NegFrameSize & 0xFFFF); + } else { + assert(isPPC64 && "Huge frame is only supported on PPC64"); + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) + .addImm(NegFrameSize >> 48); + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm((NegFrameSize >> 32) & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICR), ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm(32) + .addImm(31); + BuildMI(MBB, MBBI, dl, OrImmShiftedInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm((NegFrameSize >> 16) & 0xFFFF); + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm(NegFrameSize & 0xFFFF); + } BuildMI(MBB, MBBI, dl, StoreUpdtIdxInst, SPReg) .addReg(SPReg, RegState::Kill) .addReg(SPReg) @@ -1582,6 +1620,8 @@ : PPC::OR ); const MCInstrDesc& OrImmInst = TII.get( isPPC64 ? PPC::ORI8 : PPC::ORI ); + const MCInstrDesc &OrImmShiftedInst = + TII.get(isPPC64 ? PPC::ORIS8 : PPC::ORIS); const MCInstrDesc& AddImmInst = TII.get( isPPC64 ? PPC::ADDI8 : PPC::ADDI ); const MCInstrDesc& AddInst = TII.get( isPPC64 ? PPC::ADD8 @@ -1667,7 +1707,7 @@ // values from the stack, and set SPAdd to the value that needs to be added // to the SP at the end. The default values are as if red zone was present. unsigned RBReg = SPReg; - unsigned SPAdd = 0; + uint64_t SPAdd = 0; // Check if we can move the stack update instruction up the epilogue // past the callee saves. This will allow the move to LR instruction @@ -1725,11 +1765,29 @@ BuildMI(MBB, MBBI, dl, AddImmInst, RBReg) .addReg(FPReg).addImm(FrameSize); } else { - BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) - .addImm(FrameSize >> 16); - BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) - .addReg(ScratchReg, RegState::Kill) - .addImm(FrameSize & 0xFFFF); + if (isInt<32>(FrameSize)) { + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) + .addImm(FrameSize >> 16); + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + } else { + BuildMI(MBB, MBBI, dl, LoadImmShiftedInst, ScratchReg) + .addImm(FrameSize >> 48); + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm((FrameSize >> 32) & 0xFFFF); + BuildMI(MBB, MBBI, dl, TII.get(PPC::RLDICR), ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm(32) + .addImm(31); + BuildMI(MBB, MBBI, dl, OrImmShiftedInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm((FrameSize >> 16) & 0xFFFF); + BuildMI(MBB, MBBI, dl, OrImmInst, ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addImm(FrameSize & 0xFFFF); + } BuildMI(MBB, MBBI, dl, AddInst) .addReg(RBReg) .addReg(FPReg) diff --git a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll --- a/llvm/test/CodeGen/PowerPC/huge-frame-size.ll +++ b/llvm/test/CodeGen/PowerPC/huge-frame-size.ll @@ -1,14 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; REQUIRES: asserts -; RUN: not --crash llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu < %s \ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-linux-gnu < %s \ ; RUN: 2>&1 | FileCheck --check-prefix=CHECK-LE %s -; RUN: not --crash llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix-xcoff < %s \ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix-xcoff < %s \ ; RUN: 2>&1 | FileCheck --check-prefix=CHECK-BE %s declare void @bar(i8*) define void @foo(i8 %x) { -; CHECK-LE: Unhandled stack size -; CHECK-BE: Unhandled stack size +; CHECK-LE-LABEL: foo: +; CHECK-LE: # %bb.0: # %entry +; CHECK-LE-NEXT: lis 0, -1 +; CHECK-LE-NEXT: ori 0, 0, 65534 +; CHECK-LE-NEXT: sldi 0, 0, 32 +; CHECK-LE-NEXT: oris 0, 0, 65535 +; CHECK-LE-NEXT: ori 0, 0, 65504 +; CHECK-LE-NEXT: stdux 1, 1, 0 +; CHECK-LE-NEXT: .cfi_def_cfa_offset 32 +; CHECK-LE-NEXT: stb 3, 32(1) +; CHECK-LE-NEXT: ld 1, 0(1) +; CHECK-LE-NEXT: blr +; +; CHECK-BE-LABEL: foo: +; CHECK-BE: # %bb.0: # %entry +; CHECK-BE-NEXT: lis 0, -1 +; CHECK-BE-NEXT: ori 0, 0, 65534 +; CHECK-BE-NEXT: sldi 0, 0, 32 +; CHECK-BE-NEXT: oris 0, 0, 65535 +; CHECK-BE-NEXT: ori 0, 0, 65488 +; CHECK-BE-NEXT: stdux 1, 1, 0 +; CHECK-BE-NEXT: stb 3, 48(1) +; CHECK-BE-NEXT: ld 1, 0(1) +; CHECK-BE-NEXT: blr entry: %a = alloca i8, i64 4294967296, align 16 %b = getelementptr i8, i8* %a, i64 0