[llvm] [WebAssembly] Unstackify operands for removed terminators (PR #149432)

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 18 19:57:38 PDT 2025


aheejin wrote:

@nikic 
> Hm, couldn't this still potentially cause issues with `tee` instructions? That is, if a register does stay unstackified and it happens to be the first result of `tee`?

The only case I can think of is a really contrived case like this:
(I've removed all `implicit` arguments for readability, so this may not run with `llc` out of the box)
```mir
bb.0:
  successors: %bb.1; %bb.1
  %0:i32 = CALL @foo
  %1:i32 = CONST_I32 -1
  %2:i32 = XOR_I32 %0:i32, %1:i32
  BR_IF %bb.1, %2:i32
  BR_IF %bb.1, %2:i32
  BR_IF %bb.1, %2:i32

bb.1:
  ; predecessors: %bb.0
  RETURN
```

Because `%2` is used in both `CALL @use` and  `BR_IF`, we will get a `TEE`:
```mir                                                           
bb.0:                                                                        
  successors: %bb.1; %bb.1                                                            
  %0:i32 = CALL @foo
  %1:i32 = CONST_I32 -1
  %4:i32 = XOR_I32 %0:i32, %1:i32
  %3:i32, %2:i32 = TEE_I32 %4:i32
  BR_IF %bb.1, %3:i32
  BR_IF %bb.1, %2:i32
  BR_IF %bb.1, %2:i32

bb.1:
; predecessors: %bb.0
  RETURN
```
with `%4` and `%3` stackified. (See [this](https://github.com/llvm/llvm-project/blob/cfddb401db111c53f0a345c2a590974487a96bb9/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp#L644-L663) for how it's done)

If all these `BR_IF`s get removed in CFGSort I think the situation you are worried about can occur. If I run this from RegStackify, this fails in here:
https://github.com/llvm/llvm-project/blob/cfddb401db111c53f0a345c2a590974487a96bb9/llvm/lib/CodeGen/MachineBasicBlock.cpp#L706
So I think it's OK to assume that this kind of code is not generated without manually modifying mir files.

In valid code, there will be only one `BR_IF`, so the code could be something like
```mir
bb.0:
  successors: %bb.1; %bb.1
  %0:i32 = CALL @foo
  %1:i32 = CONST_I32 -1
  %2:i32 = XOR_I32 %0:i32, %1:i32
  CALL @use, %2:i32
  CALL @use, %2:i32
  BR_IF %bb.1, %2:i32

bb.1:
  ; predecessors: %bb.0
  RETURN
```

```mir                                                           
bb.0:                                                                        
  successors: %bb.1; %bb.1                                                            
  %0:i32 = CALL @foo
  %1:i32 = CONST_I32 -1
  %4:i32 = XOR_I32 %0:i32, %1:i32
  %3:i32, %2:i32 = TEE_I32 %4:i32
  CALL @use, %3:i32
  CALL @use, %2:i32
  BR_IF %bb.1, %2:i32

bb.1:
; predecessors: %bb.0
  RETURN
```
with `%4` and `%3` stackified.

In this case, even if the `BR_IF` is removed, its operand (%2) is not the stackified register.

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


More information about the llvm-commits mailing list