Skip to content

Commit 1ca0808

Browse files
committed
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.
1 parent 25bc999 commit 1ca0808

File tree

11 files changed

+141
-26
lines changed

11 files changed

+141
-26
lines changed

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ class LegalizerHelper {
401401
LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI);
402402
LegalizeResult lowerShuffleVector(MachineInstr &MI);
403403
LegalizeResult lowerDynStackAlloc(MachineInstr &MI);
404+
LegalizeResult lowerStackSave(MachineInstr &MI);
405+
LegalizeResult lowerStackRestore(MachineInstr &MI);
404406
LegalizeResult lowerExtract(MachineInstr &MI);
405407
LegalizeResult lowerInsert(MachineInstr &MI);
406408
LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI);

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,12 @@ HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
769769
/// Generic dynamic stack allocation.
770770
HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC)
771771

772+
/// Generic stack pointer save.
773+
HANDLE_TARGET_OPCODE(G_STACKSAVE)
774+
775+
/// Generic stack pointer restore.
776+
HANDLE_TARGET_OPCODE(G_STACKRESTORE)
777+
772778
/// Strict floating point instructions.
773779
HANDLE_TARGET_OPCODE(G_STRICT_FADD)
774780
HANDLE_TARGET_OPCODE(G_STRICT_FSUB)

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,18 @@ def G_DYN_STACKALLOC : GenericInstruction {
225225
let hasSideEffects = true;
226226
}
227227

228+
def G_STACKSAVE : GenericInstruction {
229+
let OutOperandList = (outs ptype0:$dst);
230+
let InOperandList = (ins);
231+
let hasSideEffects = true;
232+
}
233+
234+
def G_STACKRESTORE : GenericInstruction {
235+
let OutOperandList = (outs);
236+
let InOperandList = (ins ptype0:$src);
237+
let hasSideEffects = true;
238+
}
239+
228240
def G_FREEZE : GenericInstruction {
229241
let OutOperandList = (outs type0:$dst);
230242
let InOperandList = (ins type0:$src);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,31 +2229,12 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
22292229
return true;
22302230
}
22312231
case Intrinsic::stacksave: {
2232-
// Save the stack pointer to the location provided by the intrinsic.
2233-
Register Reg = getOrCreateVReg(CI);
2234-
Register StackPtr = MF->getSubtarget()
2235-
.getTargetLowering()
2236-
->getStackPointerRegisterToSaveRestore();
2237-
2238-
// If the target doesn't specify a stack pointer, then fall back.
2239-
if (!StackPtr)
2240-
return false;
2241-
2242-
MIRBuilder.buildCopy(Reg, StackPtr);
2232+
MIRBuilder.buildInstr(TargetOpcode::G_STACKSAVE, {getOrCreateVReg(CI)}, {});
22432233
return true;
22442234
}
22452235
case Intrinsic::stackrestore: {
2246-
// Restore the stack pointer from the location provided by the intrinsic.
2247-
Register Reg = getOrCreateVReg(*CI.getArgOperand(0));
2248-
Register StackPtr = MF->getSubtarget()
2249-
.getTargetLowering()
2250-
->getStackPointerRegisterToSaveRestore();
2251-
2252-
// If the target doesn't specify a stack pointer, then fall back.
2253-
if (!StackPtr)
2254-
return false;
2255-
2256-
MIRBuilder.buildCopy(StackPtr, Reg);
2236+
MIRBuilder.buildInstr(TargetOpcode::G_STACKRESTORE, {},
2237+
{getOrCreateVReg(*CI.getArgOperand(0))});
22572238
return true;
22582239
}
22592240
case Intrinsic::cttz:

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3502,6 +3502,10 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
35023502
return lowerShuffleVector(MI);
35033503
case G_DYN_STACKALLOC:
35043504
return lowerDynStackAlloc(MI);
3505+
case G_STACKSAVE:
3506+
return lowerStackSave(MI);
3507+
case G_STACKRESTORE:
3508+
return lowerStackRestore(MI);
35053509
case G_EXTRACT:
35063510
return lowerExtract(MI);
35073511
case G_INSERT:
@@ -6809,6 +6813,28 @@ LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) {
68096813
return Legalized;
68106814
}
68116815

6816+
LegalizerHelper::LegalizeResult
6817+
LegalizerHelper::lowerStackSave(MachineInstr &MI) {
6818+
Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
6819+
if (!StackPtr)
6820+
return UnableToLegalize;
6821+
6822+
MIRBuilder.buildCopy(MI.getOperand(0), StackPtr);
6823+
MI.eraseFromParent();
6824+
return Legalized;
6825+
}
6826+
6827+
LegalizerHelper::LegalizeResult
6828+
LegalizerHelper::lowerStackRestore(MachineInstr &MI) {
6829+
Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
6830+
if (!StackPtr)
6831+
return UnableToLegalize;
6832+
6833+
MIRBuilder.buildCopy(StackPtr, MI.getOperand(0));
6834+
MI.eraseFromParent();
6835+
return Legalized;
6836+
}
6837+
68126838
LegalizerHelper::LegalizeResult
68136839
LegalizerHelper::lowerExtract(MachineInstr &MI) {
68146840
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
799799
return Query.Types[0] == p0 && Query.Types[1] == s64;
800800
});
801801

802-
getActionDefinitionsBuilder(G_DYN_STACKALLOC).lower();
802+
getActionDefinitionsBuilder({G_DYN_STACKALLOC,
803+
G_STACKSAVE,
804+
G_STACKRESTORE}).lower();
803805

804806
if (ST.hasMOPS()) {
805807
// G_BZERO is not supported. Currently it is only emitted by

llvm/lib/Target/X86/X86LegalizerInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
528528
// memory intrinsics
529529
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
530530

531+
getActionDefinitionsBuilder({G_DYN_STACKALLOC,
532+
G_STACKSAVE,
533+
G_STACKRESTORE}).lower();
534+
531535
// fp intrinsics
532536
getActionDefinitionsBuilder(G_INTRINSIC_ROUNDEVEN)
533537
.scalarize(0)

llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,8 +2392,8 @@ declare ptr @llvm.stacksave()
23922392
declare void @llvm.stackrestore(ptr)
23932393
define void @test_stacksaverestore() {
23942394
; CHECK-LABEL: name: test_stacksaverestore
2395-
; CHECK: [[SAVE:%[0-9]+]]:_(p0) = COPY $sp
2396-
; CHECK-NEXT: $sp = COPY [[SAVE]](p0)
2395+
; CHECK: [[SAVE:%[0-9]+]]:_(p0) = G_STACKSAVE
2396+
; CHECK-NEXT: G_STACKRESTORE [[SAVE]]
23972397
; CHECK-NEXT: RET_ReallyLR
23982398
%sp = call ptr @llvm.stacksave()
23992399
call void @llvm.stackrestore(ptr %sp)

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,15 @@
648648
# DEBUG-NEXT: G_JUMP_TABLE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
649649
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
650650
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
651-
# DEBUG-NEXT: G_DYN_STACKALLOC (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
651+
# DEBUG-NEXT: G_DYN_STACKALLOC (opcode [[DYN_STACKALLOC:[0-9]+]]): 2 type indices, 0 imm indices
652+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
653+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
654+
# DEBUG-NEXT: G_STACKSAVE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
655+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to [[DYN_STACKALLOC]]
656+
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
657+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
658+
# DEBUG-NEXT: G_STACKRESTORE (opcode {{[0-9]+}}): 1 type index, 0 imm indices
659+
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to [[DYN_STACKALLOC]]
652660
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
653661
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
654662
# DEBUG-NEXT: G_STRICT_FADD (opcode {{[0-9]+}}): 1 type index, 0 imm indices
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2+
; RUN: llc -global-isel=1 -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s
3+
4+
declare void @use_addr(ptr)
5+
declare ptr @llvm.stacksave.p0()
6+
declare void @llvm.stackrestore.p0(ptr)
7+
8+
define void @test_scoped_alloca(i64 %n) {
9+
; CHECK-LABEL: test_scoped_alloca:
10+
; CHECK: // %bb.0:
11+
; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
12+
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
13+
; CHECK-NEXT: mov x29, sp
14+
; CHECK-NEXT: .cfi_def_cfa w29, 32
15+
; CHECK-NEXT: .cfi_offset w19, -16
16+
; CHECK-NEXT: .cfi_offset w30, -24
17+
; CHECK-NEXT: .cfi_offset w29, -32
18+
; CHECK-NEXT: add x9, x0, #15
19+
; CHECK-NEXT: mov x8, sp
20+
; CHECK-NEXT: and x9, x9, #0xfffffffffffffff0
21+
; CHECK-NEXT: mov x19, sp
22+
; CHECK-NEXT: sub x0, x8, x9
23+
; CHECK-NEXT: mov sp, x0
24+
; CHECK-NEXT: bl use_addr
25+
; CHECK-NEXT: mov sp, x19
26+
; CHECK-NEXT: mov sp, x29
27+
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
28+
; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
29+
; CHECK-NEXT: ret
30+
%sp = call ptr @llvm.stacksave.p0()
31+
%addr = alloca i8, i64 %n
32+
call void @use_addr(ptr %addr)
33+
call void @llvm.stackrestore.p0(ptr %sp)
34+
ret void
35+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2+
; RUN: llc -global-isel=1 -mtriple=x86_64-linux-gnu -o - %s | FileCheck %s
3+
4+
declare void @use_addr(ptr)
5+
declare ptr @llvm.stacksave.p0()
6+
declare void @llvm.stackrestore.p0(ptr)
7+
8+
define void @test_scoped_alloca(i64 %n) {
9+
; CHECK-LABEL: test_scoped_alloca:
10+
; CHECK: # %bb.0:
11+
; CHECK-NEXT: pushq %rbp
12+
; CHECK-NEXT: .cfi_def_cfa_offset 16
13+
; CHECK-NEXT: .cfi_offset %rbp, -16
14+
; CHECK-NEXT: movq %rsp, %rbp
15+
; CHECK-NEXT: .cfi_def_cfa_register %rbp
16+
; CHECK-NEXT: pushq %rbx
17+
; CHECK-NEXT: pushq %rax
18+
; CHECK-NEXT: .cfi_offset %rbx, -24
19+
; CHECK-NEXT: movq %rsp, %rbx
20+
; CHECK-NEXT: movq %rsp, %rax
21+
; CHECK-NEXT: imulq $1, %rdi, %rcx
22+
; CHECK-NEXT: addq $15, %rcx
23+
; CHECK-NEXT: andq $-16, %rcx
24+
; CHECK-NEXT: subq %rcx, %rax
25+
; CHECK-NEXT: movq %rax, %rsp
26+
; CHECK-NEXT: movq %rax, %rdi
27+
; CHECK-NEXT: callq use_addr
28+
; CHECK-NEXT: movq %rbx, %rsp
29+
; CHECK-NEXT: leaq -8(%rbp), %rsp
30+
; CHECK-NEXT: popq %rbx
31+
; CHECK-NEXT: popq %rbp
32+
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
33+
; CHECK-NEXT: retq
34+
%sp = call ptr @llvm.stacksave.p0()
35+
%addr = alloca i8, i64 %n
36+
call void @use_addr(ptr %addr)
37+
call void @llvm.stackrestore.p0(ptr %sp)
38+
ret void
39+
}

0 commit comments

Comments
 (0)