[llvm] [WebAssembly] Define local sp if `llvm.stacksave` is used (PR #68133)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 3 10:34:39 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/68133.diff


2 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp (+8-1) 
- (modified) llvm/test/CodeGen/WebAssembly/userstack.ll (+12) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index e60f1397b993355..d26234e7e71d1d4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -147,7 +147,14 @@ bool WebAssemblyFrameLowering::needsPrologForEH(
 /// Unlike a machine stack pointer, the wasm user stack pointer is a global
 /// variable, so it is loaded into a register in the prolog.
 bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF) const {
-  return needsSPForLocalFrame(MF) || needsPrologForEH(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 needsSPForLocalFrame(MF) || needsPrologForEH(MF) || hasExplicitSPUse;
 }
 
 /// Returns true if the local user-space stack pointer needs to be written back
diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll
index b92946d1a6af7f2..ea0fd49503380d6 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.

``````````

</details>


https://github.com/llvm/llvm-project/pull/68133


More information about the llvm-commits mailing list