[llvm] [WebAssembly][FastISel] Make use of `sign-ext` proposals instructions when available (PR #179855)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 4 21:11:38 PST 2026
https://github.com/QuantumSegfault updated https://github.com/llvm/llvm-project/pull/179855
>From 48afd3b814577781d1f6be7473e3564ffefd3d22 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Wed, 4 Feb 2026 19:53:42 -0800
Subject: [PATCH] Make use of sign-ext proposal instructions in FastISel
---
.../WebAssembly/WebAssemblyFastISel.cpp | 78 +++++++++++++++----
.../CodeGen/WebAssembly/offset-fastisel.ll | 7 +-
llvm/test/CodeGen/WebAssembly/signext-arg.ll | 7 +-
.../test/CodeGen/WebAssembly/signext-inreg.ll | 7 +-
4 files changed, 69 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index f4860e21e310e..c869164d96945 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -478,8 +478,8 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
.addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Register Result = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
- TII.get(WebAssembly::AND_I32), Result)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::AND_I32),
+ Result)
.addReg(Reg)
.addReg(Imm);
@@ -502,14 +502,26 @@ unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
return 0;
}
+ if (Subtarget->hasSignExt()) {
+ if (From == MVT::i8 || From == MVT::i16) {
+ Register Result = createResultReg(&WebAssembly::I32RegClass);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(From == MVT::i16 ? WebAssembly::I32_EXTEND16_S_I32
+ : WebAssembly::I32_EXTEND8_S_I32),
+ Result)
+ .addReg(Reg);
+ return Result;
+ }
+ }
+
Register Imm = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::CONST_I32), Imm)
.addImm(32 - MVT(From).getSizeInBits());
Register Left = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
- TII.get(WebAssembly::SHL_I32), Left)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::SHL_I32),
+ Left)
.addReg(Reg)
.addReg(Imm);
@@ -551,12 +563,45 @@ unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
if (From == MVT::i64)
return copyValue(Reg);
- Reg = signExtendToI32(Reg, V, From);
-
Register Result = createResultReg(&WebAssembly::I64RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
- TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
- .addReg(Reg);
+
+ if (Subtarget->hasSignExt()) {
+ if (From != MVT::i32) {
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
+ .addReg(Reg);
+
+ Reg = Result;
+ Result = createResultReg(&WebAssembly::I64RegClass);
+ }
+
+ switch (From) {
+ case MVT::i8:
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(WebAssembly::I64_EXTEND8_S_I64), Result)
+ .addReg(Reg);
+ return Result;
+ case MVT::i16:
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(WebAssembly::I64_EXTEND16_S_I64), Result)
+ .addReg(Reg);
+ return Result;
+ case MVT::i32:
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
+ .addReg(Reg);
+ return Result;
+ default:
+ break;
+ }
+ } else {
+ Reg = signExtendToI32(Reg, V, From);
+
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+ TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
+ .addReg(Reg);
+ }
+
return Result;
}
@@ -597,8 +642,8 @@ unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
Register NotReg = createResultReg(&WebAssembly::I32RegClass);
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
- TII.get(WebAssembly::EQZ_I32), NotReg)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::EQZ_I32),
+ NotReg)
.addReg(Reg);
return NotReg;
}
@@ -1210,8 +1255,8 @@ bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
return true;
}
- Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
- In);
+ Register Reg =
+ fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), In);
if (!Reg)
return false;
MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
@@ -1273,8 +1318,8 @@ bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
materializeLoadStoreOperands(Addr);
Register ResultReg = createResultReg(RC);
- auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc),
- ResultReg);
+ auto MIB =
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg);
addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
@@ -1422,8 +1467,7 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
if (Reg == 0)
return false;
- BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
- TII.get(WebAssembly::RETURN))
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::RETURN))
.addReg(Reg);
return true;
}
diff --git a/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll b/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
index b896f8fde247e..5d82bb9a0a771 100644
--- a/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
+++ b/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
@@ -120,11 +120,8 @@ define i32 @load_i8_s_with_folded_offset(ptr %p) {
; CHECK-LABEL: load_i8_s_with_folded_offset:
; CHECK: .functype load_i8_s_with_folded_offset (i32) -> (i32)
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.load8_u $push3=, 24($0)
-; CHECK-NEXT: i32.const $push0=, 24
-; CHECK-NEXT: i32.shl $push1=, $pop3, $pop0
-; CHECK-NEXT: i32.const $push4=, 24
-; CHECK-NEXT: i32.shr_s $push2=, $pop1, $pop4
+; CHECK-NEXT: i32.load8_u $push1=, 24($0)
+; CHECK-NEXT: i32.extend8_s $push0=, $pop1
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint ptr %p to i32
%r = add nuw i32 %q, 24
diff --git a/llvm/test/CodeGen/WebAssembly/signext-arg.ll b/llvm/test/CodeGen/WebAssembly/signext-arg.ll
index fa595056c840c..d9f3a8a95b3b7 100644
--- a/llvm/test/CodeGen/WebAssembly/signext-arg.ll
+++ b/llvm/test/CodeGen/WebAssembly/signext-arg.ll
@@ -7,11 +7,8 @@ declare i32 @get_int(i16 %arg)
define i32 @func_1(i16 %arg1 , i32 %arg2) #0 {
; CHECK-LABEL: func_1:
-; CHECK: i32.const $push1=, 16
-; CHECK-NEXT: i32.shl $push2=, $0, $pop1
-; CHECK-NEXT: i32.const $push4=, 16
-; CHECK-NEXT: i32.shr_s $push3=, $pop2, $pop4
-; CHECK-NEXT: call $push0=, get_int, $pop3
+; CHECK: i32.extend16_s $push1=, $0
+; CHECK-NEXT: call $push0=, get_int, $pop1
; CHECK-NEXT: end_function
entry:
%retval = call i32 @get_int(i16 signext %arg1)
diff --git a/llvm/test/CodeGen/WebAssembly/signext-inreg.ll b/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
index 5778a9418a3d4..2a98b14226ab4 100644
--- a/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
+++ b/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
@@ -1,6 +1,7 @@
-; RUN: llc < %s -mattr=+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=NOSIGNEXT
-
+; RUN: llc < %s -mattr=+sign-ext -fast-isel=0 -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -fast-isel=0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=NOSIGNEXT
+; RUN: llc < %s -mattr=+sign-ext -fast-isel=1 -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -fast-isel=1 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=NOSIGNEXT
target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: i32_extend8_s:
More information about the llvm-commits
mailing list