[llvm] [WebAssembly][FastISel] Call materializeLoadStoreOperands in load fold (PR #184203)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 10:54:45 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-webassembly
Author: hanbeom (ParkHanbum)
<details>
<summary>Changes</summary>
The `tryToFoldLoadIntoMI` function omitted materializing base registers for addresses before folding sign-extend instructions into loads. This left `$noreg` as the base register, crashing subsequent passes.
WebAssembly memory instructions structurally require a valid base register. Calling the existing `materializeLoadStoreOperands` function ensures that a `CONST 0` virtual register is generated when addressing global variables directly without a pre-existing base register.
(before) %1:i32 = LOAD8_S_I32_A32 0, @<!-- -->ch, $noreg ... -> CRASH (after) %3:i32 = CONST_I32 0
%1:i32 = LOAD8_S_I32_A32 0, @<!-- -->ch, %3:i32 ... -> Folded safely
---
Full diff: https://github.com/llvm/llvm-project/pull/184203.diff
2 Files Affected:
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (+1)
- (modified) llvm/test/CodeGen/WebAssembly/load-ext.ll (+291)
``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 02c3eb2469ea0..faec1acef68f9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -1306,6 +1306,7 @@ bool WebAssemblyFastISel::tryToFoldLoadIntoMI(MachineInstr *MI, unsigned OpNo,
if (!computeAddress(LI->getPointerOperand(), Addr))
return false;
+ materializeLoadStoreOperands(Addr);
Register ResultReg = MI->getOperand(0).getReg();
MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(NewOpc), ResultReg);
diff --git a/llvm/test/CodeGen/WebAssembly/load-ext.ll b/llvm/test/CodeGen/WebAssembly/load-ext.ll
index d15b69fc7c76e..23664a8691d48 100644
--- a/llvm/test/CodeGen/WebAssembly/load-ext.ll
+++ b/llvm/test/CodeGen/WebAssembly/load-ext.ll
@@ -10,6 +10,297 @@
; Test that extending loads are assembled properly.
+ at gv8 = hidden global i8 0, align 1
+ at gv16 = hidden global i16 0, align 1
+
+define i32 @global_sext_i8_i32() {
+; WASM32-DAG-LABEL: global_sext_i8_i32:
+; WASM32-DAG: .functype global_sext_i8_i32 () -> (i32)
+; WASM32-DAG-NEXT: # %bb.0:
+; WASM32-DAG-NEXT: i32.const $push0=, 0
+; WASM32-DAG-NEXT: i32.load8_s $push1=, gv8($pop0)
+; WASM32-DAG-NEXT: return $pop1
+;
+; WASM32-DAG-MVP-LABEL: global_sext_i8_i32:
+; WASM32-DAG-MVP: .functype global_sext_i8_i32 () -> (i32)
+; WASM32-DAG-MVP-NEXT: # %bb.0:
+; WASM32-DAG-MVP-NEXT: i32.const $push0=, 0
+; WASM32-DAG-MVP-NEXT: i32.load8_s $push1=, gv8($pop0)
+; WASM32-DAG-MVP-NEXT: return $pop1
+;
+; WASM32-FAST-LABEL: global_sext_i8_i32:
+; WASM32-FAST: .functype global_sext_i8_i32 () -> (i32)
+; WASM32-FAST-NEXT: # %bb.0:
+; WASM32-FAST-NEXT: i32.const $push1=, 0
+; WASM32-FAST-NEXT: i32.load8_s $push0=, gv8($pop1)
+; WASM32-FAST-NEXT: return $pop0
+;
+; WASM32-FAST-MVP-LABEL: global_sext_i8_i32:
+; WASM32-FAST-MVP: .functype global_sext_i8_i32 () -> (i32)
+; WASM32-FAST-MVP-NEXT: # %bb.0:
+; WASM32-FAST-MVP-NEXT: i32.const $push3=, 0
+; WASM32-FAST-MVP-NEXT: i32.load8_u $push4=, gv8($pop3)
+; WASM32-FAST-MVP-NEXT: i32.const $push0=, 24
+; WASM32-FAST-MVP-NEXT: i32.shl $push1=, $pop4, $pop0
+; WASM32-FAST-MVP-NEXT: i32.const $push5=, 24
+; WASM32-FAST-MVP-NEXT: i32.shr_s $push2=, $pop1, $pop5
+; WASM32-FAST-MVP-NEXT: return $pop2
+;
+; WASM64-DAG-LABEL: global_sext_i8_i32:
+; WASM64-DAG: .functype global_sext_i8_i32 () -> (i32)
+; WASM64-DAG-NEXT: # %bb.0:
+; WASM64-DAG-NEXT: i64.const $push0=, 0
+; WASM64-DAG-NEXT: i32.load8_s $push1=, gv8($pop0)
+; WASM64-DAG-NEXT: return $pop1
+;
+; WASM64-DAG-MVP-LABEL: global_sext_i8_i32:
+; WASM64-DAG-MVP: .functype global_sext_i8_i32 () -> (i32)
+; WASM64-DAG-MVP-NEXT: # %bb.0:
+; WASM64-DAG-MVP-NEXT: i64.const $push0=, 0
+; WASM64-DAG-MVP-NEXT: i32.load8_s $push1=, gv8($pop0)
+; WASM64-DAG-MVP-NEXT: return $pop1
+;
+; WASM64-FAST-LABEL: global_sext_i8_i32:
+; WASM64-FAST: .functype global_sext_i8_i32 () -> (i32)
+; WASM64-FAST-NEXT: # %bb.0:
+; WASM64-FAST-NEXT: i64.const $push1=, 0
+; WASM64-FAST-NEXT: i32.load8_s $push0=, gv8($pop1)
+; WASM64-FAST-NEXT: return $pop0
+;
+; WASM64-FAST-MVP-LABEL: global_sext_i8_i32:
+; WASM64-FAST-MVP: .functype global_sext_i8_i32 () -> (i32)
+; WASM64-FAST-MVP-NEXT: # %bb.0:
+; WASM64-FAST-MVP-NEXT: i64.const $push3=, 0
+; WASM64-FAST-MVP-NEXT: i32.load8_u $push4=, gv8($pop3)
+; WASM64-FAST-MVP-NEXT: i32.const $push0=, 24
+; WASM64-FAST-MVP-NEXT: i32.shl $push1=, $pop4, $pop0
+; WASM64-FAST-MVP-NEXT: i32.const $push5=, 24
+; WASM64-FAST-MVP-NEXT: i32.shr_s $push2=, $pop1, $pop5
+; WASM64-FAST-MVP-NEXT: return $pop2
+ %ld = load i8, ptr @gv8, align 1
+ %conv = sext i8 %ld to i32
+ ret i32 %conv
+}
+
+define i32 @global_sext_i16_i32() {
+; WASM32-DAG-LABEL: global_sext_i16_i32:
+; WASM32-DAG: .functype global_sext_i16_i32 () -> (i32)
+; WASM32-DAG-NEXT: # %bb.0:
+; WASM32-DAG-NEXT: i32.const $push0=, 0
+; WASM32-DAG-NEXT: i32.load16_s $push1=, gv16($pop0):p2align=0
+; WASM32-DAG-NEXT: return $pop1
+;
+; WASM32-DAG-MVP-LABEL: global_sext_i16_i32:
+; WASM32-DAG-MVP: .functype global_sext_i16_i32 () -> (i32)
+; WASM32-DAG-MVP-NEXT: # %bb.0:
+; WASM32-DAG-MVP-NEXT: i32.const $push0=, 0
+; WASM32-DAG-MVP-NEXT: i32.load16_s $push1=, gv16($pop0):p2align=0
+; WASM32-DAG-MVP-NEXT: return $pop1
+;
+; WASM32-FAST-LABEL: global_sext_i16_i32:
+; WASM32-FAST: .functype global_sext_i16_i32 () -> (i32)
+; WASM32-FAST-NEXT: # %bb.0:
+; WASM32-FAST-NEXT: i32.const $push1=, 0
+; WASM32-FAST-NEXT: i32.load16_s $push0=, gv16($pop1):p2align=0
+; WASM32-FAST-NEXT: return $pop0
+;
+; WASM32-FAST-MVP-LABEL: global_sext_i16_i32:
+; WASM32-FAST-MVP: .functype global_sext_i16_i32 () -> (i32)
+; WASM32-FAST-MVP-NEXT: # %bb.0:
+; WASM32-FAST-MVP-NEXT: i32.const $push3=, 0
+; WASM32-FAST-MVP-NEXT: i32.load16_u $push4=, gv16($pop3):p2align=0
+; WASM32-FAST-MVP-NEXT: i32.const $push0=, 16
+; WASM32-FAST-MVP-NEXT: i32.shl $push1=, $pop4, $pop0
+; WASM32-FAST-MVP-NEXT: i32.const $push5=, 16
+; WASM32-FAST-MVP-NEXT: i32.shr_s $push2=, $pop1, $pop5
+; WASM32-FAST-MVP-NEXT: return $pop2
+;
+; WASM64-DAG-LABEL: global_sext_i16_i32:
+; WASM64-DAG: .functype global_sext_i16_i32 () -> (i32)
+; WASM64-DAG-NEXT: # %bb.0:
+; WASM64-DAG-NEXT: i64.const $push0=, 0
+; WASM64-DAG-NEXT: i32.load16_s $push1=, gv16($pop0):p2align=0
+; WASM64-DAG-NEXT: return $pop1
+;
+; WASM64-DAG-MVP-LABEL: global_sext_i16_i32:
+; WASM64-DAG-MVP: .functype global_sext_i16_i32 () -> (i32)
+; WASM64-DAG-MVP-NEXT: # %bb.0:
+; WASM64-DAG-MVP-NEXT: i64.const $push0=, 0
+; WASM64-DAG-MVP-NEXT: i32.load16_s $push1=, gv16($pop0):p2align=0
+; WASM64-DAG-MVP-NEXT: return $pop1
+;
+; WASM64-FAST-LABEL: global_sext_i16_i32:
+; WASM64-FAST: .functype global_sext_i16_i32 () -> (i32)
+; WASM64-FAST-NEXT: # %bb.0:
+; WASM64-FAST-NEXT: i64.const $push1=, 0
+; WASM64-FAST-NEXT: i32.load16_s $push0=, gv16($pop1):p2align=0
+; WASM64-FAST-NEXT: return $pop0
+;
+; WASM64-FAST-MVP-LABEL: global_sext_i16_i32:
+; WASM64-FAST-MVP: .functype global_sext_i16_i32 () -> (i32)
+; WASM64-FAST-MVP-NEXT: # %bb.0:
+; WASM64-FAST-MVP-NEXT: i64.const $push3=, 0
+; WASM64-FAST-MVP-NEXT: i32.load16_u $push4=, gv16($pop3):p2align=0
+; WASM64-FAST-MVP-NEXT: i32.const $push0=, 16
+; WASM64-FAST-MVP-NEXT: i32.shl $push1=, $pop4, $pop0
+; WASM64-FAST-MVP-NEXT: i32.const $push5=, 16
+; WASM64-FAST-MVP-NEXT: i32.shr_s $push2=, $pop1, $pop5
+; WASM64-FAST-MVP-NEXT: return $pop2
+ %ld = load i16, ptr @gv16, align 1
+ %conv = sext i16 %ld to i32
+ ret i32 %conv
+}
+
+define i64 @global_sext_i8_i64() {
+; WASM32-DAG-LABEL: global_sext_i8_i64:
+; WASM32-DAG: .functype global_sext_i8_i64 () -> (i64)
+; WASM32-DAG-NEXT: # %bb.0:
+; WASM32-DAG-NEXT: i32.const $push0=, 0
+; WASM32-DAG-NEXT: i64.load8_s $push1=, gv8($pop0)
+; WASM32-DAG-NEXT: return $pop1
+;
+; WASM32-DAG-MVP-LABEL: global_sext_i8_i64:
+; WASM32-DAG-MVP: .functype global_sext_i8_i64 () -> (i64)
+; WASM32-DAG-MVP-NEXT: # %bb.0:
+; WASM32-DAG-MVP-NEXT: i32.const $push0=, 0
+; WASM32-DAG-MVP-NEXT: i64.load8_s $push1=, gv8($pop0)
+; WASM32-DAG-MVP-NEXT: return $pop1
+;
+; WASM32-FAST-LABEL: global_sext_i8_i64:
+; WASM32-FAST: .functype global_sext_i8_i64 () -> (i64)
+; WASM32-FAST-NEXT: # %bb.0:
+; WASM32-FAST-NEXT: i32.const $push2=, 0
+; WASM32-FAST-NEXT: i32.load8_u $push3=, gv8($pop2)
+; WASM32-FAST-NEXT: i64.extend_i32_u $push0=, $pop3
+; WASM32-FAST-NEXT: i64.extend8_s $push1=, $pop0
+; WASM32-FAST-NEXT: return $pop1
+;
+; WASM32-FAST-MVP-LABEL: global_sext_i8_i64:
+; WASM32-FAST-MVP: .functype global_sext_i8_i64 () -> (i64)
+; WASM32-FAST-MVP-NEXT: # %bb.0:
+; WASM32-FAST-MVP-NEXT: i32.const $push4=, 0
+; WASM32-FAST-MVP-NEXT: i32.load8_u $push5=, gv8($pop4)
+; WASM32-FAST-MVP-NEXT: i32.const $push1=, 24
+; WASM32-FAST-MVP-NEXT: i32.shl $push2=, $pop5, $pop1
+; WASM32-FAST-MVP-NEXT: i32.const $push6=, 24
+; WASM32-FAST-MVP-NEXT: i32.shr_s $push3=, $pop2, $pop6
+; WASM32-FAST-MVP-NEXT: i64.extend_i32_s $push0=, $pop3
+; WASM32-FAST-MVP-NEXT: return $pop0
+;
+; WASM64-DAG-LABEL: global_sext_i8_i64:
+; WASM64-DAG: .functype global_sext_i8_i64 () -> (i64)
+; WASM64-DAG-NEXT: # %bb.0:
+; WASM64-DAG-NEXT: i64.const $push0=, 0
+; WASM64-DAG-NEXT: i64.load8_s $push1=, gv8($pop0)
+; WASM64-DAG-NEXT: return $pop1
+;
+; WASM64-DAG-MVP-LABEL: global_sext_i8_i64:
+; WASM64-DAG-MVP: .functype global_sext_i8_i64 () -> (i64)
+; WASM64-DAG-MVP-NEXT: # %bb.0:
+; WASM64-DAG-MVP-NEXT: i64.const $push0=, 0
+; WASM64-DAG-MVP-NEXT: i64.load8_s $push1=, gv8($pop0)
+; WASM64-DAG-MVP-NEXT: return $pop1
+;
+; WASM64-FAST-LABEL: global_sext_i8_i64:
+; WASM64-FAST: .functype global_sext_i8_i64 () -> (i64)
+; WASM64-FAST-NEXT: # %bb.0:
+; WASM64-FAST-NEXT: i64.const $push2=, 0
+; WASM64-FAST-NEXT: i32.load8_u $push3=, gv8($pop2)
+; WASM64-FAST-NEXT: i64.extend_i32_u $push0=, $pop3
+; WASM64-FAST-NEXT: i64.extend8_s $push1=, $pop0
+; WASM64-FAST-NEXT: return $pop1
+;
+; WASM64-FAST-MVP-LABEL: global_sext_i8_i64:
+; WASM64-FAST-MVP: .functype global_sext_i8_i64 () -> (i64)
+; WASM64-FAST-MVP-NEXT: # %bb.0:
+; WASM64-FAST-MVP-NEXT: i64.const $push4=, 0
+; WASM64-FAST-MVP-NEXT: i32.load8_u $push5=, gv8($pop4)
+; WASM64-FAST-MVP-NEXT: i32.const $push1=, 24
+; WASM64-FAST-MVP-NEXT: i32.shl $push2=, $pop5, $pop1
+; WASM64-FAST-MVP-NEXT: i32.const $push6=, 24
+; WASM64-FAST-MVP-NEXT: i32.shr_s $push3=, $pop2, $pop6
+; WASM64-FAST-MVP-NEXT: i64.extend_i32_s $push0=, $pop3
+; WASM64-FAST-MVP-NEXT: return $pop0
+ %ld = load i8, ptr @gv8, align 1
+ %conv = sext i8 %ld to i64
+ ret i64 %conv
+}
+
+define i64 @global_sext_i16_i64() {
+; WASM32-DAG-LABEL: global_sext_i16_i64:
+; WASM32-DAG: .functype global_sext_i16_i64 () -> (i64)
+; WASM32-DAG-NEXT: # %bb.0:
+; WASM32-DAG-NEXT: i32.const $push0=, 0
+; WASM32-DAG-NEXT: i64.load16_s $push1=, gv16($pop0):p2align=0
+; WASM32-DAG-NEXT: return $pop1
+;
+; WASM32-DAG-MVP-LABEL: global_sext_i16_i64:
+; WASM32-DAG-MVP: .functype global_sext_i16_i64 () -> (i64)
+; WASM32-DAG-MVP-NEXT: # %bb.0:
+; WASM32-DAG-MVP-NEXT: i32.const $push0=, 0
+; WASM32-DAG-MVP-NEXT: i64.load16_s $push1=, gv16($pop0):p2align=0
+; WASM32-DAG-MVP-NEXT: return $pop1
+;
+; WASM32-FAST-LABEL: global_sext_i16_i64:
+; WASM32-FAST: .functype global_sext_i16_i64 () -> (i64)
+; WASM32-FAST-NEXT: # %bb.0:
+; WASM32-FAST-NEXT: i32.const $push2=, 0
+; WASM32-FAST-NEXT: i32.load16_u $push3=, gv16($pop2):p2align=0
+; WASM32-FAST-NEXT: i64.extend_i32_u $push0=, $pop3
+; WASM32-FAST-NEXT: i64.extend16_s $push1=, $pop0
+; WASM32-FAST-NEXT: return $pop1
+;
+; WASM32-FAST-MVP-LABEL: global_sext_i16_i64:
+; WASM32-FAST-MVP: .functype global_sext_i16_i64 () -> (i64)
+; WASM32-FAST-MVP-NEXT: # %bb.0:
+; WASM32-FAST-MVP-NEXT: i32.const $push4=, 0
+; WASM32-FAST-MVP-NEXT: i32.load16_u $push5=, gv16($pop4):p2align=0
+; WASM32-FAST-MVP-NEXT: i32.const $push1=, 16
+; WASM32-FAST-MVP-NEXT: i32.shl $push2=, $pop5, $pop1
+; WASM32-FAST-MVP-NEXT: i32.const $push6=, 16
+; WASM32-FAST-MVP-NEXT: i32.shr_s $push3=, $pop2, $pop6
+; WASM32-FAST-MVP-NEXT: i64.extend_i32_s $push0=, $pop3
+; WASM32-FAST-MVP-NEXT: return $pop0
+;
+; WASM64-DAG-LABEL: global_sext_i16_i64:
+; WASM64-DAG: .functype global_sext_i16_i64 () -> (i64)
+; WASM64-DAG-NEXT: # %bb.0:
+; WASM64-DAG-NEXT: i64.const $push0=, 0
+; WASM64-DAG-NEXT: i64.load16_s $push1=, gv16($pop0):p2align=0
+; WASM64-DAG-NEXT: return $pop1
+;
+; WASM64-DAG-MVP-LABEL: global_sext_i16_i64:
+; WASM64-DAG-MVP: .functype global_sext_i16_i64 () -> (i64)
+; WASM64-DAG-MVP-NEXT: # %bb.0:
+; WASM64-DAG-MVP-NEXT: i64.const $push0=, 0
+; WASM64-DAG-MVP-NEXT: i64.load16_s $push1=, gv16($pop0):p2align=0
+; WASM64-DAG-MVP-NEXT: return $pop1
+;
+; WASM64-FAST-LABEL: global_sext_i16_i64:
+; WASM64-FAST: .functype global_sext_i16_i64 () -> (i64)
+; WASM64-FAST-NEXT: # %bb.0:
+; WASM64-FAST-NEXT: i64.const $push2=, 0
+; WASM64-FAST-NEXT: i32.load16_u $push3=, gv16($pop2):p2align=0
+; WASM64-FAST-NEXT: i64.extend_i32_u $push0=, $pop3
+; WASM64-FAST-NEXT: i64.extend16_s $push1=, $pop0
+; WASM64-FAST-NEXT: return $pop1
+;
+; WASM64-FAST-MVP-LABEL: global_sext_i16_i64:
+; WASM64-FAST-MVP: .functype global_sext_i16_i64 () -> (i64)
+; WASM64-FAST-MVP-NEXT: # %bb.0:
+; WASM64-FAST-MVP-NEXT: i64.const $push4=, 0
+; WASM64-FAST-MVP-NEXT: i32.load16_u $push5=, gv16($pop4):p2align=0
+; WASM64-FAST-MVP-NEXT: i32.const $push1=, 16
+; WASM64-FAST-MVP-NEXT: i32.shl $push2=, $pop5, $pop1
+; WASM64-FAST-MVP-NEXT: i32.const $push6=, 16
+; WASM64-FAST-MVP-NEXT: i32.shr_s $push3=, $pop2, $pop6
+; WASM64-FAST-MVP-NEXT: i64.extend_i32_s $push0=, $pop3
+; WASM64-FAST-MVP-NEXT: return $pop0
+ %ld= load i16, ptr @gv16, align 1
+ %conv = sext i16 %ld to i64
+ ret i64 %conv
+}
+
define i32 @sext_i8_i32(ptr %p) {
; WASM32-DAG-LABEL: sext_i8_i32:
; WASM32-DAG: .functype sext_i8_i32 (i32) -> (i32)
``````````
</details>
https://github.com/llvm/llvm-project/pull/184203
More information about the llvm-commits
mailing list