[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 https://github.com/llvm/llvm-project/issues/62235
This commit is contained in:
Yuta Saito 2023-10-03 14:51:35 -07:00 committed by GitHub
parent 37fcad7be9
commit da0ca5dee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 3 deletions

View File

@ -130,7 +130,15 @@ bool WebAssemblyFrameLowering::hasReservedCallFrame(
bool WebAssemblyFrameLowering::needsSPForLocalFrame(
const MachineFunction &MF) const {
auto &MFI = MF.getFrameInfo();
return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF);
auto &MRI = MF.getRegInfo();
// llvm.stacksave can explicitly read SP register and it can appear without
// dynamic alloca.
bool HasExplicitSPUse =
any_of(MRI.use_operands(getSPReg(MF)),
[](MachineOperand &MO) { return !MO.isImplicit(); });
return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF) ||
HasExplicitSPUse;
}
// In function with EH pads, we need to make a copy of the value of

View File

@ -550,6 +550,18 @@ define void @llvm_stack_builtins(i32 %alloc) noredzone {
ret void
}
; Use of stacksave requires local SP definition even without dymamic alloca.
; CHECK-LABEL: llvm_stacksave_noalloca:
define void @llvm_stacksave_noalloca() noredzone {
; CHECK: global.get $push[[L11:.+]]=, __stack_pointer{{$}}
%stack = call i8* @llvm.stacksave()
; CHECK-NEXT: call use_i8_star, $pop[[L11:.+]]
call void @use_i8_star(i8* %stack)
ret void
}
; Not actually using the alloca'd variables exposed an issue with register
; stackification, where copying the stack pointer into the frame pointer was
; moved after the stack pointer was updated for the dynamic alloca.
@ -617,7 +629,7 @@ define void @copytoreg_fi(i1 %cond, ptr %b) {
; CHECK-32-NEXT: i32.const $push4=, 1
; CHECK-32-NEXT: i32.and $push7=, $pop8, $pop4
; CHECK-32-NEXT: local.set 0, $pop7
; CHECK-32-NEXT: .LBB10_1: # %body
; CHECK-32-NEXT: # %body
; CHECK-32-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-32-NEXT: loop # label0:
; CHECK-32-NEXT: local.get $push9=, 2
@ -645,7 +657,7 @@ define void @copytoreg_fi(i1 %cond, ptr %b) {
; CHECK-64-NEXT: i32.const $push4=, 1
; CHECK-64-NEXT: i32.and $push7=, $pop8, $pop4
; CHECK-64-NEXT: local.set 0, $pop7
; CHECK-64-NEXT: .LBB10_1: # %body
; CHECK-64-NEXT: # %body
; CHECK-64-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-64-NEXT: loop # label0:
; CHECK-64-NEXT: local.get $push9=, 2