[llvm-branch-commits] [llvm] [SelectionDAG][X86] Preserve sharing and recover CCMP folding (PR #230770)

Alan Li via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Oct 13 08:47:57 PDT 2026


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

>From 6879337c67f78f6c992223f045b238bd56cd487d 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/5] 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 a265c163cf276d..0cfa3ebcf911ed 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 39c8b532d085ac..8629b179a17970 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 cc04a03b29ed8878025258880d6c303caaf55129 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/5] 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 0cfa3ebcf911ed..5f06eec59c1757 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 cdbc80dfbe6dda..ac27c26768c920 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

>From 8e1cfe0930d139aefdf1ba17477487fc0018691a Mon Sep 17 00:00:00 2001
From: Alan Li <me at alanli.org>
Date: Mon, 12 Oct 2026 06:04:54 -0700
Subject: [PATCH 3/5] revert(x86): drop shared-shift ANDNP workaround

Keep the CCMP fix separate from the SSE copy regression. The shared-shift
workaround relies on GetDemandedMasks, whose poison handling is under
review, and needs a different approach.

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

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 5f06eec59c1757..0cfa3ebcf911ed 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57873,17 +57873,6 @@ 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 ac27c26768c920..cdbc80dfbe6dda 100644
--- a/llvm/test/CodeGen/X86/vector-bo-select.ll
+++ b/llvm/test/CodeGen/X86/vector-bo-select.ll
@@ -9,10 +9,11 @@ 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:    psrad $31, %xmm0
-; SSE2-NEXT:    pand %xmm0, %xmm2
+; SSE2-NEXT:    movdqa %xmm0, %xmm3
+; SSE2-NEXT:    psrad $31, %xmm3
+; SSE2-NEXT:    pand %xmm2, %xmm3
 ; SSE2-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE2-NEXT:    por %xmm2, %xmm0
+; SSE2-NEXT:    por %xmm3, %xmm0
 ; SSE2-NEXT:    addps %xmm1, %xmm0
 ; SSE2-NEXT:    retq
 ;
@@ -62,17 +63,19 @@ 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:    psrad $31, %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:    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:    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 %xmm0, %xmm3
-; SSE2-NEXT:    pandn %xmm6, %xmm0
-; SSE2-NEXT:    por %xmm3, %xmm0
+; SSE2-NEXT:    pand %xmm3, %xmm0
+; SSE2-NEXT:    por %xmm4, %xmm0
 ; SSE2-NEXT:    addps %xmm1, %xmm0
 ; SSE2-NEXT:    addps %xmm2, %xmm5
 ; SSE2-NEXT:    movaps %xmm5, %xmm1

>From b2d5806f72b6b751e34abaa7c1eab6234ad3ccfd Mon Sep 17 00:00:00 2001
From: Alan Li <me at alanli.org>
Date: Mon, 12 Oct 2026 06:08:48 -0700
Subject: [PATCH 4/5] fix(x86): generalize boolean NOT folding

Use known bits to prove the other AND operand clears every bit above
bit zero. This permits non-SETCC booleans without changing the upper
bits of an arbitrary byte or duplicating a shared inversion.

Cover a shifted boolean, arbitrary bytes, and shared inversions.
---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 11 +--
 llvm/test/CodeGen/X86/setcc-logic.ll    | 92 +++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 0cfa3ebcf911ed..2ce44390c5e1bd 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53422,17 +53422,18 @@ 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.
+  // Fold NOT(SETCC) into the opposite condition when AND only observes bit 0.
+  // The other operand must clear the upper bits set by NOT but not by SETCC.
   // Require one use of the NOT to avoid duplicating the inverted condition.
-  SDValue SetCC, OtherSetCC;
+  SDValue SetCC, Other;
   if (sd_match(N, m_And(m_OneUse(m_Not(
                             m_Value(SetCC, m_SpecificOpc<X86ISD::SETCC>()))),
-                        m_Value(OtherSetCC, m_SpecificOpc<X86ISD::SETCC>())))) {
+                        m_Value(Other))) &&
+      DAG.MaskedValueIsZero(Other, ~APInt(VT.getScalarSizeInBits(), 1))) {
     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);
+    return DAG.getNode(ISD::AND, dl, VT, Other, Inverted);
   }
 
   if (SDValue SetCC = combineAndOrForCcmpCtest(N, DAG, DCI, Subtarget))
diff --git a/llvm/test/CodeGen/X86/setcc-logic.ll b/llvm/test/CodeGen/X86/setcc-logic.ll
index 4ca4c12b93120c..e49885b9c99ebc 100644
--- a/llvm/test/CodeGen/X86/setcc-logic.ll
+++ b/llvm/test/CodeGen/X86/setcc-logic.ll
@@ -868,3 +868,95 @@ define i1 @mixed_cc(i8 %x) {
   %res = and i1 %c1, %c2
   ret i1 %res
 }
+
+declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64)
+
+; A non-SETCC operand with only bit zero set also permits condition inversion.
+define i8 @and_not_known_boolean(i64 %a, i64 %b, i8 %c) {
+; NOBMI-LABEL: and_not_known_boolean:
+; NOBMI:       # %bb.0:
+; NOBMI-NEXT:    shrb $7, %dl
+; NOBMI-NEXT:    cmpq %rsi, %rdi
+; NOBMI-NEXT:    setno %al
+; NOBMI-NEXT:    andb %dl, %al
+; NOBMI-NEXT:    retq
+;
+; BMI-LABEL: and_not_known_boolean:
+; BMI:       # %bb.0:
+; BMI-NEXT:    xorl %eax, %eax
+; BMI-NEXT:    cmpq %rsi, %rdi
+; BMI-NEXT:    seto %al
+; BMI-NEXT:    shrb $7, %dl
+; BMI-NEXT:    movzbl %dl, %ecx
+; BMI-NEXT:    andnl %ecx, %eax, %eax
+; BMI-NEXT:    # kill: def $al killed $al killed $eax
+; BMI-NEXT:    retq
+  %sub = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+  %ov = extractvalue {i64, i1} %sub, 1
+  %ov8 = zext i1 %ov to i8
+  %not = xor i8 %ov8, -1
+  %bit = lshr i8 %c, 7
+  %r = and i8 %not, %bit
+  ret i8 %r
+}
+
+; Preserve the upper bits of NOT when the other operand can observe them.
+define i8 @and_not_arbitrary_byte(i64 %a, i64 %b, i8 %c) {
+; NOBMI-LABEL: and_not_arbitrary_byte:
+; NOBMI:       # %bb.0:
+; NOBMI-NEXT:    cmpq %rsi, %rdi
+; NOBMI-NEXT:    seto %al
+; NOBMI-NEXT:    notb %al
+; NOBMI-NEXT:    andb %dl, %al
+; NOBMI-NEXT:    retq
+;
+; BMI-LABEL: and_not_arbitrary_byte:
+; BMI:       # %bb.0:
+; BMI-NEXT:    xorl %eax, %eax
+; BMI-NEXT:    cmpq %rsi, %rdi
+; BMI-NEXT:    seto %al
+; BMI-NEXT:    andnl %edx, %eax, %eax
+; BMI-NEXT:    # kill: def $al killed $al killed $eax
+; BMI-NEXT:    retq
+  %sub = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+  %ov = extractvalue {i64, i1} %sub, 1
+  %ov8 = zext i1 %ov to i8
+  %not = xor i8 %ov8, -1
+  %r = and i8 %c, %not
+  ret i8 %r
+}
+
+; Do not duplicate an inversion that must still produce all eight bits.
+define i8 @and_not_shared_inversion(i64 %a, i64 %b, i8 %c, ptr %p) {
+; NOBMI-LABEL: and_not_shared_inversion:
+; NOBMI:       # %bb.0:
+; NOBMI-NEXT:    cmpq %rsi, %rdi
+; NOBMI-NEXT:    seto %al
+; NOBMI-NEXT:    notb %al
+; NOBMI-NEXT:    movb %al, (%rcx)
+; NOBMI-NEXT:    shrb $7, %dl
+; NOBMI-NEXT:    andb %dl, %al
+; NOBMI-NEXT:    retq
+;
+; BMI-LABEL: and_not_shared_inversion:
+; BMI:       # %bb.0:
+; BMI-NEXT:    xorl %r8d, %r8d
+; BMI-NEXT:    cmpq %rsi, %rdi
+; BMI-NEXT:    seto %r8b
+; BMI-NEXT:    shrb $7, %dl
+; BMI-NEXT:    movzbl %dl, %eax
+; BMI-NEXT:    andnl %eax, %r8d, %eax
+; BMI-NEXT:    movl %r8d, %edx
+; BMI-NEXT:    notb %dl
+; BMI-NEXT:    movb %dl, (%rcx)
+; BMI-NEXT:    # kill: def $al killed $al killed $eax
+; BMI-NEXT:    retq
+  %sub = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+  %ov = extractvalue {i64, i1} %sub, 1
+  %ov8 = zext i1 %ov to i8
+  %not = xor i8 %ov8, -1
+  store i8 %not, ptr %p
+  %bit = lshr i8 %c, 7
+  %r = and i8 %not, %bit
+  ret i8 %r
+}

>From c39ae7facc16f62b56ffd4a9120f07216a7fdb1b Mon Sep 17 00:00:00 2001
From: Alan Li <me at alanli.org>
Date: Mon, 12 Oct 2026 07:11:28 -0700
Subject: [PATCH 5/5] fix(SelectionDAG): Preserve operand sharing

Demanded-bits simplification can bypass a shared producer without
removing it or its bitwise user. Reusing its previously single-use input
extends its live range and can introduce two-address copies.

Keep the shared value in this case for AND, OR, and XOR. Still bypass
bitwise producers to enable reassociation. Folds that remove the user
and rewrites using already-shared inputs remain available.

Remove three redundant copies in vector-bo-select without target or
subtarget checks.

The RISC-V checks each lose one instruction. GFX9 v_sdiv_i24 moves five
vector operations to scalar operations and adds a final move, growing
by four bytes; the other AMDGPU changes only affect register allocation.
---
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  33 ++++--
 llvm/test/CodeGen/AMDGPU/sdiv.ll              |  79 ++++++-------
 .../CodeGen/RISCV/srem-seteq-illegal-types.ll | 108 +++++++++---------
 llvm/test/CodeGen/X86/vector-bo-select.ll     |  23 ++--
 4 files changed, 124 insertions(+), 119 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 8628faad486aac..763103993290d9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1403,6 +1403,21 @@ bool TargetLowering::SimplifyDemandedBits(
                                 TLO, Depth + 1);
   };
 
+  // Bypassing a shared operand does not remove it. Avoid giving its single-use
+  // input another use when the bitwise operation also remains: this extends the
+  // input's live range and can require an extra copy for a two-address
+  // operation. Still bypass bitwise operands, which can enable reassociation
+  // and folding.
+  auto SimplifyBitwiseOperand = [&](SDValue V) {
+    SDValue NewV = SimplifyMultipleUseDemandedBits(
+        V, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
+    if (NewV && !V.hasOneUse() && NewV.hasOneUse() &&
+        !ISD::isBitwiseLogicOp(V.getOpcode()) &&
+        llvm::is_contained(V->op_values(), NewV))
+      return SDValue();
+    return NewV;
+  };
+
   KnownBits Known2;
   switch (Op.getOpcode()) {
   case ISD::SCALAR_TO_VECTOR: {
@@ -1729,10 +1744,8 @@ bool TargetLowering::SimplifyDemandedBits(
 
     // Attempt to avoid multi-use ops if we don't need anything from them.
     if (!DemandedBits.isAllOnes() || !DemandedElts.isAllOnes()) {
-      SDValue DemandedOp0 = SimplifyMultipleUseDemandedBits(
-          Op0, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
-      SDValue DemandedOp1 = SimplifyMultipleUseDemandedBits(
-          Op1, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
+      SDValue DemandedOp0 = SimplifyBitwiseOperand(Op0);
+      SDValue DemandedOp1 = SimplifyBitwiseOperand(Op1);
       if (DemandedOp0 || DemandedOp1) {
         Op0 = DemandedOp0 ? DemandedOp0 : Op0;
         Op1 = DemandedOp1 ? DemandedOp1 : Op1;
@@ -1781,10 +1794,8 @@ bool TargetLowering::SimplifyDemandedBits(
 
     // Attempt to avoid multi-use ops if we don't need anything from them.
     if (!DemandedBits.isAllOnes() || !DemandedElts.isAllOnes()) {
-      SDValue DemandedOp0 = SimplifyMultipleUseDemandedBits(
-          Op0, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
-      SDValue DemandedOp1 = SimplifyMultipleUseDemandedBits(
-          Op1, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
+      SDValue DemandedOp0 = SimplifyBitwiseOperand(Op0);
+      SDValue DemandedOp1 = SimplifyBitwiseOperand(Op1);
       if (DemandedOp0 || DemandedOp1) {
         Op0 = DemandedOp0 ? DemandedOp0 : Op0;
         Op1 = DemandedOp1 ? DemandedOp1 : Op1;
@@ -1898,10 +1909,8 @@ bool TargetLowering::SimplifyDemandedBits(
 
     // Attempt to avoid multi-use ops if we don't need anything from them.
     if (!DemandedBits.isAllOnes() || !DemandedElts.isAllOnes()) {
-      SDValue DemandedOp0 = SimplifyMultipleUseDemandedBits(
-          Op0, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
-      SDValue DemandedOp1 = SimplifyMultipleUseDemandedBits(
-          Op1, DemandedBits, DemandedElts, TLO.DAG, Depth + 1);
+      SDValue DemandedOp0 = SimplifyBitwiseOperand(Op0);
+      SDValue DemandedOp1 = SimplifyBitwiseOperand(Op1);
       if (DemandedOp0 || DemandedOp1) {
         Op0 = DemandedOp0 ? DemandedOp0 : Op0;
         Op1 = DemandedOp1 ? DemandedOp1 : Op1;
diff --git a/llvm/test/CodeGen/AMDGPU/sdiv.ll b/llvm/test/CodeGen/AMDGPU/sdiv.ll
index 01224a1c1ebfe8..7840ed717eb6e4 100644
--- a/llvm/test/CodeGen/AMDGPU/sdiv.ll
+++ b/llvm/test/CodeGen/AMDGPU/sdiv.ll
@@ -1807,18 +1807,18 @@ define amdgpu_kernel void @v_sdiv_i24(ptr addrspace(1) %out, ptr addrspace(1) %i
 ; GCN-NEXT:    s_mov_b32 s0, s4
 ; GCN-NEXT:    s_mov_b32 s1, s5
 ; GCN-NEXT:    s_waitcnt vmcnt(3)
-; GCN-NEXT:    v_lshlrev_b32_e32 v4, 16, v0
+; GCN-NEXT:    v_lshlrev_b32_e32 v0, 16, v0
 ; GCN-NEXT:    s_waitcnt vmcnt(2)
-; GCN-NEXT:    v_or_b32_e32 v1, v1, v4
+; GCN-NEXT:    v_or_b32_e32 v1, v1, v0
 ; GCN-NEXT:    v_sub_i32_e32 v4, vcc, 0, v1
 ; GCN-NEXT:    v_max_i32_e32 v1, v1, v4
 ; GCN-NEXT:    v_cvt_f32_u32_e32 v4, v1
 ; GCN-NEXT:    v_sub_i32_e32 v5, vcc, 0, v1
 ; GCN-NEXT:    s_waitcnt vmcnt(1)
-; GCN-NEXT:    v_lshlrev_b32_e32 v6, 16, v2
+; GCN-NEXT:    v_lshlrev_b32_e32 v2, 16, v2
 ; GCN-NEXT:    v_rcp_f32_e32 v4, v4
 ; GCN-NEXT:    s_waitcnt vmcnt(0)
-; GCN-NEXT:    v_or_b32_e32 v3, v3, v6
+; GCN-NEXT:    v_or_b32_e32 v3, v3, v2
 ; GCN-NEXT:    v_sub_i32_e32 v6, vcc, 0, v3
 ; GCN-NEXT:    v_mul_f32_e32 v4, 0x4f7ffffe, v4
 ; GCN-NEXT:    v_cvt_u32_f32_e32 v4, v4
@@ -1862,18 +1862,18 @@ define amdgpu_kernel void @v_sdiv_i24(ptr addrspace(1) %out, ptr addrspace(1) %i
 ; TONGA-NEXT:    s_mov_b32 s0, s4
 ; TONGA-NEXT:    s_mov_b32 s1, s5
 ; TONGA-NEXT:    s_waitcnt vmcnt(3)
-; TONGA-NEXT:    v_lshlrev_b32_e32 v4, 16, v0
+; TONGA-NEXT:    v_lshlrev_b32_e32 v0, 16, v0
 ; TONGA-NEXT:    s_waitcnt vmcnt(2)
-; TONGA-NEXT:    v_or_b32_e32 v1, v1, v4
+; TONGA-NEXT:    v_or_b32_e32 v1, v1, v0
 ; TONGA-NEXT:    v_sub_u32_e32 v4, vcc, 0, v1
 ; TONGA-NEXT:    v_max_i32_e32 v1, v1, v4
 ; TONGA-NEXT:    v_cvt_f32_u32_e32 v4, v1
 ; TONGA-NEXT:    v_sub_u32_e32 v5, vcc, 0, v1
 ; TONGA-NEXT:    s_waitcnt vmcnt(1)
-; TONGA-NEXT:    v_lshlrev_b32_e32 v6, 16, v2
+; TONGA-NEXT:    v_lshlrev_b32_e32 v2, 16, v2
 ; TONGA-NEXT:    v_rcp_f32_e32 v4, v4
 ; TONGA-NEXT:    s_waitcnt vmcnt(0)
-; TONGA-NEXT:    v_or_b32_e32 v3, v3, v6
+; TONGA-NEXT:    v_or_b32_e32 v3, v3, v2
 ; TONGA-NEXT:    v_sub_u32_e32 v6, vcc, 0, v3
 ; TONGA-NEXT:    v_mul_f32_e32 v4, 0x4f7ffffe, v4
 ; TONGA-NEXT:    v_cvt_u32_f32_e32 v4, v4
@@ -1919,42 +1919,43 @@ define amdgpu_kernel void @v_sdiv_i24(ptr addrspace(1) %out, ptr addrspace(1) %i
 ; GFX9-NEXT:    v_readfirstlane_b32 s1, v0
 ; GFX9-NEXT:    s_waitcnt vmcnt(2)
 ; GFX9-NEXT:    v_readfirstlane_b32 s4, v1
-; GFX9-NEXT:    s_lshl_b32 s1, s1, 16
-; GFX9-NEXT:    s_or_b32 s1, s4, s1
+; GFX9-NEXT:    s_lshl_b32 s5, s1, 16
+; GFX9-NEXT:    s_or_b32 s1, s4, s5
 ; GFX9-NEXT:    s_abs_i32 s4, s1
-; GFX9-NEXT:    v_cvt_f32_u32_e32 v1, s4
+; GFX9-NEXT:    v_cvt_f32_u32_e32 v0, s4
 ; GFX9-NEXT:    s_waitcnt vmcnt(1)
-; GFX9-NEXT:    v_readfirstlane_b32 s5, v2
+; GFX9-NEXT:    v_readfirstlane_b32 s6, v2
 ; GFX9-NEXT:    s_waitcnt vmcnt(0)
-; GFX9-NEXT:    v_readfirstlane_b32 s6, v3
-; GFX9-NEXT:    s_lshl_b32 s5, s5, 16
-; GFX9-NEXT:    v_rcp_f32_e32 v1, v1
-; GFX9-NEXT:    s_or_b32 s5, s6, s5
-; GFX9-NEXT:    s_sub_i32 s6, 0, s4
-; GFX9-NEXT:    s_abs_i32 s5, s5
-; GFX9-NEXT:    v_mul_f32_e32 v1, 0x4f7ffffe, v1
-; GFX9-NEXT:    v_cvt_u32_f32_e32 v1, v1
-; GFX9-NEXT:    v_xor_b32_e32 v0, v2, v0
-; GFX9-NEXT:    v_ashrrev_i32_e32 v0, 31, v0
+; GFX9-NEXT:    v_readfirstlane_b32 s7, v3
+; GFX9-NEXT:    s_lshl_b32 s6, s6, 16
+; GFX9-NEXT:    v_rcp_f32_e32 v0, v0
+; GFX9-NEXT:    s_or_b32 s7, s7, s6
+; GFX9-NEXT:    s_xor_b32 s5, s6, s5
+; GFX9-NEXT:    s_abs_i32 s6, s7
+; GFX9-NEXT:    v_mul_f32_e32 v0, 0x4f7ffffe, v0
+; GFX9-NEXT:    v_cvt_u32_f32_e32 v0, v0
+; GFX9-NEXT:    s_sub_i32 s7, 0, s4
 ; GFX9-NEXT:    s_mov_b32 s1, s9
-; GFX9-NEXT:    v_readfirstlane_b32 s7, v1
-; GFX9-NEXT:    s_mul_i32 s6, s6, s7
-; GFX9-NEXT:    s_mul_hi_u32 s6, s7, s6
-; GFX9-NEXT:    s_add_i32 s7, s7, s6
-; GFX9-NEXT:    s_mul_hi_u32 s6, s5, s7
-; GFX9-NEXT:    s_mul_i32 s7, s6, s4
-; GFX9-NEXT:    s_sub_i32 s5, s5, s7
-; GFX9-NEXT:    s_add_i32 s8, s6, 1
-; GFX9-NEXT:    s_sub_i32 s7, s5, s4
-; GFX9-NEXT:    s_cmp_ge_u32 s5, s4
+; GFX9-NEXT:    s_ashr_i32 s5, s5, 31
+; GFX9-NEXT:    v_readfirstlane_b32 s8, v0
+; GFX9-NEXT:    s_mul_i32 s7, s7, s8
+; GFX9-NEXT:    s_mul_hi_u32 s7, s8, s7
+; GFX9-NEXT:    s_add_i32 s8, s8, s7
+; GFX9-NEXT:    s_mul_hi_u32 s7, s6, s8
+; GFX9-NEXT:    s_mul_i32 s8, s7, s4
+; GFX9-NEXT:    s_sub_i32 s6, s6, s8
+; GFX9-NEXT:    s_add_i32 s9, s7, 1
+; GFX9-NEXT:    s_sub_i32 s8, s6, s4
+; GFX9-NEXT:    s_cmp_ge_u32 s6, s4
+; GFX9-NEXT:    s_cselect_b32 s7, s9, s7
 ; GFX9-NEXT:    s_cselect_b32 s6, s8, s6
-; GFX9-NEXT:    s_cselect_b32 s5, s7, s5
-; GFX9-NEXT:    s_add_i32 s7, s6, 1
-; GFX9-NEXT:    s_cmp_ge_u32 s5, s4
-; GFX9-NEXT:    s_cselect_b32 s4, s7, s6
-; GFX9-NEXT:    v_xor_b32_e32 v1, s4, v0
-; GFX9-NEXT:    v_sub_u32_e32 v0, v1, v0
-; GFX9-NEXT:    v_bfe_i32 v0, v0, 0, 24
+; GFX9-NEXT:    s_add_i32 s8, s7, 1
+; GFX9-NEXT:    s_cmp_ge_u32 s6, s4
+; GFX9-NEXT:    s_cselect_b32 s4, s8, s7
+; GFX9-NEXT:    s_xor_b32 s4, s4, s5
+; GFX9-NEXT:    s_sub_i32 s4, s4, s5
+; GFX9-NEXT:    s_bfe_i32 s4, s4, 0x180000
+; GFX9-NEXT:    v_mov_b32_e32 v0, s4
 ; GFX9-NEXT:    buffer_store_dword v0, off, s[0:3], 0
 ; GFX9-NEXT:    s_endpgm
 ;
diff --git a/llvm/test/CodeGen/RISCV/srem-seteq-illegal-types.ll b/llvm/test/CodeGen/RISCV/srem-seteq-illegal-types.ll
index 87f8e2bb9be178..71196b3e059f48 100644
--- a/llvm/test/CodeGen/RISCV/srem-seteq-illegal-types.ll
+++ b/llvm/test/CodeGen/RISCV/srem-seteq-illegal-types.ll
@@ -495,25 +495,24 @@ define void @test_srem_vec(ptr %X) nounwind {
 ; RV64-NEXT:    or a1, a2, a1
 ; RV64-NEXT:    sltu a1, a5, a1
 ; RV64-NEXT:    addi a0, a0, -2
-; RV64-NEXT:    addi s1, s1, -1
 ; RV64-NEXT:    seqz a0, a0
+; RV64-NEXT:    addi s1, s1, -1
 ; RV64-NEXT:    seqz a2, s1
 ; RV64-NEXT:    neg a1, a1
 ; RV64-NEXT:    addi a2, a2, -1
 ; RV64-NEXT:    addi a0, a0, -1
-; RV64-NEXT:    slli a3, a2, 31
-; RV64-NEXT:    slli a4, a0, 2
-; RV64-NEXT:    srli a3, a3, 62
-; RV64-NEXT:    or a3, a3, a4
+; RV64-NEXT:    andi a3, a0, 7
+; RV64-NEXT:    slli a0, a0, 2
+; RV64-NEXT:    slli a4, a2, 31
 ; RV64-NEXT:    slli a1, a1, 31
 ; RV64-NEXT:    srli a1, a1, 31
 ; RV64-NEXT:    slli a2, a2, 33
-; RV64-NEXT:    slli a0, a0, 29
+; RV64-NEXT:    srli a4, a4, 62
 ; RV64-NEXT:    or a1, a1, a2
-; RV64-NEXT:    srli a0, a0, 61
+; RV64-NEXT:    or a0, a4, a0
 ; RV64-NEXT:    sd a1, 0(s0)
-; RV64-NEXT:    sw a3, 8(s0)
-; RV64-NEXT:    sb a0, 12(s0)
+; RV64-NEXT:    sw a0, 8(s0)
+; RV64-NEXT:    sb a3, 12(s0)
 ; RV64-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
 ; RV64-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
 ; RV64-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
@@ -607,69 +606,68 @@ define void @test_srem_vec(ptr %X) nounwind {
 ;
 ; RV64M-LABEL: test_srem_vec:
 ; RV64M:       # %bb.0:
-; RV64M-NEXT:    ld a1, 0(a0)
+; RV64M-NEXT:    lbu a1, 12(a0)
 ; RV64M-NEXT:    lwu a2, 8(a0)
-; RV64M-NEXT:    lbu a3, 12(a0)
+; RV64M-NEXT:    ld a3, 0(a0)
 ; RV64M-NEXT:    lui a4, %hi(.LCPI3_0)
 ; RV64M-NEXT:    lui a5, %hi(.LCPI3_1)
 ; RV64M-NEXT:    ld a4, %lo(.LCPI3_0)(a4)
 ; RV64M-NEXT:    ld a5, %lo(.LCPI3_1)(a5)
-; RV64M-NEXT:    srli a6, a1, 2
+; RV64M-NEXT:    slli a1, a1, 32
+; RV64M-NEXT:    srli a6, a3, 2
 ; RV64M-NEXT:    slli a7, a2, 62
-; RV64M-NEXT:    slli a3, a3, 32
-; RV64M-NEXT:    or a6, a7, a6
-; RV64M-NEXT:    or a2, a2, a3
-; RV64M-NEXT:    srai a3, a6, 31
-; RV64M-NEXT:    slli a2, a2, 29
-; RV64M-NEXT:    mulh a5, a3, a5
-; RV64M-NEXT:    lui a6, 699051
+; RV64M-NEXT:    or a1, a2, a1
+; RV64M-NEXT:    or a2, a7, a6
+; RV64M-NEXT:    slli a1, a1, 29
 ; RV64M-NEXT:    srai a2, a2, 31
-; RV64M-NEXT:    addi a6, a6, -1365
+; RV64M-NEXT:    srai a1, a1, 31
 ; RV64M-NEXT:    mulh a4, a2, a4
+; RV64M-NEXT:    lui a6, 699051
+; RV64M-NEXT:    mulh a5, a1, a5
+; RV64M-NEXT:    addi a6, a6, -1365
 ; RV64M-NEXT:    slli a7, a6, 32
-; RV64M-NEXT:    slli a1, a1, 31
+; RV64M-NEXT:    slli a3, a3, 31
 ; RV64M-NEXT:    add a6, a6, a7
-; RV64M-NEXT:    srai a1, a1, 31
-; RV64M-NEXT:    lui a7, %hi(.LCPI3_2)
-; RV64M-NEXT:    mul a1, a1, a6
-; RV64M-NEXT:    srli a6, a5, 63
-; RV64M-NEXT:    srai a5, a5, 1
-; RV64M-NEXT:    ld a7, %lo(.LCPI3_2)(a7)
-; RV64M-NEXT:    add a5, a5, a6
+; RV64M-NEXT:    srai a3, a3, 31
+; RV64M-NEXT:    mul a3, a3, a6
 ; RV64M-NEXT:    srli a6, a4, 63
 ; RV64M-NEXT:    srai a4, a4, 1
-; RV64M-NEXT:    add a3, a3, a5
-; RV64M-NEXT:    slli a5, a5, 3
+; RV64M-NEXT:    srli a7, a5, 63
+; RV64M-NEXT:    srai a5, a5, 1
 ; RV64M-NEXT:    add a4, a4, a6
-; RV64M-NEXT:    sub a3, a3, a5
-; RV64M-NEXT:    add a2, a2, a4
-; RV64M-NEXT:    slli a4, a4, 2
+; RV64M-NEXT:    add a5, a5, a7
+; RV64M-NEXT:    lui a6, %hi(.LCPI3_2)
 ; RV64M-NEXT:    add a2, a2, a4
-; RV64M-NEXT:    addi a3, a3, -1
-; RV64M-NEXT:    seqz a3, a3
-; RV64M-NEXT:    add a1, a1, a7
-; RV64M-NEXT:    slli a4, a1, 63
-; RV64M-NEXT:    srli a1, a1, 1
-; RV64M-NEXT:    addi a2, a2, -2
-; RV64M-NEXT:    or a1, a1, a4
+; RV64M-NEXT:    slli a4, a4, 3
+; RV64M-NEXT:    ld a6, %lo(.LCPI3_2)(a6)
+; RV64M-NEXT:    add a1, a1, a5
+; RV64M-NEXT:    slli a5, a5, 2
+; RV64M-NEXT:    sub a2, a2, a4
+; RV64M-NEXT:    add a1, a1, a5
+; RV64M-NEXT:    addi a1, a1, -2
+; RV64M-NEXT:    addi a2, a2, -1
+; RV64M-NEXT:    seqz a1, a1
+; RV64M-NEXT:    add a3, a3, a6
+; RV64M-NEXT:    slli a4, a3, 63
+; RV64M-NEXT:    srli a3, a3, 1
 ; RV64M-NEXT:    seqz a2, a2
-; RV64M-NEXT:    sltu a1, a7, a1
+; RV64M-NEXT:    or a3, a3, a4
+; RV64M-NEXT:    sltu a3, a6, a3
 ; RV64M-NEXT:    addi a2, a2, -1
-; RV64M-NEXT:    neg a1, a1
-; RV64M-NEXT:    addi a3, a3, -1
-; RV64M-NEXT:    slli a1, a1, 31
-; RV64M-NEXT:    slli a4, a3, 33
-; RV64M-NEXT:    srli a1, a1, 31
-; RV64M-NEXT:    or a1, a1, a4
+; RV64M-NEXT:    addi a1, a1, -1
+; RV64M-NEXT:    neg a3, a3
+; RV64M-NEXT:    andi a4, a1, 7
 ; RV64M-NEXT:    slli a3, a3, 31
-; RV64M-NEXT:    slli a4, a2, 2
-; RV64M-NEXT:    srli a3, a3, 62
-; RV64M-NEXT:    or a3, a3, a4
-; RV64M-NEXT:    slli a2, a2, 29
-; RV64M-NEXT:    srli a2, a2, 61
-; RV64M-NEXT:    sd a1, 0(a0)
-; RV64M-NEXT:    sw a3, 8(a0)
-; RV64M-NEXT:    sb a2, 12(a0)
+; RV64M-NEXT:    slli a5, a2, 33
+; RV64M-NEXT:    srli a3, a3, 31
+; RV64M-NEXT:    or a3, a3, a5
+; RV64M-NEXT:    slli a2, a2, 31
+; RV64M-NEXT:    slli a1, a1, 2
+; RV64M-NEXT:    srli a2, a2, 62
+; RV64M-NEXT:    or a1, a2, a1
+; RV64M-NEXT:    sd a3, 0(a0)
+; RV64M-NEXT:    sw a1, 8(a0)
+; RV64M-NEXT:    sb a4, 12(a0)
 ; RV64M-NEXT:    ret
 ;
 ; RV32MV-LABEL: test_srem_vec:
diff --git a/llvm/test/CodeGen/X86/vector-bo-select.ll b/llvm/test/CodeGen/X86/vector-bo-select.ll
index cdbc80dfbe6dda..ac27c26768c920 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