Jasmine Tang d7a29e5d56
[WebAssembly] Reapply #149461 with correct CondCode in combine of SETCC (#153703)
This PR reapplies https://github.com/llvm/llvm-project/pull/149461

In the original `combineVectorSizedSetCCEquality`, the result of setcc
is being negated by returning setcc with the same cond code, leading to
wrong logic.

For example, with
```llvm
 %cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16)
  %res = icmp eq i32 %cmp_16, 0
```

the original PR producese all_true and then also compares the result
equal to 0 (using the same SETEQ in the returning setcc), meaning that
semantically, it effectively is calling icmp ne.

Instead, the PR should have use SETNE in the returning setcc, this way,
all true return 1, then it is compared again ne 0, which is equivalent
to icmp eq.
2025-08-15 12:06:47 -07:00

143 lines
5.2 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s
target triple = "wasm32-unknown-unknown"
declare i32 @memcmp(ptr, ptr, i32)
define i1 @memcmp_expand_3(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_3:
; CHECK: .functype memcmp_expand_3 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.load16_u $push7=, 0($0):p2align=0
; CHECK-NEXT: i32.load16_u $push6=, 0($1):p2align=0
; CHECK-NEXT: i32.xor $push8=, $pop7, $pop6
; CHECK-NEXT: i32.const $push0=, 2
; CHECK-NEXT: i32.add $push3=, $0, $pop0
; CHECK-NEXT: i32.load8_u $push4=, 0($pop3)
; CHECK-NEXT: i32.const $push13=, 2
; CHECK-NEXT: i32.add $push1=, $1, $pop13
; CHECK-NEXT: i32.load8_u $push2=, 0($pop1)
; CHECK-NEXT: i32.xor $push5=, $pop4, $pop2
; CHECK-NEXT: i32.or $push9=, $pop8, $pop5
; CHECK-NEXT: i32.const $push10=, 65535
; CHECK-NEXT: i32.and $push11=, $pop9, $pop10
; CHECK-NEXT: i32.eqz $push12=, $pop11
; CHECK-NEXT: return $pop12
%cmp_3 = call i32 @memcmp(ptr %a, ptr %b, i32 3)
%res = icmp eq i32 %cmp_3, 0
ret i1 %res
}
define i1 @memcmp_expand_5(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_5:
; CHECK: .functype memcmp_expand_5 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.load $push7=, 0($0):p2align=0
; CHECK-NEXT: i32.load $push6=, 0($1):p2align=0
; CHECK-NEXT: i32.xor $push8=, $pop7, $pop6
; CHECK-NEXT: i32.const $push0=, 4
; CHECK-NEXT: i32.add $push3=, $0, $pop0
; CHECK-NEXT: i32.load8_u $push4=, 0($pop3)
; CHECK-NEXT: i32.const $push11=, 4
; CHECK-NEXT: i32.add $push1=, $1, $pop11
; CHECK-NEXT: i32.load8_u $push2=, 0($pop1)
; CHECK-NEXT: i32.xor $push5=, $pop4, $pop2
; CHECK-NEXT: i32.or $push9=, $pop8, $pop5
; CHECK-NEXT: i32.eqz $push10=, $pop9
; CHECK-NEXT: return $pop10
%cmp_5 = call i32 @memcmp(ptr %a, ptr %b, i32 5)
%res = icmp eq i32 %cmp_5, 0
ret i1 %res
}
define i1 @memcmp_expand_7(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_7:
; CHECK: .functype memcmp_expand_7 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.load $push7=, 0($0):p2align=0
; CHECK-NEXT: i32.load $push6=, 0($1):p2align=0
; CHECK-NEXT: i32.xor $push8=, $pop7, $pop6
; CHECK-NEXT: i32.const $push0=, 3
; CHECK-NEXT: i32.add $push3=, $0, $pop0
; CHECK-NEXT: i32.load $push4=, 0($pop3):p2align=0
; CHECK-NEXT: i32.const $push11=, 3
; CHECK-NEXT: i32.add $push1=, $1, $pop11
; CHECK-NEXT: i32.load $push2=, 0($pop1):p2align=0
; CHECK-NEXT: i32.xor $push5=, $pop4, $pop2
; CHECK-NEXT: i32.or $push9=, $pop8, $pop5
; CHECK-NEXT: i32.eqz $push10=, $pop9
; CHECK-NEXT: return $pop10
%cmp_7 = call i32 @memcmp(ptr %a, ptr %b, i32 7)
%res = icmp eq i32 %cmp_7, 0
ret i1 %res
}
; INFO: Negative test
; Should not expand even with simd128
define i1 @memcmp_expand_129(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_129:
; CHECK: .functype memcmp_expand_129 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.const $push0=, 129
; CHECK-NEXT: call $push1=, memcmp, $0, $1, $pop0
; CHECK-NEXT: i32.eqz $push2=, $pop1
; CHECK-NEXT: return $pop2
%cmp_129 = call i32 @memcmp(ptr %a, ptr %b, i32 129)
%res = icmp eq i32 %cmp_129, 0
ret i1 %res
}
define i1 @memcmp_expand_2(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_2:
; CHECK: .functype memcmp_expand_2 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.load16_u $push1=, 0($0):p2align=0
; CHECK-NEXT: i32.load16_u $push0=, 0($1):p2align=0
; CHECK-NEXT: i32.eq $push2=, $pop1, $pop0
; CHECK-NEXT: return $pop2
%cmp_2 = call i32 @memcmp(ptr %a, ptr %b, i32 2)
%res = icmp eq i32 %cmp_2, 0
ret i1 %res
}
define i1 @memcmp_expand_2_align(ptr align(2) %a, ptr align(2) %b) {
; CHECK-LABEL: memcmp_expand_2_align:
; CHECK: .functype memcmp_expand_2_align (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i32.load16_u $push1=, 0($0)
; CHECK-NEXT: i32.load16_u $push0=, 0($1)
; CHECK-NEXT: i32.eq $push2=, $pop1, $pop0
; CHECK-NEXT: return $pop2
%cmp_2 = call i32 @memcmp(ptr %a, ptr %b, i32 2)
%res = icmp eq i32 %cmp_2, 0
ret i1 %res
}
define i1 @memcmp_expand_8(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_8:
; CHECK: .functype memcmp_expand_8 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: i64.load $push1=, 0($0):p2align=0
; CHECK-NEXT: i64.load $push0=, 0($1):p2align=0
; CHECK-NEXT: i64.eq $push2=, $pop1, $pop0
; CHECK-NEXT: return $pop2
%cmp_8 = call i32 @memcmp(ptr %a, ptr %b, i32 8)
%res = icmp eq i32 %cmp_8, 0
ret i1 %res
}
define i1 @memcmp_expand_16(ptr %a, ptr %b) {
; CHECK-LABEL: memcmp_expand_16:
; CHECK: .functype memcmp_expand_16 (i32, i32) -> (i32)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: v128.load $push1=, 0($0):p2align=0
; CHECK-NEXT: v128.load $push0=, 0($1):p2align=0
; CHECK-NEXT: i8x16.eq $push2=, $pop1, $pop0
; CHECK-NEXT: i8x16.all_true $push3=, $pop2
; CHECK-NEXT: return $pop3
%cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16)
%res = icmp eq i32 %cmp_16, 0
ret i1 %res
}