From 7aeecae6393d5c3333beec64ad343ed1cabe75e4 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 29 Jul 2023 19:12:24 -0400 Subject: [PATCH 1/7] GlobalISel: Don't expand stacksave/stackrestore in IRTranslator In some (likely invalid edge cases anyway), it's not correct to directly copy the stack pointer register. --- .../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 2 + llvm/include/llvm/Support/TargetOpcodes.def | 6 +++ llvm/include/llvm/Target/GenericOpcodes.td | 12 ++++++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 25 ++---------- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 26 +++++++++++++ .../AArch64/GISel/AArch64LegalizerInfo.cpp | 4 +- llvm/lib/Target/X86/X86LegalizerInfo.cpp | 4 ++ .../AArch64/GlobalISel/arm64-irtranslator.ll | 4 +- .../GlobalISel/legalizer-info-validation.mir | 10 ++++- .../GlobalISel/stacksave-stackrestore.ll | 35 +++++++++++++++++ .../X86/GlobalISel/stacksave-stackrestore.ll | 39 +++++++++++++++++++ 11 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/stacksave-stackrestore.ll create mode 100644 llvm/test/CodeGen/X86/GlobalISel/stacksave-stackrestore.ll diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index a568edd0e640..9288091874cf 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -401,6 +401,8 @@ public: 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); diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index 186bea75ae96..c92ce6dc701c 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -763,6 +763,12 @@ HANDLE_TARGET_OPCODE(G_JUMP_TABLE) /// 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) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 00d56d1c4bd5..e8cfaeab3cd8 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -225,6 +225,18 @@ def G_DYN_STACKALLOC : GenericInstruction { 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); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 9a67a8d05a4d..e4b837c6b8ce 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2229,31 +2229,12 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, 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: diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index f0da0d88140f..75d9789be4d0 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -3503,6 +3503,10 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { 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 @@ LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) { 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(); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index d905da4eaec3..f0130a0be29d 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -797,7 +797,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) 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 diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp index a4a247f85f3d..104461cff0a9 100644 --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -528,6 +528,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, // 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) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll index 5f3544add398..575cd6b874e3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -2392,8 +2392,8 @@ declare ptr @llvm.stacksave() 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) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index b4fe73d29fa6..461161f5b338 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/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 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/stacksave-stackrestore.ll b/llvm/test/CodeGen/AArch64/GlobalISel/stacksave-stackrestore.ll new file mode 100644 index 000000000000..16bf85af9c17 --- /dev/null +++ b/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 +} diff --git a/llvm/test/CodeGen/X86/GlobalISel/stacksave-stackrestore.ll b/llvm/test/CodeGen/X86/GlobalISel/stacksave-stackrestore.ll new file mode 100644 index 000000000000..e86c04ee22db --- /dev/null +++ b/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 +} -- 2.42.0.windows.2