316 lines
13 KiB
Diff
316 lines
13 KiB
Diff
From 7aeecae6393d5c3333beec64ad343ed1cabe75e4 Mon Sep 17 00:00:00 2001
|
|
From: Matt Arsenault <Matthew.Arsenault@amd.com>
|
|
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
|
|
|