Issue 180774
Summary [WebAssembly][FastISel] emits redundant explicit zext ('and') after unsigned loads
Labels new issue
Assignees
Reporter ParkHanbum
    Description

When using FastISel (-fast-isel) for the WebAssembly target, the instruction selector emits redundant bitwise and instructions for zext operations, even when the source value was loaded using an unsigned load instruction (i32.load8_u or i32.load16_u).

Since i32.load8_u and i32.load16_u are guaranteed to zero-extend the value according to the WebAssembly specification, the subsequent explicit zero-extension (implemented as and with a mask) is unnecessary and should be optimized away, similar to how SelectionDAG handles it.
Reproduction Steps

Create a file named redundant_zext.ll with the following contentt:

sample: 
```
define i32 @zext_i8_i32(ptr %p) {
e1:
  %v = load atomic i8, ptr %p seq_cst, align 1
  %e = zext i8 %v to i32
  ret i32 %e
}
define i32 @zext_i16_i32(ptr %p) {
  %v = load atomic i16, ptr %p seq_cst, align 2
  %e = zext i16 %v to i32
  ret i32 %e
}

```

isel resuts : 
```
zext_i8_i32:                            # @zext_i8_i32
 .functype       zext_i8_i32 (i32) -> (i32)
# %bb.0: # %e1
        local.get       0
        i32.load8_u 0

zext_i16_i32:                           # @zext_i16_i32
 .functype       zext_i16_i32 (i32) -> (i32)
# %bb.0:
        local.get 0
        i32.load16_u    0
                            
...


Current Behavior (Output)
The generated assembly includes unnecessary i32.const and i32.and instructions.

fast-isel results : 
```
zext_i8_i32: # @zext_i8_i32
        .functype       zext_i8_i32 (i32) -> (i32)
# %bb.0:                                # %e1
        local.get 0
        i32.load8_u     0
        i32.const       255
        i32.and
 end_function

zext_i16_i32:                           # @zext_i16_i32
        .functype       zext_i16_i32 (i32) -> (i32)
# %bb.0:
        local.get       0
        i32.load16_u    0
 i32.const       65535
        i32.and
 end_function

```

Expected Behavior

The zext should be folded into the load instruction (or realized as a no-op), as the value is already zero-extended by the hardware instruction.

```
test_zext_i8:
 local.get 0
    i32.load8_u 0
    # No 'and' instruction needed
 end_function

test_zext_i16:
    local.get 0
    i32.load16_u 0
    # No 'and' instruction needed
    end_function
```

Additional Context

 Target: WebAssembly (wasm32)

    Component: WebAssemblyFastISel.cpp

 Function: SelectZExt

Standard ISel (SelectionDAG) already optimizes this correctly. This seems to be a missed optimization opportunity in FastISel where it doesn't check if the operand is defined by a LOAD8_U or LOAD16_U instruction.









_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to