Skip to content

Commit da0ca5d

Browse files
[WebAssembly] Define local sp if llvm.stacksave is used (#68133)
Usually `llvm.stacksave/stackrestore` are used together with `alloca` but they can appear without it (e.g. `alloca` can be optimized away). WebAssembly's function local physical user sp register, which is referenced by `llvm.stacksave` is created while frame lowering and replaced with virtual register. However the sp register was not created when `llvm.stacksave` is used without `alloca`, and it led MIR verification failure about use-before-def of sp virtual register. Resolves #62235
1 parent 37fcad7 commit da0ca5d

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,15 @@ bool WebAssemblyFrameLowering::hasReservedCallFrame(
130130
bool WebAssemblyFrameLowering::needsSPForLocalFrame(
131131
const MachineFunction &MF) const {
132132
auto &MFI = MF.getFrameInfo();
133-
return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF);
133+
auto &MRI = MF.getRegInfo();
134+
// llvm.stacksave can explicitly read SP register and it can appear without
135+
// dynamic alloca.
136+
bool HasExplicitSPUse =
137+
any_of(MRI.use_operands(getSPReg(MF)),
138+
[](MachineOperand &MO) { return !MO.isImplicit(); });
139+
140+
return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF) ||
141+
HasExplicitSPUse;
134142
}
135143

136144
// In function with EH pads, we need to make a copy of the value of

llvm/test/CodeGen/WebAssembly/userstack.ll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,18 @@ define void @llvm_stack_builtins(i32 %alloc) noredzone {
550550
ret void
551551
}
552552

553+
; Use of stacksave requires local SP definition even without dymamic alloca.
554+
; CHECK-LABEL: llvm_stacksave_noalloca:
555+
define void @llvm_stacksave_noalloca() noredzone {
556+
; CHECK: global.get $push[[L11:.+]]=, __stack_pointer{{$}}
557+
%stack = call i8* @llvm.stacksave()
558+
559+
; CHECK-NEXT: call use_i8_star, $pop[[L11:.+]]
560+
call void @use_i8_star(i8* %stack)
561+
562+
ret void
563+
}
564+
553565
; Not actually using the alloca'd variables exposed an issue with register
554566
; stackification, where copying the stack pointer into the frame pointer was
555567
; moved after the stack pointer was updated for the dynamic alloca.
@@ -617,7 +629,7 @@ define void @copytoreg_fi(i1 %cond, ptr %b) {
617629
; CHECK-32-NEXT: i32.const $push4=, 1
618630
; CHECK-32-NEXT: i32.and $push7=, $pop8, $pop4
619631
; CHECK-32-NEXT: local.set 0, $pop7
620-
; CHECK-32-NEXT: .LBB10_1: # %body
632+
; CHECK-32-NEXT: # %body
621633
; CHECK-32-NEXT: # =>This Inner Loop Header: Depth=1
622634
; CHECK-32-NEXT: loop # label0:
623635
; CHECK-32-NEXT: local.get $push9=, 2
@@ -645,7 +657,7 @@ define void @copytoreg_fi(i1 %cond, ptr %b) {
645657
; CHECK-64-NEXT: i32.const $push4=, 1
646658
; CHECK-64-NEXT: i32.and $push7=, $pop8, $pop4
647659
; CHECK-64-NEXT: local.set 0, $pop7
648-
; CHECK-64-NEXT: .LBB10_1: # %body
660+
; CHECK-64-NEXT: # %body
649661
; CHECK-64-NEXT: # =>This Inner Loop Header: Depth=1
650662
; CHECK-64-NEXT: loop # label0:
651663
; CHECK-64-NEXT: local.get $push9=, 2

0 commit comments

Comments
 (0)