[llvm] 9858b9b - [DAG] Fold pow2 masked bittest comparisons (#216302)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 06:17:15 PDT 2026


Author: Dhruva
Date: 2026-08-19T13:17:10Z
New Revision: 9858b9bee7f2173ff9d32face0d17a620d2eae90

URL: https://github.com/llvm/llvm-project/commit/9858b9bee7f2173ff9d32face0d17a620d2eae90
DIFF: https://github.com/llvm/llvm-project/commit/9858b9bee7f2173ff9d32face0d17a620d2eae90.diff

LOG: [DAG] Fold pow2 masked bittest comparisons (#216302)

Implements logic to merge bittest comparisons in `foldLogicOfSetCCs` .

Equivalent to the fold done in `foldLogOpOfMaskedICmps`.

Fold is valid when `LL1` and `RL1` are powers of 2.
```cpp
(and (setne (and X, LL1), 0), (setne (and X, RL1), 0)) --> (seteq (and X, (LL1|RL1)), (LL1|RL1))
(or  (seteq (and X, LL1), 0), (seteq (and X, RL1), 0)) --> (setne (and X, (LL1|RL1)), (LL1|RL1))
```

Fixes #214772 .

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/X86/setcc-logic.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 053e993a49e66..8c3e487b44e9e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6814,6 +6814,26 @@ SDValue DAGCombiner::foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1,
     }
   }
 
+  // (and (setne (and X, LL1), 0), (setne (and X, RL1), 0))
+  // --> (seteq (and X, (LL1|RL1)), (LL1|RL1))
+  // (or  (seteq (and X, LL1), 0), (seteq (and X, RL1), 0))
+  // --> (setne (and X, (LL1|RL1)), (LL1|RL1))
+  if (LL.getOpcode() == ISD::AND && RL.getOpcode() == ISD::AND &&
+      isNullConstant(LR) && isNullConstant(RR) && CC0 == CC1 &&
+      (CC0 == ISD::SETNE || CC0 == ISD::SETEQ)) {
+    SDValue LL0, LL1, RL0, RL1;
+    LL0 = LL.getOperand(0);
+    RL0 = RL.getOperand(0);
+    LL1 = LL.getOperand(1);
+    RL1 = RL.getOperand(1);
+    if (LL0 == RL0 && DAG.isKnownToBeAPowerOfTwo(LL1) &&
+        DAG.isKnownToBeAPowerOfTwo(RL1)) {
+      SDValue Or = DAG.getNode(ISD::OR, SDLoc(N0), OpVT, LL1, RL1);
+      SDValue And = DAG.getNode(ISD::AND, SDLoc(N0), OpVT, LL0, Or);
+      return DAG.getSetCC(DL, VT, And, Or, IsAnd ? ISD::SETEQ : ISD::SETNE);
+    }
+  }
+
   // (and (setne X, 0), (setne X, -1)) --> (setuge (add X, 1), 2)
   // (or  (seteq X, 0), (seteq X, -1)) --> (setult (add X, 1), 2)
   if (LL == RL && CC0 == CC1 && OpVT.getScalarSizeInBits() > 1 && IsInteger &&

diff  --git a/llvm/test/CodeGen/X86/setcc-logic.ll b/llvm/test/CodeGen/X86/setcc-logic.ll
index c577849b45ee8..1390c666bb4ec 100644
--- a/llvm/test/CodeGen/X86/setcc-logic.ll
+++ b/llvm/test/CodeGen/X86/setcc-logic.ll
@@ -740,3 +740,136 @@ define <16 x i8> @or_cmp_ne_v4i32(<16 x i8> %x, <16 x i8> %y) {
   %s = sext <16 x i1> %c to <16 x i8>
   ret <16 x i8> %s
 }
+
+;PR214772 - Merge bittest comparisions.
+
+define i1 @and_cmp_ne(i8 %x) {
+; CHECK-LABEL: and_cmp_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notb %dil
+; CHECK-NEXT:    testb $12, %dil
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 4
+  %a2 = and i8 %x, 8
+  %c1 = icmp ne i8 %a1, 0
+  %c2 = icmp ne i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @and_cmp_eq(i8 %x) {
+; CHECK-LABEL: and_cmp_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    testb $12, %dil
+; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 4
+  %a2 = and i8 %x, 8
+  %c1 = icmp eq i8 %a1, 0
+  %c2 = icmp eq i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @or_cmp_eq(i32 %x) {
+; CHECK-LABEL: or_cmp_eq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    notl %edi
+; CHECK-NEXT:    testb $40, %dil
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    retq
+  %a1 = and i32 %x, 8
+  %a2 = and i32 %x, 32
+  %c1 = icmp eq i32 %a1, 0
+  %c2 = icmp eq i32 %a2, 0
+  %res = or i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @or_cmp_ne(i32 %x) {
+; CHECK-LABEL: or_cmp_ne:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    testb $40, %dil
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    retq
+  %a1 = and i32 %x, 8
+  %a2 = and i32 %x, 32
+  %c1 = icmp ne i32 %a1, 0
+  %c2 = icmp ne i32 %a2, 0
+  %res = or i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @not_pow2(i8 %x) {
+; CHECK-LABEL: not_pow2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andb $8, %al
+; CHECK-NEXT:    testb $3, %dil
+; CHECK-NEXT:    setne %cl
+; CHECK-NEXT:    shrb $3, %al
+; CHECK-NEXT:    andb %cl, %al
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 3
+  %a2 = and i8 %x, 8
+  %c1 = icmp ne i8 %a1, 0
+  %c2 = icmp ne i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @
diff _vars(i8 %x, i8 %y) {
+; CHECK-LABEL: 
diff _vars:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %esi, %eax
+; CHECK-NEXT:    andb $8, %al
+; CHECK-NEXT:    shrb $2, %dil
+; CHECK-NEXT:    shrb $3, %al
+; CHECK-NEXT:    andb %dil, %al
+; CHECK-NEXT:    # kill: def $al killed $al killed $eax
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 4
+  %a2 = and i8 %y, 8
+  %c1 = icmp ne i8 %a1, 0
+  %c2 = icmp ne i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @nonzero_rhs(i8 %x) {
+; CHECK-LABEL: nonzero_rhs:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andb $4, %al
+; CHECK-NEXT:    andb $8, %dil
+; CHECK-NEXT:    cmpb $1, %al
+; CHECK-NEXT:    setne %al
+; CHECK-NEXT:    shrb $3, %dil
+; CHECK-NEXT:    andb %dil, %al
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 4
+  %a2 = and i8 %x, 8
+  %c1 = icmp ne i8 %a1, 1
+  %c2 = icmp ne i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}
+
+define i1 @mixed_cc(i8 %x) {
+; CHECK-LABEL: mixed_cc:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    andb $8, %al
+; CHECK-NEXT:    testb $4, %dil
+; CHECK-NEXT:    sete %cl
+; CHECK-NEXT:    shrb $3, %al
+; CHECK-NEXT:    andb %cl, %al
+; CHECK-NEXT:    retq
+  %a1 = and i8 %x, 4
+  %a2 = and i8 %x, 8
+  %c1 = icmp eq i8 %a1, 0
+  %c2 = icmp ne i8 %a2, 0
+  %res = and i1 %c1, %c2
+  ret i1 %res
+}


        


More information about the llvm-commits mailing list