[llvm] Revert revert fix teach load (PR #153703)
Jasmine Tang via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 14 15:22:52 PDT 2025
https://github.com/badumbatish created https://github.com/llvm/llvm-project/pull/153703
This PR reapplies https://github.com/llvm/llvm-project/pull/153360.
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.
>From 39ac6965a8dcc17b8db0af979ad97cc7a3a9f068 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Thu, 14 Aug 2025 14:48:09 -0700
Subject: [PATCH 1/2] Reapply "[WebAssembly] Combine i128 to v16i8 for setcc &
expand memcmp for 16 byte loads with simd128" (#153360)
This reverts commit d32793ca6e19e7b23fe0fa3fd1d550ecc919b9ed.
---
.../WebAssembly/WebAssemblyISelLowering.cpp | 54 ++++++++++-
.../WebAssemblyTargetTransformInfo.cpp | 3 +-
.../test/CodeGen/WebAssembly/memcmp-expand.ll | 22 ++---
llvm/test/CodeGen/WebAssembly/simd-setcc.ll | 89 +++++++++++++++++++
4 files changed, 150 insertions(+), 18 deletions(-)
create mode 100644 llvm/test/CodeGen/WebAssembly/simd-setcc.ll
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 8baca2ad3133e..144872e4366e0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -3386,8 +3386,55 @@ static SDValue TryMatchTrue(SDNode *N, EVT VecVT, SelectionDAG &DAG) {
return DAG.getZExtOrTrunc(Ret, DL, N->getValueType(0));
}
+/// Try to convert a i128 comparison to a v16i8 comparison before type
+/// legalization splits it up into chunks
+static SDValue
+combineVectorSizedSetCCEquality(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
+ const WebAssemblySubtarget *Subtarget) {
+
+ SDLoc DL(N);
+ SDValue X = N->getOperand(0);
+ SDValue Y = N->getOperand(1);
+ EVT VT = N->getValueType(0);
+ EVT OpVT = X.getValueType();
+
+ SelectionDAG &DAG = DCI.DAG;
+ if (DCI.DAG.getMachineFunction().getFunction().hasFnAttribute(
+ Attribute::NoImplicitFloat))
+ return SDValue();
+
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ // We're looking for an oversized integer equality comparison with SIMD
+ if (!OpVT.isScalarInteger() || !OpVT.isByteSized() || OpVT != MVT::i128 ||
+ !Subtarget->hasSIMD128() || !isIntEqualitySetCC(CC))
+ return SDValue();
+
+ // Don't perform this combine if constructing the vector will be expensive.
+ auto IsVectorBitCastCheap = [](SDValue X) {
+ X = peekThroughBitcasts(X);
+ return isa<ConstantSDNode>(X) || X.getOpcode() == ISD::LOAD;
+ };
+
+ if (!IsVectorBitCastCheap(X) || !IsVectorBitCastCheap(Y))
+ return SDValue();
+
+ SDValue VecX = DAG.getBitcast(MVT::v16i8, X);
+ SDValue VecY = DAG.getBitcast(MVT::v16i8, Y);
+ SDValue Cmp = DAG.getSetCC(DL, MVT::v16i8, VecX, VecY, CC);
+
+ SDValue Intr =
+ DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
+ {DAG.getConstant(CC == ISD::SETEQ ? Intrinsic::wasm_alltrue
+ : Intrinsic::wasm_anytrue,
+ DL, MVT::i32),
+ Cmp});
+
+ return DAG.getSetCC(DL, VT, Intr, DAG.getConstant(0, DL, MVT::i32), CC);
+}
+
static SDValue performSETCCCombine(SDNode *N,
- TargetLowering::DAGCombinerInfo &DCI) {
+ TargetLowering::DAGCombinerInfo &DCI,
+ const WebAssemblySubtarget *Subtarget) {
if (!DCI.isBeforeLegalize())
return SDValue();
@@ -3395,6 +3442,9 @@ static SDValue performSETCCCombine(SDNode *N,
if (!VT.isScalarInteger())
return SDValue();
+ if (SDValue V = combineVectorSizedSetCCEquality(N, DCI, Subtarget))
+ return V;
+
SDValue LHS = N->getOperand(0);
if (LHS->getOpcode() != ISD::BITCAST)
return SDValue();
@@ -3574,7 +3624,7 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::BITCAST:
return performBitcastCombine(N, DCI);
case ISD::SETCC:
- return performSETCCCombine(N, DCI);
+ return performSETCCCombine(N, DCI, Subtarget);
case ISD::VECTOR_SHUFFLE:
return performVECTOR_SHUFFLECombine(N, DCI);
case ISD::SIGN_EXTEND:
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
index 52e706514226b..08fb7586d215e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
@@ -147,7 +147,8 @@ WebAssemblyTTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
Options.AllowOverlappingLoads = true;
- // TODO: Teach WebAssembly backend about load v128.
+ if (ST->hasSIMD128())
+ Options.LoadSizes.push_back(16);
Options.LoadSizes.append({8, 4, 2, 1});
Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
diff --git a/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll b/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
index 8030438645f82..9c520ff9a4db7 100644
--- a/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
+++ b/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
@@ -1,5 +1,5 @@
; 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 | FileCheck %s
+; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s
target triple = "wasm32-unknown-unknown"
@@ -127,24 +127,16 @@ define i1 @memcmp_expand_8(ptr %a, ptr %b) {
ret i1 %res
}
-; TODO: Should be using a single load i64x2 or equivalent in bitsizes
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: i64.load $push7=, 0($0):p2align=0
-; CHECK-NEXT: i64.load $push6=, 0($1):p2align=0
-; CHECK-NEXT: i64.xor $push8=, $pop7, $pop6
-; CHECK-NEXT: i32.const $push0=, 8
-; CHECK-NEXT: i32.add $push3=, $0, $pop0
-; CHECK-NEXT: i64.load $push4=, 0($pop3):p2align=0
-; CHECK-NEXT: i32.const $push11=, 8
-; CHECK-NEXT: i32.add $push1=, $1, $pop11
-; CHECK-NEXT: i64.load $push2=, 0($pop1):p2align=0
-; CHECK-NEXT: i64.xor $push5=, $pop4, $pop2
-; CHECK-NEXT: i64.or $push9=, $pop8, $pop5
-; CHECK-NEXT: i64.eqz $push10=, $pop9
-; CHECK-NEXT: return $pop10
+; 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: i32.eqz $push4=, $pop3
+; CHECK-NEXT: return $pop4
%cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16)
%res = icmp eq i32 %cmp_16, 0
ret i1 %res
diff --git a/llvm/test/CodeGen/WebAssembly/simd-setcc.ll b/llvm/test/CodeGen/WebAssembly/simd-setcc.ll
new file mode 100644
index 0000000000000..9efa63ab9bbbd
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/simd-setcc.ll
@@ -0,0 +1,89 @@
+; 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 @setcc_load(ptr %a, ptr %b) {
+; CHECK-LABEL: setcc_load:
+; CHECK: .functype setcc_load (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: i32.eqz $push4=, $pop3
+; CHECK-NEXT: return $pop4
+ %cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16)
+ %res = icmp eq i32 %cmp_16, 0
+ ret i1 %res
+}
+
+; INFO: Negative test: noimplicitfloat disables simd
+define i1 @setcc_load_should_not_vectorize(ptr %a, ptr %b) noimplicitfloat {
+; CHECK-LABEL: setcc_load_should_not_vectorize:
+; CHECK: .functype setcc_load_should_not_vectorize (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i64.load $push4=, 0($0):p2align=0
+; CHECK-NEXT: i64.load $push3=, 0($1):p2align=0
+; CHECK-NEXT: i64.xor $push5=, $pop4, $pop3
+; CHECK-NEXT: i64.load $push1=, 8($0):p2align=0
+; CHECK-NEXT: i64.load $push0=, 8($1):p2align=0
+; CHECK-NEXT: i64.xor $push2=, $pop1, $pop0
+; CHECK-NEXT: i64.or $push6=, $pop5, $pop2
+; CHECK-NEXT: i64.eqz $push7=, $pop6
+; CHECK-NEXT: return $pop7
+ %cmp_16 = call i32 @memcmp(ptr %a, ptr %b, i32 16)
+ %res = icmp eq i32 %cmp_16, 0
+ ret i1 %res
+}
+
+define i1 @setcc_eq_const_i128(ptr %ptr) {
+; CHECK-LABEL: setcc_eq_const_i128:
+; CHECK: .functype setcc_eq_const_i128 (i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: v128.load $push0=, 0($0)
+; CHECK-NEXT: v128.const $push1=, 6, 0
+; CHECK-NEXT: i8x16.eq $push2=, $pop0, $pop1
+; CHECK-NEXT: i8x16.all_true $push3=, $pop2
+; CHECK-NEXT: i32.eqz $push4=, $pop3
+; CHECK-NEXT: return $pop4
+ %l = load i128, ptr %ptr
+ %res = icmp eq i128 %l, 6
+ ret i1 %res
+}
+
+define i1 @setcc_ne_const_i128(ptr %ptr) {
+; CHECK-LABEL: setcc_ne_const_i128:
+; CHECK: .functype setcc_ne_const_i128 (i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: v128.load $push0=, 0($0)
+; CHECK-NEXT: v128.const $push1=, 16, 0
+; CHECK-NEXT: i8x16.ne $push2=, $pop0, $pop1
+; CHECK-NEXT: v128.any_true $push3=, $pop2
+; CHECK-NEXT: return $pop3
+ %l = load i128, ptr %ptr
+ %res = icmp ne i128 %l, 16
+ ret i1 %res
+}
+
+; INFO: Negative test: only eq and ne works
+define i1 @setcc_slt_const_i128(ptr %ptr) {
+; CHECK-LABEL: setcc_slt_const_i128:
+; CHECK: .functype setcc_slt_const_i128 (i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i64.load $push2=, 0($0)
+; CHECK-NEXT: i64.const $push3=, 25
+; CHECK-NEXT: i64.lt_u $push4=, $pop2, $pop3
+; CHECK-NEXT: i64.load $push8=, 8($0)
+; CHECK-NEXT: local.tee $push7=, $1=, $pop8
+; CHECK-NEXT: i64.const $push0=, 0
+; CHECK-NEXT: i64.lt_s $push1=, $pop7, $pop0
+; CHECK-NEXT: i64.eqz $push5=, $1
+; CHECK-NEXT: i32.select $push6=, $pop4, $pop1, $pop5
+; CHECK-NEXT: return $pop6
+ %l = load i128, ptr %ptr
+ %res = icmp slt i128 %l, 25
+ ret i1 %res
+}
>From 3892b0c85cf8f4022cab5b58a494a8ec222baf9c Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Thu, 14 Aug 2025 15:04:24 -0700
Subject: [PATCH 2/2] Reapply #149461
---
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | 2 +-
llvm/test/CodeGen/WebAssembly/memcmp-expand.ll | 3 +--
llvm/test/CodeGen/WebAssembly/simd-setcc.ll | 6 ++----
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 144872e4366e0..92b8e47e273c7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -3429,7 +3429,7 @@ combineVectorSizedSetCCEquality(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
DL, MVT::i32),
Cmp});
- return DAG.getSetCC(DL, VT, Intr, DAG.getConstant(0, DL, MVT::i32), CC);
+ return DAG.getSetCC(DL, VT, Intr, DAG.getConstant(0, DL, MVT::i32), ISD::SETNE);
}
static SDValue performSETCCCombine(SDNode *N,
diff --git a/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll b/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
index 9c520ff9a4db7..4357dc5631eb0 100644
--- a/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
+++ b/llvm/test/CodeGen/WebAssembly/memcmp-expand.ll
@@ -135,8 +135,7 @@ define i1 @memcmp_expand_16(ptr %a, ptr %b) {
; 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: i32.eqz $push4=, $pop3
-; CHECK-NEXT: return $pop4
+; 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
diff --git a/llvm/test/CodeGen/WebAssembly/simd-setcc.ll b/llvm/test/CodeGen/WebAssembly/simd-setcc.ll
index 9efa63ab9bbbd..127fd4e963039 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-setcc.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-setcc.ll
@@ -13,8 +13,7 @@ define i1 @setcc_load(ptr %a, ptr %b) {
; 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: i32.eqz $push4=, $pop3
-; CHECK-NEXT: return $pop4
+; 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
@@ -47,8 +46,7 @@ define i1 @setcc_eq_const_i128(ptr %ptr) {
; CHECK-NEXT: v128.const $push1=, 6, 0
; CHECK-NEXT: i8x16.eq $push2=, $pop0, $pop1
; CHECK-NEXT: i8x16.all_true $push3=, $pop2
-; CHECK-NEXT: i32.eqz $push4=, $pop3
-; CHECK-NEXT: return $pop4
+; CHECK-NEXT: return $pop3
%l = load i128, ptr %ptr
%res = icmp eq i128 %l, 6
ret i1 %res
More information about the llvm-commits
mailing list