[llvm] [WebAssembly][FastISel] Fix sext i1 to i64 with +sign-ext (#213734) (PR #214007)

Gauarv Chaudhary via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 22:13:27 PDT 2026


https://github.com/ANAMASGARD updated https://github.com/llvm/llvm-project/pull/214007

>From a867410bf73a965e8afa9f3d9f46bded0f4bf7cd Mon Sep 17 00:00:00 2001
From: Gaurav Chaudhary <chaudharygaurav2004 at gmail.com>
Date: Tue, 4 Aug 2026 22:14:33 +0530
Subject: [PATCH 1/2] =?UTF-8?q?[WebAssembly][FastISel]=20Fix=20sext=20i1?=
 =?UTF-8?q?=20to=20i64=20with=20+sign-ext=20(#213734)=20When=20the=20sign-?=
 =?UTF-8?q?ext=20feature=20is=20enabled,=20signExtend()=20for=20i1?=
 =?UTF-8?q?=E2=86=92i64=20fell=20through=20the=20switch=20without=20emitti?=
 =?UTF-8?q?ng=20any=20instruction,=20returning=20an=20undefined=20register?=
 =?UTF-8?q?.=20This=20broke=20floor-division=20patterns=20that=20adjust=20?=
 =?UTF-8?q?the=20quotient=20via=20sext=20i1,=20producing=20wrong=20results?=
 =?UTF-8?q?=20at=20-O0.=20Restructure=20the=20i64=20sign-extend=20path=20s?=
 =?UTF-8?q?o=20i8,=20i16,=20and=20i32=20use=20their=20native=20extend=20se?=
 =?UTF-8?q?quences,=20while=20i1=20uses=20the=20generic=20signExtendToI32?=
 =?UTF-8?q?=20+=20i64.extend=5Fi32=5Fs=20fallback.=20Unsupported=20types?=
 =?UTF-8?q?=20return=200=20from=20signExtendToI32()=20and=20fail=20FastISe?=
 =?UTF-8?q?l=20cleanly.=20Fixes=20#213734?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Gaurav Chaudhary <chaudharygaurav2004 at gmail.com>
---
 .../WebAssembly/WebAssemblyFastISel.cpp       | 35 ++++++++-----------
 .../test/CodeGen/WebAssembly/signext-inreg.ll | 25 +++++++++++--
 2 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index 95f4367f76cdf..cbfca984c3679 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -583,26 +583,20 @@ unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
     Register Result = createResultReg(&WebAssembly::I64RegClass);
 
     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:
+      case MVT::i16: {
+        Register Tmp = createResultReg(&WebAssembly::I64RegClass);
         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
-                TII.get(WebAssembly::I64_EXTEND8_S_I64), Result)
+                TII.get(WebAssembly::I64_EXTEND_U_I32), Tmp)
             .addReg(Reg);
-        return Result;
-      case MVT::i16:
         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
-                TII.get(WebAssembly::I64_EXTEND16_S_I64), Result)
-            .addReg(Reg);
+                TII.get(From == MVT::i8 ? WebAssembly::I64_EXTEND8_S_I64
+                                        : WebAssembly::I64_EXTEND16_S_I64),
+                Result)
+            .addReg(Tmp);
         return Result;
+      }
       case MVT::i32:
         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
                 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
@@ -611,14 +605,15 @@ unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
       default:
         break;
       }
-    } else {
-      Reg = signExtendToI32(Reg, V, From);
-
-      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
-              TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
-          .addReg(Reg);
     }
 
+    Reg = signExtendToI32(Reg, V, From);
+    if (Reg == 0)
+      return 0;
+
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
+            TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
+        .addReg(Reg);
     return Result;
   }
 
diff --git a/llvm/test/CodeGen/WebAssembly/signext-inreg.ll b/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
index c56ee860082c8..7b4a00cfc9f05 100644
--- a/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
+++ b/llvm/test/CodeGen/WebAssembly/signext-inreg.ll
@@ -1,6 +1,6 @@
-; 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 -mattr=+sign-ext -fast-isel=0 -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,SLOW
 ; RUN: llc < %s -mattr=-sign-ext -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 -mattr=+sign-ext -fast-isel=1 -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,FAST
 ; RUN: llc < %s -mattr=-sign-ext -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"
 
@@ -63,3 +63,24 @@ define i64 @i64_extend32_s(i32 %x) {
   %a = sext i32 %x to i64
   ret i64 %a
 }
+
+; CHECK-LABEL: i64_extend1_s:
+; CHECK-NEXT: .functype i64_extend1_s (i32) -> (i64){{$}}
+; SLOW-NEXT: i64.const $push[[NUM3:[0-9]+]]=, 0{{$}}
+; SLOW-NEXT: i64.extend_i32_u $push[[NUM0:[0-9]+]]=, $0{{$}}
+; SLOW-NEXT: i64.const $push[[NUM1:[0-9]+]]=, 1{{$}}
+; SLOW-NEXT: i64.and $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
+; SLOW-NEXT: i64.sub $push[[NUM4:[0-9]+]]=, $pop[[NUM3]], $pop[[NUM2]]{{$}}
+; SLOW-NEXT: return $pop[[NUM4]]{{$}}
+; FAST-NEXT: i32.const $push[[NUM1:[0-9]+]]=, 31{{$}}
+; FAST-NEXT: i32.shl $push[[NUM0:[0-9]+]]=, $0, $pop[[NUM1]]{{$}}
+; FAST-NEXT: i32.const $push[[NUM4:[0-9]+]]=, 31{{$}}
+; FAST-NEXT: i32.shr_s $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM4]]{{$}}
+; FAST-NEXT: i64.extend_i32_s $push[[NUM3:[0-9]+]]=, $pop[[NUM2]]{{$}}
+; FAST-NEXT: return $pop[[NUM3]]{{$}}
+
+; NOSIGNEXT-LABEL: i64_extend1_s
+define i64 @i64_extend1_s(i1 %x) {
+  %a = sext i1 %x to i64
+  ret i64 %a
+}

>From 3e4d1ac3dc5f04e244515aa19cfaea16c57e9592 Mon Sep 17 00:00:00 2001
From: Gaurav Chaudhary <chaudharygaurav2004 at gmail.com>
Date: Wed, 5 Aug 2026 10:41:03 +0530
Subject: [PATCH 2/2] [WebAssembly][FastISel] Restore i8/i16 register pattern
 in signExtend()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The i1→i64 fix introduced a separate Tmp register for i8/i16 sign
extension, which changed virtual-register push order and broke
fast-isel-atomic-fold.ll FileChecks. Restore the upstream Result/Reg
reuse pattern so codegen matches the autogenerated test expectations.

Part of fix for #213734.

Signed-off-by: Gaurav Chaudhary <chaudharygaurav2004 at gmail.com>
---
 llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index cbfca984c3679..0b608261932e3 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -586,15 +586,18 @@ unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
       switch (From) {
       case MVT::i8:
       case MVT::i16: {
-        Register Tmp = createResultReg(&WebAssembly::I64RegClass);
         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
-                TII.get(WebAssembly::I64_EXTEND_U_I32), Tmp)
+                TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
             .addReg(Reg);
+
+        Reg = Result;
+        Result = createResultReg(&WebAssembly::I64RegClass);
+
         BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
                 TII.get(From == MVT::i8 ? WebAssembly::I64_EXTEND8_S_I64
                                         : WebAssembly::I64_EXTEND16_S_I64),
                 Result)
-            .addReg(Tmp);
+            .addReg(Reg);
         return Result;
       }
       case MVT::i32:



More information about the llvm-commits mailing list