Skip to content

[WebAssembly] Unstackify registers with no uses in ExplicitLocals #149626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 22, 2025

Conversation

aheejin
Copy link
Member

@aheejin aheejin commented Jul 19, 2025

There are cases we end up removing some intructions that use stackified registers after RegStackify. For example,

bb.0:
  %0 = ...    ;; %0 is stackified
  br_if %bb.1, %0
bb.1:

In this code, br_if will be removed in CFGSort, so we should unstackify %0 so that it can be correctly dropped in ExplicitLocals.

Rather than handling this in case-by-case basis, this PR just unstackifies all stackifies register with no uses in the beginning of ExplicitLocals, so that they can be correctly dropped.

Fixes #149097.

There are cases we end up removing some intructions that use stackified
registers after RegStackify. For example,

```wasm
bb.0:
  %0 = ...    ;; %0 is stackified
  br_if %bb.1, %0
bb.1:
```

In this code, br_if will be removed in CFGSort, so we should unstackify
%0 so that it can be correctly dropped in ExplicitLocals.

Rather than handling this in case-by-case basis, this PR just
unstackifies all stackifies register with no uses, so that they can be
correctly dropped.

Fixes llvm#149097.
@aheejin aheejin requested review from nikic and sunfishcode July 19, 2025 01:23
@aheejin
Copy link
Member Author

aheejin commented Jul 19, 2025

cc @SingleAccretion

@llvmbot
Copy link
Member

llvmbot commented Jul 19, 2025

@llvm/pr-subscribers-backend-webassembly

Author: Heejin Ahn (aheejin)

Changes

There are cases we end up removing some intructions that use stackified registers after RegStackify. For example,

bb.0:
  %0 = ...    ;; %0 is stackified
  br_if %bb.1, %0
bb.1:

In this code, br_if will be removed in CFGSort, so we should unstackify %0 so that it can be correctly dropped in ExplicitLocals.

Rather than handling this in case-by-case basis, this PR just unstackifies all stackifies register with no uses, so that they can be correctly dropped.

Fixes #149097.


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

2 Files Affected:

  • (modified) llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp (+10-2)
  • (added) llvm/test/CodeGen/WebAssembly/removed-terminator.ll (+14)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index 2662241ef8499..ad28e36f29112 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -256,9 +256,17 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
 
   // Precompute the set of registers that are unused, so that we can insert
   // drops to their defs.
+  // And unstackify any stackified registers that don't have any uses, so that
+  // they can be dropped later. This can happen when transformations after
+  // RegStackify removes instructions that use stackified registers.
   BitVector UseEmpty(MRI.getNumVirtRegs());
-  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I)
-    UseEmpty[I] = MRI.use_empty(Register::index2VirtReg(I));
+  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
+    Register Reg = Register::index2VirtReg(I);
+    if (MRI.use_empty(Reg)) {
+      UseEmpty[I] = true;
+      MFI.unstackifyVReg(Reg);
+    }
+  }
 
   // Visit each instruction in the function.
   for (MachineBasicBlock &MBB : MF) {
diff --git a/llvm/test/CodeGen/WebAssembly/removed-terminator.ll b/llvm/test/CodeGen/WebAssembly/removed-terminator.ll
new file mode 100644
index 0000000000000..8c9b6ff4bca97
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/removed-terminator.ll
@@ -0,0 +1,14 @@
+; RUN: llc -O0 < %s
+
+target triple = "wasm32-unknown-unknown"
+
+define void @test(i1 %x) {
+  %y = xor i1 %x, true
+  ; This br_if's operand (%y) is stackified in RegStackify. But this terminator
+  ; will be removed in CFGSort after that. We need to make sure we unstackify %y
+  ; so that it can be dropped in ExplicitLocals.
+  br i1 %y, label %exit, label %exit
+
+exit:
+  ret void
+}

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I confirmed that this also fixes my original issue.

@aheejin aheejin merged commit b13bca7 into llvm:main Jul 22, 2025
9 checks passed
@aheejin aheejin deleted the reg_unstackify branch July 22, 2025 22:34
@nikic nikic added this to the LLVM 21.x Release milestone Jul 23, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Jul 23, 2025
@nikic
Copy link
Contributor

nikic commented Jul 23, 2025

/cherry-pick b13bca7

@llvmbot
Copy link
Member

llvmbot commented Jul 23, 2025

/pull-request #150187

@llvmbot llvmbot moved this from Needs Triage to Done in LLVM Release Status Jul 23, 2025
tru pushed a commit to llvmbot/llvm-project that referenced this pull request Jul 24, 2025
…vm#149626)

There are cases we end up removing some intructions that use stackified
registers after RegStackify. For example,

```wasm
bb.0:
  %0 = ...    ;; %0 is stackified
  br_if %bb.1, %0
bb.1:
```

In this code, br_if will be removed in CFGSort, so we should unstackify
%0 so that it can be correctly dropped in ExplicitLocals.

Rather than handling this in case-by-case basis, this PR just
unstackifies all stackifies register with no uses in the beginning of
ExplicitLocals, so that they can be correctly dropped.

Fixes llvm#149097.

(cherry picked from commit b13bca7)
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Jul 28, 2025
…vm#149626)

There are cases we end up removing some intructions that use stackified
registers after RegStackify. For example,

```wasm
bb.0:
  %0 = ...    ;; %0 is stackified
  br_if %bb.1, %0
bb.1:
```

In this code, br_if will be removed in CFGSort, so we should unstackify
%0 so that it can be correctly dropped in ExplicitLocals.

Rather than handling this in case-by-case basis, this PR just
unstackifies all stackifies register with no uses in the beginning of
ExplicitLocals, so that they can be correctly dropped.

Fixes llvm#149097.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

[WebAssembly] Assertion failure at -O0
3 participants