diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp index e60f1397b9933..8f3ad167ae41f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -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 diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll index b92946d1a6af7..f7bdcdd42ba13 100644 --- a/llvm/test/CodeGen/WebAssembly/userstack.ll +++ b/llvm/test/CodeGen/WebAssembly/userstack.ll @@ -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