diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5907,8 +5907,8 @@
   SDValue LHS1 = LHS->getOperand(1);
   SDValue RHS1 = RHS->getOperand(1);
 
-  // TODO: We don't actually need a splat here, for vectors we just need
-  // LaneLHS[N] == -LaneRHS[N];
+  // TODO: We don't actually need a splat here, for vectors we just need the
+  // invariants to hold for each element.
   auto *LHS1C = isConstOrConstSplat(LHS1);
   auto *RHS1C = isConstOrConstSplat(RHS1);
 
@@ -5919,15 +5919,16 @@
   if (CCL == CCR &&
       CCL == (LogicOp->getOpcode() == ISD::AND ? ISD::SETNE : ISD::SETEQ) &&
       LHS0 == RHS0 && LHS1C && RHS1C && OpVT.isInteger() && LHS.hasOneUse() &&
-      RHS.hasOneUse() && LHS1C->getAPIntValue() == (-RHS1C->getAPIntValue())) {
+      RHS.hasOneUse()) {
+    const APInt &APLhs = LHS1C->getAPIntValue();
+    const APInt &APRhs = RHS1C->getAPIntValue();
 
     // Preference is to use ISD::ABS or we already have an ISD::ABS (in which
     // case this is just a compare).
-    if (TargetPreference == AndOrSETCCFoldKind::ABS ||
-        DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0})) {
-      APInt C = LHS1C->getAPIntValue();
-      if (C.isNegative())
-        C = RHS1C->getAPIntValue();
+    if (APLhs == (-APRhs) &&
+        (TargetPreference == AndOrSETCCFoldKind::ABS ||
+         DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}))) {
+      const APInt &C = APLhs.isNegative() ? APRhs : APLhs;
       // (icmp eq A, C) | (icmp eq A, -C)
       //    -> (icmp eq Abs(A), C)
       // (icmp ne A, C) & (icmp ne A, -C)
@@ -5936,23 +5937,20 @@
       return DAG.getNode(ISD::SETCC, DL, VT, AbsOp,
                          DAG.getConstant(C, DL, OpVT), LHS.getOperand(2));
     } else if (TargetPreference == AndOrSETCCFoldKind::AddAnd) {
-      // With C as a power of 2 and C != 0 and C != INT_MIN:
-      //   (icmp eq A, C) | (icmp eq A, -C)
-      //        -> (icmp eq and(add(A, C), ~(C + C)), 0)
-      //   (icmp ne A, C) & (icmp ne A, -C)w
-      //        -> (icmp ne and(add(A, C), ~(C + C)), 0)
-      const ConstantSDNode *Pow2 = nullptr;
-      if (LHS1C->getAPIntValue().isPowerOf2())
-        Pow2 = LHS1C;
-      else if (RHS1C->getAPIntValue().isPowerOf2())
-        Pow2 = RHS1C;
-      // isPowerOf2 is only for non-zero powers of 2.
-      if (Pow2 != nullptr && !Pow2->getAPIntValue().isMinSignedValue()) {
-        const APInt &C = Pow2->getAPIntValue();
-        SDValue AddOp =
-            DAG.getNode(ISD::ADD, DL, OpVT, LHS0, DAG.getConstant(C, DL, OpVT));
+      // A == C0 | A == C1
+      //  IF IsPow2(smax(C0, C1)-smin(C0, C1))
+      //    -> ((A - smin(C0, C1)) & ~(smax(C0, C1)-smin(C0, C1))) == 0
+      // A != C0 & A != C1
+      //  IF IsPow2(smax(C0, C1)-smin(C0, C1))
+      //    -> ((A - smin(C0, C1)) & ~(smax(C0, C1)-smin(C0, C1))) != 0
+      const APInt &MaxC = APIntOps::smax(APRhs, APLhs);
+      const APInt &MinC = APIntOps::smin(APRhs, APLhs);
+      APInt Dif = MaxC - MinC;
+      if (!Dif.isZero() && Dif.isPowerOf2()) {
+        SDValue AddOp = DAG.getNode(ISD::ADD, DL, OpVT, LHS0,
+                                    DAG.getConstant(-MinC, DL, OpVT));
         SDValue AndOp = DAG.getNode(ISD::AND, DL, OpVT, AddOp,
-                                    DAG.getConstant(~(C + C), DL, OpVT));
+                                    DAG.getConstant(~Dif, DL, OpVT));
         return DAG.getNode(ISD::SETCC, DL, VT, AndOp,
                            DAG.getConstant(0, DL, OpVT), LHS.getOperand(2));
       }
diff --git a/llvm/test/CodeGen/X86/icmp-pow2-diff.ll b/llvm/test/CodeGen/X86/icmp-pow2-diff.ll
--- a/llvm/test/CodeGen/X86/icmp-pow2-diff.ll
+++ b/llvm/test/CodeGen/X86/icmp-pow2-diff.ll
@@ -311,12 +311,9 @@
 define i1 @addand_ne_i16(i16 %x) nounwind {
 ; CHECK-LABEL: addand_ne_i16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpw $-3, %di
-; CHECK-NEXT:    setne %cl
-; CHECK-NEXT:    movzwl %di, %eax
-; CHECK-NEXT:    cmpl $16381, %eax # imm = 0x3FFD
+; CHECK-NEXT:    addl $3, %edi
+; CHECK-NEXT:    testl $49151, %edi # imm = 0xBFFF
 ; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    andb %cl, %al
 ; CHECK-NEXT:    retq
   %cmp1 = icmp ne i16 %x, -3
   %cmp2 = icmp ne i16 %x, 16381
@@ -362,11 +359,9 @@
 define i1 @addand_eq_i32(i32 %x) nounwind {
 ; CHECK-LABEL: addand_eq_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpl $-1, %edi
-; CHECK-NEXT:    sete %cl
-; CHECK-NEXT:    cmpl $7, %edi
+; CHECK-NEXT:    incl %edi
+; CHECK-NEXT:    testl $-9, %edi
 ; CHECK-NEXT:    sete %al
-; CHECK-NEXT:    orb %cl, %al
 ; CHECK-NEXT:    retq
   %cmp1 = icmp eq i32 %x, -1
   %cmp2 = icmp eq i32 %x, 7
@@ -393,11 +388,9 @@
 define i1 @addand_ne_i8(i8 %x) nounwind {
 ; CHECK-LABEL: addand_ne_i8:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpb $59, %dil
-; CHECK-NEXT:    setne %cl
-; CHECK-NEXT:    cmpb $-5, %dil
+; CHECK-NEXT:    addb $5, %dil
+; CHECK-NEXT:    testb $-65, %dil
 ; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    andb %cl, %al
 ; CHECK-NEXT:    retq
   %cmp1 = icmp ne i8 %x, 59
   %cmp2 = icmp ne i8 %x, -5
@@ -424,11 +417,9 @@
 define i1 @addand_eq_i64(i64 %x) nounwind {
 ; CHECK-LABEL: addand_eq_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    cmpq $768, %rdi # imm = 0x300
-; CHECK-NEXT:    setne %cl
-; CHECK-NEXT:    cmpq $-256, %rdi
+; CHECK-NEXT:    addq $256, %rdi # imm = 0x100
+; CHECK-NEXT:    testq $-1025, %rdi # imm = 0xFBFF
 ; CHECK-NEXT:    setne %al
-; CHECK-NEXT:    andb %cl, %al
 ; CHECK-NEXT:    retq
   %cmp1 = icmp ne i64 %x, 768
   %cmp2 = icmp ne i64 %x, -256
diff --git a/llvm/test/CodeGen/X86/setcc-logic.ll b/llvm/test/CodeGen/X86/setcc-logic.ll
--- a/llvm/test/CodeGen/X86/setcc-logic.ll
+++ b/llvm/test/CodeGen/X86/setcc-logic.ll
@@ -456,8 +456,8 @@
 ; CHECK-LABEL: ne_neg1_and_ne_zero:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    incq %rdi
-; CHECK-NEXT:    cmpq $2, %rdi
-; CHECK-NEXT:    setae %al
+; CHECK-NEXT:    testq $-2, %rdi
+; CHECK-NEXT:    setne %al
 ; CHECK-NEXT:    retq
   %cmp1 = icmp ne i64 %x, -1
   %cmp2 = icmp ne i64 %x, 0