[llvm] [WebAssembly][FastISel] Omit redundant AND for zext of i8/i16 loads (PR #182240)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 19 01:48:57 PST 2026


https://github.com/ParkHanbum created https://github.com/llvm/llvm-project/pull/182240

When zero-extending an i8 or i16 load to i32, FastISel previously emitted an explicit AND instruction to mask the upper bits. This is redundant because WebAssembly's native unsigned load instructions (load8_u and load16_u) inherently zero-extend the loaded values.

Fixes #180783

>From 25077f5e99569fb6f90144063b5d3c02b65738de Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Thu, 19 Feb 2026 18:46:07 +0900
Subject: [PATCH] [WebAssembly][FastISel] Omit redundant AND for zext of i8/i16
 loads

When zero-extending an i8 or i16 load to i32, FastISel previously
emitted an explicit AND instruction to mask the upper bits. This is
redundant because WebAssembly's native unsigned load instructions
(load8_u and load16_u) inherently zero-extend the loaded values.

Fixes #180783
---
 .../Target/WebAssembly/WebAssemblyFastISel.cpp   |  2 ++
 llvm/test/CodeGen/WebAssembly/load-ext.ll        | 16 ++++------------
 llvm/test/CodeGen/WebAssembly/offset-fastisel.ll |  4 +---
 3 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
index c869164d96945..fcadfd1f70871 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -465,6 +465,8 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
     break;
   case MVT::i8:
   case MVT::i16:
+    if (isa<LoadInst>(V))
+      return copyValue(Reg);
     break;
   case MVT::i32:
     return copyValue(Reg);
diff --git a/llvm/test/CodeGen/WebAssembly/load-ext.ll b/llvm/test/CodeGen/WebAssembly/load-ext.ll
index c3460f7916c30..5f93017b1e078 100644
--- a/llvm/test/CodeGen/WebAssembly/load-ext.ll
+++ b/llvm/test/CodeGen/WebAssembly/load-ext.ll
@@ -21,9 +21,7 @@ define i32 @sext_i8_i32(ptr %p) {
 ; DAG: i32.load8_u $push0=, 0($0){{$}}
 ; DAG-NEXT: return $pop0{{$}}
 ; FAST:       i32.load8_u $push[[L:[0-9]+]]=, 0($0)
-; FAST-NEXT:       i32.const   $push[[C:[0-9]+]]=, 255
-; FAST-NEXT:       i32.and     $push[[R:[0-9]+]]=, $pop[[L]], $pop[[C]]
-; FAST-NEXT:       return      $pop[[R]]
+; FAST-NEXT:       return      $pop[[L]]
 define i32 @zext_i8_i32(ptr %p) {
   %v = load i8, ptr %p
   %e = zext i8 %v to i32
@@ -46,9 +44,7 @@ define i32 @sext_i16_i32(ptr %p) {
 ; DAG: i32.load16_u $push0=, 0($0){{$}}
 ; DAG-NEXT: return $pop0{{$}}
 ; FAST:      i32.load16_u $push[[L:[0-9]+]]=, 0($0)
-; FAST-NEXT: i32.const    $push[[C:[0-9]+]]=, 65535
-; FAST-NEXT: i32.and      $push[[R:[0-9]+]]=, $pop[[L]], $pop[[C]]
-; FAST-NEXT: return       $pop[[R]]
+; FAST-NEXT: return       $pop[[L]]
 define i32 @zext_i16_i32(ptr %p) {
   %v = load i16, ptr %p
   %e = zext i16 %v to i32
@@ -72,9 +68,7 @@ define i64 @sext_i8_i64(ptr %p) {
 ; DAG: i64.load8_u $push0=, 0($0){{$}}
 ; DAG-NEXT: return $pop0{{$}}
 ; FAST:      i32.load8_u      $push[[L:[0-9]+]]=, 0($0)
-; FAST-NEXT: i32.const        $push[[C:[0-9]+]]=, 255
-; FAST-NEXT: i32.and          $push[[AND:[0-9]+]]=, $pop[[L]], $pop[[C]]
-; FAST-NEXT: i64.extend_i32_u $push[[EXT:[0-9]+]]=, $pop[[AND]]
+; FAST-NEXT: i64.extend_i32_u $push[[EXT:[0-9]+]]=, $pop[[L]]
 ; FAST-NEXT: return           $pop[[EXT]]
 define i64 @zext_i8_i64(ptr %p) {
   %v = load i8, ptr %p
@@ -99,9 +93,7 @@ define i64 @sext_i16_i64(ptr %p) {
 ; DAG: i64.load16_u $push0=, 0($0){{$}}
 ; DAG-NEXT: return $pop0{{$}}
 ; FAST:      i32.load16_u     $push[[L:[0-9]+]]=, 0($0)
-; FAST-NEXT: i32.const        $push[[C:[0-9]+]]=, 65535
-; FAST-NEXT: i32.and          $push[[AND:[0-9]+]]=, $pop[[L]], $pop[[C]]
-; FAST-NEXT: i64.extend_i32_u $push[[EXT:[0-9]+]]=, $pop[[AND]]
+; FAST-NEXT: i64.extend_i32_u $push[[EXT:[0-9]+]]=, $pop[[L]]
 ; FAST-NEXT: return           $pop[[EXT]]
 define i64 @zext_i16_i64(ptr %p) {
   %v = load i16, ptr %p
diff --git a/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll b/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
index c004410f18122..4b5faa723cf0c 100644
--- a/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
+++ b/llvm/test/CodeGen/WebAssembly/offset-fastisel.ll
@@ -104,9 +104,7 @@ define i32 @load_i8_u_with_folded_offset(ptr %p) {
 ; CHECK-LABEL: load_i8_u_with_folded_offset:
 ; CHECK:         .functype load_i8_u_with_folded_offset (i32) -> (i32)
 ; CHECK-NEXT:  # %bb.0:
-; CHECK-NEXT:    i32.load8_u $push2=, 24($0)
-; CHECK-NEXT:    i32.const $push0=, 255
-; CHECK-NEXT:    i32.and $push1=, $pop2, $pop0
+; CHECK-NEXT:    i32.load8_u $push0=, 24($0)
 ; CHECK-NEXT:    # fallthrough-return
   %q = ptrtoint ptr %p to i32
   %r = add nuw i32 %q, 24



More information about the llvm-commits mailing list