[llvm] [X86] Fix a>b being different than b<a on -mattr=+avx2 (PR #195712)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 13:47:21 PDT 2026


https://github.com/thatSteveFan updated https://github.com/llvm/llvm-project/pull/195712

>From 3b850d6dd7dcfd2e163680d317af15bdad517d42 Mon Sep 17 00:00:00 2001
From: thatSteveFan <pnaduthota at google.com>
Date: Sat, 2 May 2026 03:34:54 +0000
Subject: [PATCH 1/2] Fix a>b being different than b<a on -mattr=+avx2

---
 llvm/lib/Target/X86/X86ISelLowering.cpp              |  7 +++++++
 .../CodeGen/X86/vector-unsigned-cmp-fold-load.ll     | 12 ++++++++++++
 2 files changed, 19 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/vector-unsigned-cmp-fold-load.ll

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 5a1171b2b4ee6..7fa41bf1d1ccd 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -25060,6 +25060,13 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget,
   if (ISD::isUnsignedIntSetCC(Cond) &&
       (FlipSigns || ISD::isTrueWhenEqual(Cond)) &&
       TLI.isOperationLegal(ISD::UMIN, VT)) {
+    // If Op0 is a load and Op1 is not, swap them to allow folding the load
+    // into the min/max operation.
+    if (Op0.getOpcode() == ISD::LOAD && Op1.getOpcode() != ISD::LOAD) {
+      std::swap(Op0, Op1);
+      Cond = ISD::getSetCCSwappedOperands(Cond);
+    }
+
     // If we have a constant operand, increment/decrement it and change the
     // condition to avoid an invert.
     if (Cond == ISD::SETUGT) {
diff --git a/llvm/test/CodeGen/X86/vector-unsigned-cmp-fold-load.ll b/llvm/test/CodeGen/X86/vector-unsigned-cmp-fold-load.ll
new file mode 100644
index 0000000000000..a28b0eee83832
--- /dev/null
+++ b/llvm/test/CodeGen/X86/vector-unsigned-cmp-fold-load.ll
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s
+
+define <8 x i32> @count_lt1_ir(<8 x i32> %y, <8 x i32>* %p) {
+; CHECK-LABEL: count_lt1_ir:
+; CHECK:       # %bb.0:
+; CHECK:         vpminud (%{{[a-z0-9]+}}), %ymm{{[0-9]+}}, %ymm{{[0-9]+}}
+; CHECK:         retq
+  %x = load <8 x i32>, <8 x i32>* %p
+  %cmp = icmp ult <8 x i32> %x, %y
+  %sext = sext <8 x i1> %cmp to <8 x i32>
+  ret <8 x i32> %sext
+}

>From 2938ce76d3d8653856fad876f8e12f79c951e4bb Mon Sep 17 00:00:00 2001
From: thatSteveFan <pnaduthota at google.com>
Date: Mon, 4 May 2026 20:41:16 +0000
Subject: [PATCH 2/2] Change to mayFoldLoad and add testcase for multi-load

---
 llvm/lib/Target/X86/X86ISelLowering.cpp     |  2 +-
 llvm/test/CodeGen/X86/avx2-icmp-multiuse.ll | 67 +++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/X86/avx2-icmp-multiuse.ll

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 7fa41bf1d1ccd..be8fe52482b55 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -25062,7 +25062,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget,
       TLI.isOperationLegal(ISD::UMIN, VT)) {
     // If Op0 is a load and Op1 is not, swap them to allow folding the load
     // into the min/max operation.
-    if (Op0.getOpcode() == ISD::LOAD && Op1.getOpcode() != ISD::LOAD) {
+    if (X86::mayFoldLoad(Op0, Subtarget) && !X86::mayFoldLoad(Op1, Subtarget)) {
       std::swap(Op0, Op1);
       Cond = ISD::getSetCCSwappedOperands(Cond);
     }
diff --git a/llvm/test/CodeGen/X86/avx2-icmp-multiuse.ll b/llvm/test/CodeGen/X86/avx2-icmp-multiuse.ll
new file mode 100644
index 0000000000000..0500e04917987
--- /dev/null
+++ b/llvm/test/CodeGen/X86/avx2-icmp-multiuse.ll
@@ -0,0 +1,67 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,X64
+
+define <8 x i32> @test_lt_multiuse_op0(ptr %ptr1, ptr %ptr2, ptr %external) nounwind {
+; X86-LABEL: test_lt_multiuse_op0:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    vmovdqa (%edx), %ymm0
+; X86-NEXT:    vpmaxud (%ecx), %ymm0, %ymm1
+; X86-NEXT:    vmovdqa %ymm0, (%eax)
+; X86-NEXT:    vpcmpeqd %ymm1, %ymm0, %ymm0
+; X86-NEXT:    vpbroadcastd {{.*#+}} ymm1 = [1,1,1,1,1,1,1,1]
+; X86-NEXT:    vpandn %ymm1, %ymm0, %ymm0
+; X86-NEXT:    retl
+;
+; X64-LABEL: test_lt_multiuse_op0:
+; X64:       # %bb.0:
+; X64-NEXT:    vmovdqa (%rdi), %ymm0
+; X64-NEXT:    vpmaxud (%rsi), %ymm0, %ymm1
+; X64-NEXT:    vmovdqa %ymm0, (%rdx)
+; X64-NEXT:    vpcmpeqd %ymm1, %ymm0, %ymm0
+; X64-NEXT:    vpbroadcastd {{.*#+}} ymm1 = [1,1,1,1,1,1,1,1]
+; X64-NEXT:    vpandn %ymm1, %ymm0, %ymm0
+; X64-NEXT:    retq
+  %a = load <8 x i32>, ptr %ptr1, align 32
+  %b = load <8 x i32>, ptr %ptr2, align 32
+  %cmp = icmp ult <8 x i32> %a, %b
+  store <8 x i32> %a, ptr %external, align 32
+  %res = zext <8 x i1> %cmp to <8 x i32>
+  ret <8 x i32> %res
+}
+
+define <8 x i32> @test_lt_multiuse_op1(ptr %ptr1, ptr %ptr2, ptr %external) nounwind {
+; X86-LABEL: test_lt_multiuse_op1:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT:    vmovdqa (%edx), %ymm0
+; X86-NEXT:    vpminud (%ecx), %ymm0, %ymm1
+; X86-NEXT:    vmovdqa %ymm0, (%eax)
+; X86-NEXT:    vpcmpeqd %ymm1, %ymm0, %ymm0
+; X86-NEXT:    vpbroadcastd {{.*#+}} ymm1 = [1,1,1,1,1,1,1,1]
+; X86-NEXT:    vpandn %ymm1, %ymm0, %ymm0
+; X86-NEXT:    retl
+;
+; X64-LABEL: test_lt_multiuse_op1:
+; X64:       # %bb.0:
+; X64-NEXT:    vmovdqa (%rsi), %ymm0
+; X64-NEXT:    vpminud (%rdi), %ymm0, %ymm1
+; X64-NEXT:    vmovdqa %ymm0, (%rdx)
+; X64-NEXT:    vpcmpeqd %ymm1, %ymm0, %ymm0
+; X64-NEXT:    vpbroadcastd {{.*#+}} ymm1 = [1,1,1,1,1,1,1,1]
+; X64-NEXT:    vpandn %ymm1, %ymm0, %ymm0
+; X64-NEXT:    retq
+  %a = load <8 x i32>, ptr %ptr1, align 32
+  %b = load <8 x i32>, ptr %ptr2, align 32
+  %cmp = icmp ult <8 x i32> %a, %b
+  store <8 x i32> %b, ptr %external, align 32
+  %res = zext <8 x i1> %cmp to <8 x i32>
+  ret <8 x i32> %res
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}



More information about the llvm-commits mailing list