diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -2966,6 +2966,7 @@ // We save R4 and R5 before use and restore them before leaving the function. unsigned ScratchReg0 = ARM::R4; unsigned ScratchReg1 = ARM::R5; + unsigned MovOp = ST->useMovt() ? ARM::t2MOVi32imm : ARM::tMOVi32imm; uint64_t AlignedStackSize; MachineBasicBlock *PrevStackMBB = MF.CreateMachineBasicBlock(); @@ -3083,8 +3084,8 @@ .addImm(AlignedStackSize) .add(predOps(ARMCC::AL)); } else { - if (Thumb2) { - BuildMI(McrMBB, DL, TII.get(ARM::t2MOVi32imm), ScratchReg0) + if (Thumb2 || ST->genExecuteOnly()) { + BuildMI(McrMBB, DL, TII.get(MovOp), ScratchReg0) .addImm(AlignedStackSize); } else { auto MBBI = McrMBB->end(); @@ -3119,16 +3120,21 @@ } if (Thumb && ST->isThumb1Only()) { - unsigned PCLabelId = ARMFI->createPICLabelUId(); - ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol::Create( - MF.getFunction().getContext(), "__STACK_LIMIT", PCLabelId, 0); - MachineConstantPool *MCP = MF.getConstantPool(); - unsigned CPI = MCP->getConstantPoolIndex(NewCPV, Align(4)); - - // ldr SR0, [pc, offset(STACK_LIMIT)] - BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0) - .addConstantPoolIndex(CPI) - .add(predOps(ARMCC::AL)); + if (ST->genExecuteOnly()) { + BuildMI(GetMBB, DL, TII.get(MovOp), ScratchReg0) + .addExternalSymbol("__STACK_LIMIT"); + } else { + unsigned PCLabelId = ARMFI->createPICLabelUId(); + ARMConstantPoolValue *NewCPV = ARMConstantPoolSymbol::Create( + MF.getFunction().getContext(), "__STACK_LIMIT", PCLabelId, 0); + MachineConstantPool *MCP = MF.getConstantPool(); + unsigned CPI = MCP->getConstantPoolIndex(NewCPV, Align(4)); + + // ldr SR0, [pc, offset(STACK_LIMIT)] + BuildMI(GetMBB, DL, TII.get(ARM::tLDRpci), ScratchReg0) + .addConstantPoolIndex(CPI) + .add(predOps(ARMCC::AL)); + } // ldr SR0, [SR0] BuildMI(GetMBB, DL, TII.get(ARM::tLDRi), ScratchReg0) @@ -3188,8 +3194,8 @@ .addImm(AlignedStackSize) .add(predOps(ARMCC::AL)); } else { - if (Thumb2) { - BuildMI(AllocMBB, DL, TII.get(ARM::t2MOVi32imm), ScratchReg0) + if (Thumb2 || ST->genExecuteOnly()) { + BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg0) .addImm(AlignedStackSize); } else { auto MBBI = AllocMBB->end(); @@ -3221,8 +3227,8 @@ .addImm(alignToARMConstant(ARMFI->getArgumentStackSize())) .add(predOps(ARMCC::AL)); } else { - if (Thumb2) { - BuildMI(AllocMBB, DL, TII.get(ARM::t2MOVi32imm), ScratchReg1) + if (Thumb2 || ST->genExecuteOnly()) { + BuildMI(AllocMBB, DL, TII.get(MovOp), ScratchReg1) .addImm(alignToARMConstant(ARMFI->getArgumentStackSize())); } else { auto MBBI = AllocMBB->end(); diff --git a/llvm/test/CodeGen/ARM/execute-only-segmented-stack.ll b/llvm/test/CodeGen/ARM/execute-only-segmented-stack.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/execute-only-segmented-stack.ll @@ -0,0 +1,47 @@ +; RUN: llc -mtriple=thumbv6m-linux-eabi -mattr=+execute-only %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOMOVW-SIZE,CHECK-NOMOVW-LIMIT +; RUN: llc -mtriple=thumbv8m.base-linux-eabi -mattr=+execute-only %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MOVW-SIZE,CHECK-MOVW-LIMIT +; RUN: llc -mtriple=thumbv7m-linux-eabi -mattr=+execute-only %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MOVW-SIZE,CHECK-MRC-LIMIT +; RUN: llc -mtriple=thumbv8m.main-linux-eabi -mattr=+execute-only %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MOVW-SIZE,CHECK-MRC-LIMIT + +%struct.large_struct = type { [500 x i8] } +declare void @fn(ptr) + +; CHECK-LABEL: test: +; CHECK: mov [[SP:r[0-9]+]], sp +; CHECK-MOVW-SIZE-NEXT: movw [[SIZE:r[0-9]+]], #4032 +; CHECK-NOMOVW-SIZE-NEXT: movs [[SIZE:r[0-9]+]], #15 +; CHECK-NOMOVW-SIZE-NEXT: lsls [[SIZE]], [[SIZE]], #8 +; CHECK-NOMOVW-SIZE-NEXT: adds [[SIZE]], #192 +; CHECK-NEXT: sub{{s?}} [[SP]], [[SP]], [[SIZE]] +; CHECK-MOVW-LIMIT-NEXT: movw [[LIMIT:r[0-9]+]], :lower16:__STACK_LIMIT +; CHECK-MOVW-LIMIT-NEXT: movt [[LIMIT]], :upper16:__STACK_LIMIT +; CHECK-NOMOVW-LIMIT-NEXT: movs [[LIMIT:r[0-9]+]], :upper8_15:__STACK_LIMIT +; CHECK-NOMOVW-LIMIT-NEXT: lsls [[LIMIT]], [[LIMIT]], #8 +; CHECK-NOMOVW-LIMIT-NEXT: adds [[LIMIT]], :upper0_7:__STACK_LIMIT +; CHECK-NOMOVW-LIMIT-NEXT: lsls [[LIMIT]], [[LIMIT]], #8 +; CHECK-NOMOVW-LIMIT-NEXT: adds [[LIMIT]], :lower8_15:__STACK_LIMIT +; CHECK-NOMOVW-LIMIT-NEXT: lsls [[LIMIT]], [[LIMIT]], #8 +; CHECK-NOMOVW-LIMIT-NEXT: adds [[LIMIT]], :lower0_7:__STACK_LIMIT +; CHECK-MRC-LIMIT-NEXT: p15, #0, [[LIMIT:r[0-9]+]], c13, c0, #3 +; CHECK-NEXT: ldr [[LIMIT]], [[[LIMIT]]{{.*}}] +; CHECK-NEXT: cmp [[LIMIT]], [[SP]] +; CHECK-NEXT: bls +; CHECK-NEXT: @{{.*}}: +; CHECK-MOVW-SIZE-NEXT: movw r4, #4032 +; CHECK-NOMOVW-SIZE-NEXT: movs r4, #15 +; CHECK-NOMOVW-SIZE-NEXT: lsls r4, r4, #8 +; CHECK-NOMOVW-SIZE-NEXT: adds r4, #192 +; CHECK-MOVW-SIZE-NEXT: movw r5, #484 +; CHECK-NOMOVW-SIZE-NEXT: movs r5, #1 +; CHECK-NOMOVW-SIZE-NEXT: lsls r5, r5, #8 +; CHECK-NOMOVW-SIZE-NEXT: adds r5, #228 +; CHECK-NEXT: push {lr} +; CHECK-NEXT: bl __morestack + +define void @test(ptr byval(%struct.large_struct) align 4 %arg) #0 { + %ptr = alloca i32, i32 1000 + call void @fn(ptr %ptr) + ret void +} + +attributes #0 = { "split-stack" }