Index: llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -401,6 +401,8 @@ LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI); LegalizeResult lowerShuffleVector(MachineInstr &MI); LegalizeResult lowerDynStackAlloc(MachineInstr &MI); + LegalizeResult lowerStackSave(MachineInstr &MI); + LegalizeResult lowerStackRestore(MachineInstr &MI); LegalizeResult lowerExtract(MachineInstr &MI); LegalizeResult lowerInsert(MachineInstr &MI); LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); Index: llvm/include/llvm/Support/TargetOpcodes.def =================================================================== --- llvm/include/llvm/Support/TargetOpcodes.def +++ llvm/include/llvm/Support/TargetOpcodes.def @@ -763,6 +763,12 @@ /// Generic dynamic stack allocation. HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC) +/// Generic stack pointer save. +HANDLE_TARGET_OPCODE(G_STACKSAVE) + +/// Generic stack pointer restore. +HANDLE_TARGET_OPCODE(G_STACKRESTORE) + /// Strict floating point instructions. HANDLE_TARGET_OPCODE(G_STRICT_FADD) HANDLE_TARGET_OPCODE(G_STRICT_FSUB) Index: llvm/include/llvm/Target/GenericOpcodes.td =================================================================== --- llvm/include/llvm/Target/GenericOpcodes.td +++ llvm/include/llvm/Target/GenericOpcodes.td @@ -225,6 +225,18 @@ let hasSideEffects = true; } +def G_STACKSAVE : GenericInstruction { + let OutOperandList = (outs ptype0:$dst); + let InOperandList = (ins); + let hasSideEffects = true; +} + +def G_STACKRESTORE : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins ptype0:$src); + let hasSideEffects = true; +} + def G_FREEZE : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins type0:$src); Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2229,31 +2229,12 @@ return true; } case Intrinsic::stacksave: { - // Save the stack pointer to the location provided by the intrinsic. - Register Reg = getOrCreateVReg(CI); - Register StackPtr = MF->getSubtarget() - .getTargetLowering() - ->getStackPointerRegisterToSaveRestore(); - - // If the target doesn't specify a stack pointer, then fall back. - if (!StackPtr) - return false; - - MIRBuilder.buildCopy(Reg, StackPtr); + MIRBuilder.buildInstr(TargetOpcode::G_STACKSAVE, {getOrCreateVReg(CI)}, {}); return true; } case Intrinsic::stackrestore: { - // Restore the stack pointer from the location provided by the intrinsic. - Register Reg = getOrCreateVReg(*CI.getArgOperand(0)); - Register StackPtr = MF->getSubtarget() - .getTargetLowering() - ->getStackPointerRegisterToSaveRestore(); - - // If the target doesn't specify a stack pointer, then fall back. - if (!StackPtr) - return false; - - MIRBuilder.buildCopy(StackPtr, Reg); + MIRBuilder.buildInstr(TargetOpcode::G_STACKRESTORE, {}, + {getOrCreateVReg(*CI.getArgOperand(0))}); return true; } case Intrinsic::cttz: Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -3503,6 +3503,10 @@ return lowerShuffleVector(MI); case G_DYN_STACKALLOC: return lowerDynStackAlloc(MI); + case G_STACKSAVE: + return lowerStackSave(MI); + case G_STACKRESTORE: + return lowerStackRestore(MI); case G_EXTRACT: return lowerExtract(MI); case G_INSERT: @@ -6810,6 +6814,28 @@ return Legalized; } +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerStackSave(MachineInstr &MI) { + Register StackPtr = TLI.getStackPointerRegisterToSaveRestore(); + if (!StackPtr) + return UnableToLegalize; + + MIRBuilder.buildCopy(MI.getOperand(0), StackPtr); + MI.eraseFromParent(); + return Legalized; +} + +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerStackRestore(MachineInstr &MI) { + Register StackPtr = TLI.getStackPointerRegisterToSaveRestore(); + if (!StackPtr) + return UnableToLegalize; + + MIRBuilder.buildCopy(StackPtr, MI.getOperand(0)); + MI.eraseFromParent(); + return Legalized; +} + LegalizerHelper::LegalizeResult LegalizerHelper::lowerExtract(MachineInstr &MI) { auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs(); Index: llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -798,7 +798,9 @@ return Query.Types[0] == p0 && Query.Types[1] == s64; }); - getActionDefinitionsBuilder(G_DYN_STACKALLOC).lower(); + getActionDefinitionsBuilder({G_DYN_STACKALLOC, + G_STACKSAVE, + G_STACKRESTORE}).lower(); if (ST.hasMOPS()) { // G_BZERO is not supported. Currently it is only emitted by Index: llvm/lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -528,6 +528,10 @@ // memory intrinsics getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall(); + getActionDefinitionsBuilder({G_DYN_STACKALLOC, + G_STACKSAVE, + G_STACKRESTORE}).lower(); + // fp intrinsics getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN) .scalarize(0) Index: llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -2392,8 +2392,8 @@ declare void @llvm.stackrestore(ptr) define void @test_stacksaverestore() { ; CHECK-LABEL: name: test_stacksaverestore - ; CHECK: [[SAVE:%[0-9]+]]:_(p0) = COPY $sp - ; CHECK-NEXT: $sp = COPY [[SAVE]](p0) + ; CHECK: [[SAVE:%[0-9]+]]:_(p0) = G_STACKSAVE + ; CHECK-NEXT: G_STACKRESTORE [[SAVE]] ; CHECK-NEXT: RET_ReallyLR %sp = call ptr @llvm.stacksave() call void @llvm.stackrestore(ptr %sp) Index: llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -641,7 +641,15 @@ # DEBUG-NEXT: G_JUMP_TABLE (opcode {{[0-9]+}}): 1 type index, 0 imm indices # DEBUG-NEXT: .. the first uncovered type index: 1, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK -# DEBUG-NEXT: G_DYN_STACKALLOC (opcode {{[0-9]+}}): 2 type indices, 0 imm indices +# DEBUG-NEXT: G_DYN_STACKALLOC (opcode [[DYN_STACKALLOC:[0-9]+]]): 2 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: G_STACKSAVE (opcode {{[0-9]+}}): 1 type index, 0 imm indices +# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to [[DYN_STACKALLOC]] +# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: G_STACKRESTORE (opcode {{[0-9]+}}): 1 type index, 0 imm indices +# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to [[DYN_STACKALLOC]] # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: G_STRICT_FADD (opcode {{[0-9]+}}): 1 type index, 0 imm indices Index: llvm/test/CodeGen/AArch64/GlobalISel/stacksave-stackrestore.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/GlobalISel/stacksave-stackrestore.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -global-isel=1 -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s + +declare void @use_addr(ptr) +declare ptr @llvm.stacksave.p0() +declare void @llvm.stackrestore.p0(ptr) + +define void @test_scoped_alloca(i64 %n) { +; CHECK-LABEL: test_scoped_alloca: +; CHECK: // %bb.0: +; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill +; CHECK-NEXT: str x19, [sp, #16] // 8-byte Folded Spill +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .cfi_def_cfa w29, 32 +; CHECK-NEXT: .cfi_offset w19, -16 +; CHECK-NEXT: .cfi_offset w30, -24 +; CHECK-NEXT: .cfi_offset w29, -32 +; CHECK-NEXT: add x9, x0, #15 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0 +; CHECK-NEXT: mov x19, sp +; CHECK-NEXT: sub x0, x8, x9 +; CHECK-NEXT: mov sp, x0 +; CHECK-NEXT: bl use_addr +; CHECK-NEXT: mov sp, x19 +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload +; CHECK-NEXT: ret + %sp = call ptr @llvm.stacksave.p0() + %addr = alloca i8, i64 %n + call void @use_addr(ptr %addr) + call void @llvm.stackrestore.p0(ptr %sp) + ret void +} Index: llvm/test/CodeGen/X86/GlobalISel/stacksave-stackrestore.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/GlobalISel/stacksave-stackrestore.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -global-isel=1 -mtriple=x86_64-linux-gnu -o - %s | FileCheck %s + +declare void @use_addr(ptr) +declare ptr @llvm.stacksave.p0() +declare void @llvm.stackrestore.p0(ptr) + +define void @test_scoped_alloca(i64 %n) { +; CHECK-LABEL: test_scoped_alloca: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movq %rsp, %rbp +; CHECK-NEXT: .cfi_def_cfa_register %rbp +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_offset %rbx, -24 +; CHECK-NEXT: movq %rsp, %rbx +; CHECK-NEXT: movq %rsp, %rax +; CHECK-NEXT: imulq $1, %rdi, %rcx +; CHECK-NEXT: addq $15, %rcx +; CHECK-NEXT: andq $-16, %rcx +; CHECK-NEXT: subq %rcx, %rax +; CHECK-NEXT: movq %rax, %rsp +; CHECK-NEXT: movq %rax, %rdi +; CHECK-NEXT: callq use_addr +; CHECK-NEXT: movq %rbx, %rsp +; CHECK-NEXT: leaq -8(%rbp), %rsp +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: .cfi_def_cfa %rsp, 8 +; CHECK-NEXT: retq + %sp = call ptr @llvm.stacksave.p0() + %addr = alloca i8, i64 %n + call void @use_addr(ptr %addr) + call void @llvm.stackrestore.p0(ptr %sp) + ret void +}