[llvm-branch-commits] [llvm] [X86] Restore CCMP formation through boolean NOT (PR #230770)

Alan Li via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Oct 10 03:19:53 PDT 2026


https://github.com/lialan updated https://github.com/llvm/llvm-project/pull/230770

>From 0a65dd1175dc9ff08f7e424c54f3e26d96a8f43d Mon Sep 17 00:00:00 2001
From: Alan Li <me at alanli.org>
Date: Fri, 9 Oct 2026 17:06:12 -0700
Subject: [PATCH 1/2] fix(X86): restore CCMP through boolean NOT

Demanded-bits simplification can turn XOR with 1 into NOT, hiding
SETCC operands from CCMP formation. Invert the condition under AND
when the other SETCC masks high bits and the NOT has one use.

Restore the original ccmp.ll checks for all four configurations.

Refs #230700
---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 13 +++++++++++++
 llvm/test/CodeGen/X86/apx/ccmp.ll       | 22 ++++++----------------
 2 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a265c163cf276..0cfa3ebcf911e 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53422,6 +53422,19 @@ static SDValue combineAnd(SDNode *N, SelectionDAG &DAG,
     }
   }
 
+  // SETCC only produces 0 or 1, so AND only observes the low bit of the NOT.
+  // Fold the inversion even if demanded bits changed XOR with 1 into NOT.
+  // Require one use of the NOT to avoid duplicating the inverted condition.
+  SDValue SetCC, OtherSetCC;
+  if (sd_match(N, m_And(m_OneUse(m_Not(
+                            m_Value(SetCC, m_SpecificOpc<X86ISD::SETCC>()))),
+                        m_Value(OtherSetCC, m_SpecificOpc<X86ISD::SETCC>())))) {
+    auto CC = static_cast<X86::CondCode>(SetCC.getConstantOperandVal(0));
+    SDValue Inverted = getSETCC(X86::GetOppositeBranchCondition(CC),
+                                SetCC.getOperand(1), dl, DAG);
+    return DAG.getNode(ISD::AND, dl, VT, OtherSetCC, Inverted);
+  }
+
   if (SDValue SetCC = combineAndOrForCcmpCtest(N, DAG, DCI, Subtarget))
     return SetCC;
 
diff --git a/llvm/test/CodeGen/X86/apx/ccmp.ll b/llvm/test/CodeGen/X86/apx/ccmp.ll
index 39c8b532d085a..8629b179a1797 100644
--- a/llvm/test/CodeGen/X86/apx/ccmp.ll
+++ b/llvm/test/CodeGen/X86/apx/ccmp.ll
@@ -435,12 +435,8 @@ define void @ccmp64rr_of(i64 %a, i64 %b, i64 %c) {
 ; CHECK-LABEL: ccmp64rr_of:
 ; CHECK:       # %bb.0: # %bb
 ; CHECK-NEXT:    cmpq %rdx, %rdi # encoding: [0x48,0x39,0xd7]
-; CHECK-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
-; CHECK-NEXT:    cmpq %rsi, %rdi # encoding: [0x48,0x39,0xf7]
-; CHECK-NEXT:    seto %cl # encoding: [0x0f,0x90,0xc1]
-; CHECK-NEXT:    notb %cl # encoding: [0xf6,0xd1]
-; CHECK-NEXT:    testb %cl, %al # encoding: [0x84,0xc8]
-; CHECK-NEXT:    jne .LBB6_1 # encoding: [0x75,A]
+; CHECK-NEXT:    ccmpbq {dfv=of} %rsi, %rdi # encoding: [0x62,0xf4,0xc4,0x02,0x39,0xf7]
+; CHECK-NEXT:    jno .LBB6_1 # encoding: [0x71,A]
 ; CHECK-NEXT:    # fixup A - offset: 1, value: .LBB6_1, kind: FK_PCRel_1
 ; CHECK-NEXT:  # %bb.2: # %if.then
 ; CHECK-NEXT:    xorl %eax, %eax # encoding: [0x31,0xc0]
@@ -453,12 +449,8 @@ define void @ccmp64rr_of(i64 %a, i64 %b, i64 %c) {
 ; NDD-LABEL: ccmp64rr_of:
 ; NDD:       # %bb.0: # %bb
 ; NDD-NEXT:    cmpq %rdx, %rdi # encoding: [0x48,0x39,0xd7]
-; NDD-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
-; NDD-NEXT:    cmpq %rsi, %rdi # encoding: [0x48,0x39,0xf7]
-; NDD-NEXT:    seto %cl # encoding: [0x0f,0x90,0xc1]
-; NDD-NEXT:    notb %cl # EVEX TO LEGACY Compression encoding: [0xf6,0xd1]
-; NDD-NEXT:    testb %cl, %al # encoding: [0x84,0xc8]
-; NDD-NEXT:    jne .LBB6_1 # encoding: [0x75,A]
+; NDD-NEXT:    ccmpbq {dfv=of} %rsi, %rdi # encoding: [0x62,0xf4,0xc4,0x02,0x39,0xf7]
+; NDD-NEXT:    jno .LBB6_1 # encoding: [0x71,A]
 ; NDD-NEXT:    # fixup A - offset: 1, value: .LBB6_1, kind: FK_PCRel_1
 ; NDD-NEXT:  # %bb.2: # %if.then
 ; NDD-NEXT:    xorl %eax, %eax # encoding: [0x31,0xc0]
@@ -473,8 +465,7 @@ define void @ccmp64rr_of(i64 %a, i64 %b, i64 %c) {
 ; PREFER_NO_LEGACY_SETCC-NEXT:    cmpq %rdx, %rdi # encoding: [0x48,0x39,0xd7]
 ; PREFER_NO_LEGACY_SETCC-NEXT:    setzub %al # encoding: [0x62,0xf4,0x7f,0x18,0x42,0xc0]
 ; PREFER_NO_LEGACY_SETCC-NEXT:    cmpq %rsi, %rdi # encoding: [0x48,0x39,0xf7]
-; PREFER_NO_LEGACY_SETCC-NEXT:    setzuo %cl # encoding: [0x62,0xf4,0x7f,0x18,0x40,0xc1]
-; PREFER_NO_LEGACY_SETCC-NEXT:    notb %cl # encoding: [0xf6,0xd1]
+; PREFER_NO_LEGACY_SETCC-NEXT:    setzuno %cl # encoding: [0x62,0xf4,0x7f,0x18,0x41,0xc1]
 ; PREFER_NO_LEGACY_SETCC-NEXT:    testb %cl, %al # encoding: [0x84,0xc8]
 ; PREFER_NO_LEGACY_SETCC-NEXT:    jne .LBB6_1 # encoding: [0x75,A]
 ; PREFER_NO_LEGACY_SETCC-NEXT:    # fixup A - offset: 1, value: .LBB6_1, kind: FK_PCRel_1
@@ -491,8 +482,7 @@ define void @ccmp64rr_of(i64 %a, i64 %b, i64 %c) {
 ; PREFER_LEGACY_SETCC-NEXT:    cmpq %rdx, %rdi # encoding: [0x48,0x39,0xd7]
 ; PREFER_LEGACY_SETCC-NEXT:    setb %al # encoding: [0x0f,0x92,0xc0]
 ; PREFER_LEGACY_SETCC-NEXT:    cmpq %rsi, %rdi # encoding: [0x48,0x39,0xf7]
-; PREFER_LEGACY_SETCC-NEXT:    seto %cl # encoding: [0x0f,0x90,0xc1]
-; PREFER_LEGACY_SETCC-NEXT:    notb %cl # encoding: [0xf6,0xd1]
+; PREFER_LEGACY_SETCC-NEXT:    setno %cl # encoding: [0x0f,0x91,0xc1]
 ; PREFER_LEGACY_SETCC-NEXT:    testb %cl, %al # encoding: [0x84,0xc8]
 ; PREFER_LEGACY_SETCC-NEXT:    jne .LBB6_1 # encoding: [0x75,A]
 ; PREFER_LEGACY_SETCC-NEXT:    # fixup A - offset: 1, value: .LBB6_1, kind: FK_PCRel_1

>From b6d8f819daf4bf4dadb1563b3a3ace415fdd4c18 Mon Sep 17 00:00:00 2001
From: Alan Li <me at alanli.org>
Date: Sat, 10 Oct 2026 03:18:47 -0700
Subject: [PATCH 2/2] fix(x86): reuse shifted masks in SSE ANDNP

Demanded-bit simplification can bypass a shared arithmetic shift when
ANDNP only needs sign bits. Reuse the existing shift to avoid keeping
its input live across a two-address SSE instruction.

Restore the original SSE2 vector select checks.

Refs #230700
---
 llvm/lib/Target/X86/X86ISelLowering.cpp   | 11 +++++++++++
 llvm/test/CodeGen/X86/vector-bo-select.ll | 23 ++++++++++-------------
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 0cfa3ebcf911e..5f06eec59c175 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57873,6 +57873,17 @@ static SDValue combineAndnp(SDNode *N, SelectionDAG &DAG,
     std::tie(Bits0, Elts0) = GetDemandedMasks(N1);
     std::tie(Bits1, Elts1) = GetDemandedMasks(N0, true);
 
+    // Reuse a live arithmetic shift when only sign bits are needed. This keeps
+    // the two-address SSE shift from requiring a copy of its input for ANDNP.
+    if (!Subtarget.hasAVX() && Bits0.isSignMask() &&
+        N0->hasNUsesOfValue(2, N0.getResNo())) {
+      for (SDNode *User : N0->users()) {
+        if (User->getOpcode() == X86ISD::VSRAI && User->hasOneUse() &&
+            User->getOperand(0) == N0)
+          return DAG.getNode(X86ISD::ANDNP, DL, VT, SDValue(User, 0), N1);
+      }
+    }
+
     if (TLI.SimplifyDemandedVectorElts(N0, Elts0, DCI) ||
         TLI.SimplifyDemandedVectorElts(N1, Elts1, DCI) ||
         TLI.SimplifyDemandedBits(N0, Bits0, Elts0, DCI) ||
diff --git a/llvm/test/CodeGen/X86/vector-bo-select.ll b/llvm/test/CodeGen/X86/vector-bo-select.ll
index cdbc80dfbe6dd..ac27c26768c92 100644
--- a/llvm/test/CodeGen/X86/vector-bo-select.ll
+++ b/llvm/test/CodeGen/X86/vector-bo-select.ll
@@ -9,11 +9,10 @@ define <4 x float> @fadd_v4f32(<4 x i1> %b, <4 x float> noundef %x, <4 x float>
 ; SSE2-LABEL: fadd_v4f32:
 ; SSE2:       # %bb.0:
 ; SSE2-NEXT:    pslld $31, %xmm0
-; SSE2-NEXT:    movdqa %xmm0, %xmm3
-; SSE2-NEXT:    psrad $31, %xmm3
-; SSE2-NEXT:    pand %xmm2, %xmm3
+; SSE2-NEXT:    psrad $31, %xmm0
+; SSE2-NEXT:    pand %xmm0, %xmm2
 ; SSE2-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT:    por %xmm3, %xmm0
+; SSE2-NEXT:    por %xmm2, %xmm0
 ; SSE2-NEXT:    addps %xmm1, %xmm0
 ; SSE2-NEXT:    retq
 ;
@@ -63,19 +62,17 @@ define <8 x float> @fadd_v8f32_commute(<8 x i1> %b, <8 x float> noundef %x, <8 x
 ; SSE2-NEXT:    movdqa %xmm0, %xmm5
 ; SSE2-NEXT:    punpckhwd {{.*#+}} xmm5 = xmm5[4,4,5,5,6,6,7,7]
 ; SSE2-NEXT:    pslld $31, %xmm5
-; SSE2-NEXT:    movdqa {{.*#+}} xmm6 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
-; SSE2-NEXT:    movdqa %xmm5, %xmm7
-; SSE2-NEXT:    pandn %xmm6, %xmm7
 ; SSE2-NEXT:    psrad $31, %xmm5
-; SSE2-NEXT:    pand %xmm4, %xmm5
-; SSE2-NEXT:    por %xmm7, %xmm5
+; SSE2-NEXT:    movdqa {{.*#+}} xmm6 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
+; SSE2-NEXT:    pand %xmm5, %xmm4
+; SSE2-NEXT:    pandn %xmm6, %xmm5
+; SSE2-NEXT:    por %xmm4, %xmm5
 ; SSE2-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3]
 ; SSE2-NEXT:    pslld $31, %xmm0
-; SSE2-NEXT:    movdqa %xmm0, %xmm4
-; SSE2-NEXT:    pandn %xmm6, %xmm4
 ; SSE2-NEXT:    psrad $31, %xmm0
-; SSE2-NEXT:    pand %xmm3, %xmm0
-; SSE2-NEXT:    por %xmm4, %xmm0
+; SSE2-NEXT:    pand %xmm0, %xmm3
+; SSE2-NEXT:    pandn %xmm6, %xmm0
+; SSE2-NEXT:    por %xmm3, %xmm0
 ; SSE2-NEXT:    addps %xmm1, %xmm0
 ; SSE2-NEXT:    addps %xmm2, %xmm5
 ; SSE2-NEXT:    movaps %xmm5, %xmm1



More information about the llvm-branch-commits mailing list