Issue 71844
Summary WASM: Masking 64-bit Shifts After Zext
Labels new issue
Assignees
Reporter Geotale
    Although capable of doing so after a 16-bit to 32-bit extension of an integer, WASM codegen appears not to be able to optimize the mask of a shift from a 32-bit to 64-bit extension.

```cpp
uint32_t test_32_16(uint32_t x, uint16_t y) {
 return x << (y & 31);
}

uint64_t test_64_32(uint64_t x, uint32_t y) {
    return x << (y & 63);
}
```
is equivalent to the two nearly identical IR functions:
```llvm
define i32 @test_32_16(i32 %x, i16 %y) {
  %1 = and i16 %y, 31
  %2 = zext i16 %1 to i32
  %3 = shl i32 %x, %2
  ret i32 %3
}

define i64 @test_64_32(i64 %x, i32 %y) {
  %1 = and i32 %y, 63
  %2 = zext i32 %1 to i64
  %3 = shl i64 %x, %2
  ret i64 %3
}
```
Compiling with any non-zero optimization level to wasm32-unknown-unknown gives:
```wasm
test_32_16: # @test_32_16
        local.get       0
 local.get       1
        i32.shl 
        end_function
test_64_32: # @test_64_32
        local.get       0
 local.get       1
        i32.const       63
        i32.and 
 i64.extend_i32_u
        i64.shl 
 end_function
```
with the first function eliminating the mask, and the second not doing so.
Clang 13 appears to be the first version in which `test_32_16` eliminates the mask.

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

Reply via email to