diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index e577d0cc7ad41..57fa4f29d5eff 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -94,6 +94,10 @@ void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, KnownBits &Known);
 void computeKnownBitsFromContext(const Value *V, KnownBits &Known,
                                  unsigned Depth, const SimplifyQuery &Q);
 
+void computeKnownBitsFromCond(const Value *V, Value *Cond, KnownBits &Known,
+                              unsigned Depth, const SimplifyQuery &SQ,
+                              bool Invert);
+
 /// Using KnownBits LHS/RHS produce the known bits for logic op (and/xor/or).
 KnownBits analyzeKnownBitsFromAndXorOr(const Operator *I,
                                        const KnownBits &KnownLHS,
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index 855d1aeddfaee..f81150b7b31f6 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -438,6 +438,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
     return llvm::computeKnownBits(V, Depth, SQ.getWithInstruction(CxtI));
   }
 
+  void computeKnownBitsFromCond(const Value *V, ICmpInst *Cmp, KnownBits &Known,
+                                unsigned Depth, const Instruction *CxtI,
+                                bool Invert) const {
+    llvm::computeKnownBitsFromCond(V, Cmp, Known, Depth,
+                                   SQ.getWithInstruction(CxtI), Invert);
+  }
+
   bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero = false,
                               unsigned Depth = 0,
                               const Instruction *CxtI = nullptr) {
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8126d2a1acc27..085e4a81d17ee 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -747,9 +747,9 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
   computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
 }
 
-static void computeKnownBitsFromCond(const Value *V, Value *Cond,
-                                     KnownBits &Known, unsigned Depth,
-                                     const SimplifyQuery &SQ, bool Invert) {
+void llvm::computeKnownBitsFromCond(const Value *V, Value *Cond,
+                                    KnownBits &Known, unsigned Depth,
+                                    const SimplifyQuery &SQ, bool Invert) {
   Value *A, *B;
   if (Depth < MaxAnalysisRecursionDepth &&
       match(Cond, m_LogicalOp(m_Value(A), m_Value(B)))) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 7d26807544d7e..3d667ec5f1b3f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1809,6 +1809,198 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+// ICmpInst of SelectInst is not included in the calculation of KnownBits
+// so we are missing the opportunity to optimize the Value of the True or
+// False Condition via ICmpInst with KnownBits.
+//
+// Consider:
+//   %or = or i32 %x, %y
+//   %or0 = icmp eq i32 %or, 0
+//   %and = and i32 %x, %y
+//   %cond = select i1 %or0, i32 %and, i32 %or
+//   ret i32 %cond
+//
+// Expect:
+//   %or = or i32 %x, %y
+//   ret i32 %or
+//
+// We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
+static Instruction *foldSelectICmpBinOp(SelectInst &SI, ICmpInst *ICI,
+                                        Value *CmpLHS, Value *CmpRHS,
+                                        Value *TVal, Value *FVal,
+                                        InstCombinerImpl &IC) {
+  Value *X, *Y;
+  const APInt *C;
+  unsigned CmpLHSOpc;
+  bool IsDisjoint = false;
+  // Specially handling for X^Y==0 transformed to X==Y
+  if (match(TVal, m_c_BitwiseLogic(m_Specific(CmpLHS), m_Specific(CmpRHS)))) {
+    X = CmpLHS;
+    Y = CmpRHS;
+    APInt ZeroVal = APInt::getZero(CmpLHS->getType()->getScalarSizeInBits());
+    C = const_cast<APInt *>(&ZeroVal);
+    CmpLHSOpc = Instruction::Xor;
+  } else if ((match(CmpLHS, m_BinOp(m_Value(X), m_Value(Y))) &&
+              match(CmpRHS, m_APInt(C))) &&
+             (match(TVal, m_c_BinOp(m_Specific(X), m_Value())) ||
+              match(TVal, m_c_BinOp(m_Specific(Y), m_Value())))) {
+    if (auto Inst = dyn_cast<PossiblyDisjointInst>(CmpLHS)) {
+      if (Inst->isDisjoint())
+        IsDisjoint = true;
+      CmpLHSOpc = Instruction::Or;
+    } else
+      CmpLHSOpc = cast<BinaryOperator>(CmpLHS)->getOpcode();
+  } else
+    return nullptr;
+
+  enum SpecialKnownBits {
+    NothingSpecial = 0,
+    NoCommonBits = 1 << 1,
+    AllCommonBits = 1 << 2,
+    AllBitsEnabled = 1 << 3,
+  };
+
+  // We cannot know exactly what bits is known in X Y.
+  // Instead, we just know what relationship exist for.
+  auto isSpecialKnownBitsFor = [&]() -> unsigned {
+    if (CmpLHSOpc == Instruction::And) {
+      if (C->isZero())
+        return NoCommonBits;
+    } else if (CmpLHSOpc == Instruction::Xor) {
+      if (C->isAllOnes())
+        return NoCommonBits | AllBitsEnabled;
+      if (C->isZero())
+        return AllCommonBits;
+    } else if (CmpLHSOpc == Instruction::Or && IsDisjoint) {
+      if (C->isAllOnes())
+        return NoCommonBits | AllBitsEnabled;
+      return NoCommonBits;
+    }
+
+    return NothingSpecial;
+  };
+
+  auto hasOperandAt = [&](Instruction *I, Value *Op) -> int {
+    for (unsigned Idx = 0; Idx < I->getNumOperands(); Idx++) {
+      if (I->getOperand(Idx) == Op)
+        return Idx + 1;
+    }
+    return 0;
+  };
+
+  Type *TValTy = TVal->getType();
+  unsigned BitWidth = TVal->getType()->getScalarSizeInBits();
+  auto TValBop = cast<BinaryOperator>(TVal);
+  unsigned XOrder = hasOperandAt(TValBop, X);
+  unsigned YOrder = hasOperandAt(TValBop, Y);
+  unsigned SKB = isSpecialKnownBitsFor();
+
+  KnownBits Known;
+  if (TValBop->isBitwiseLogicOp()) {
+    // We handle if we know specific knownbits from cond of selectinst.
+    // ex) X&Y==-1 ? X^Y : False
+    if (SKB != SpecialKnownBits::NothingSpecial && XOrder && YOrder) {
+      // No common bits between X, Y
+      if (SKB & SpecialKnownBits::NoCommonBits) {
+        if (SKB & (SpecialKnownBits::AllBitsEnabled)) {
+          // If X op Y == -1, then XOR must be -1
+          if (TValBop->getOpcode() == Instruction::Xor)
+            Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+        }
+        // If Trueval is X&Y then it should be 0.
+        if (TValBop->getOpcode() == Instruction::And)
+          Known = KnownBits::makeConstant(APInt(BitWidth, 0));
+        // X|Y can be replace with X^Y, X^Y can be replace with X|Y
+        // This replacing is meaningful when falseval is same.
+        else if ((match(TVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+                  match(FVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) ||
+                 (match(TVal, m_c_Xor(m_Specific(X), m_Specific(Y))) &&
+                  match(FVal, m_c_Or(m_Specific(X), m_Specific(Y)))))
+          return IC.replaceInstUsesWith(SI, FVal);
+        // All common bits between X, Y
+      } else if (SKB & SpecialKnownBits::AllCommonBits) {
+        // We can replace (X&Y) and (X|Y) to X or Y
+        if (TValBop->getOpcode() == Instruction::And ||
+            TValBop->getOpcode() == Instruction::Or)
+          if (TValBop->hasOneUse())
+            return IC.replaceOperand(SI, 1, X);
+      } else if (SKB & SpecialKnownBits::AllBitsEnabled) {
+        // We can replace (X|Y) to -1
+        if (TValBop->getOpcode() == Instruction::Or)
+          Known = KnownBits::makeConstant(APInt(BitWidth, -1));
+      }
+    } else {
+      KnownBits XKnown, YKnown, Temp;
+      KnownBits TValBop0KB, TValBop1KB;
+      // computeKnowBits calculates the KnownBits in the branching condition
+      // that the specified variable passes in the execution flow. however, it
+      // does not contain the SelectInst condition, so there is an optimization
+      // opportunity to update the knownbits obtained by calculating KnownBits
+      // with the SelectInst condition.
+      XKnown = IC.computeKnownBits(X, 0, &SI);
+      IC.computeKnownBitsFromCond(X, ICI, XKnown, 0, &SI, false);
+      YKnown = IC.computeKnownBits(Y, 0, &SI);
+      IC.computeKnownBitsFromCond(Y, ICI, YKnown, 0, &SI, false);
+      CmpInst::Predicate Pred = ICI->getPredicate();
+      if (Pred == ICmpInst::ICMP_EQ) {
+        // Estimate additional KnownBits from the relationship between X and Y
+        if (CmpLHSOpc == Instruction::And) {
+          // The bit that are set to 1 at `~C&Y` must be 0 in X
+          // The bit that are set to 1 at `~C&X` must be 0 in Y
+          XKnown.Zero |= ~*C & YKnown.One;
+          YKnown.Zero |= ~*C & XKnown.One;
+        }
+        if (CmpLHSOpc == Instruction::Or) {
+          // The bit that are set to 0 at `C&Y` must be 1 in X
+          // The bit that are set to 0 at `C&X` must be 1 in Y
+          XKnown.One |= *C & YKnown.Zero;
+          YKnown.One |= *C & XKnown.Zero;
+        }
+        if (CmpLHSOpc == Instruction::Xor) {
+          // If X^Y==C, then X and Y must be either (1,0) or (0,1) for the
+          // enabled bits in C.
+          XKnown.One |= *C & YKnown.Zero;
+          XKnown.Zero |= *C & YKnown.One;
+          YKnown.One |= *C & XKnown.Zero;
+          YKnown.Zero |= *C & XKnown.One;
+          // If X^Y==C, then X and Y must be either (0,0) or (1,1) for the
+          // disabled bits in C.
+          XKnown.Zero |= ~*C & YKnown.Zero;
+          XKnown.One |= ~*C & YKnown.One;
+          YKnown.Zero |= ~*C & XKnown.Zero;
+          YKnown.One |= ~*C & XKnown.One;
+        }
+      }
+
+      // If TrueVal has X or Y, return the corresponding KnownBits, otherwise
+      // compute and return new KnownBits.
+      auto getTValBopKB = [&](unsigned OpNum) -> KnownBits {
+        unsigned Order = OpNum + 1;
+        if (Order == XOrder)
+          return XKnown;
+        else if (Order == YOrder)
+          return YKnown;
+
+        Value *V = TValBop->getOperand(OpNum);
+        KnownBits Known = IC.computeKnownBits(V, 0, &SI);
+        return Known;
+      };
+      TValBop0KB = getTValBopKB(0);
+      TValBop1KB = getTValBopKB(1);
+      Known = analyzeKnownBitsFromAndXorOr(
+          cast<Operator>(TValBop), TValBop0KB, TValBop1KB, 0,
+          IC.getSimplifyQuery().getWithInstruction(&SI));
+    }
+  }
+
+  if (Known.isConstant()) {
+    auto Const = ConstantInt::get(TValTy, Known.getConstant());
+    return IC.replaceOperand(SI, 1, Const);
+  }
+
+  return nullptr;
+}
+
 /// Visit a SelectInst that has an ICmpInst as its first operand.
 Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
                                                       ICmpInst *ICI) {
@@ -1951,6 +2143,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
   if (Value *V = foldAbsDiff(ICI, TrueVal, FalseVal, Builder))
     return replaceInstUsesWith(SI, V);
 
+  if (Instruction *NewSel = foldSelectICmpBinOp(SI, ICI, CmpLHS, CmpRHS,
+                                                TrueVal, FalseVal, *this))
+    return NewSel;
+
   return Changed ? &SI : nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/select-of-bittest.ll b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
index e3eb76de459e2..b81b90c1a948e 100644
--- a/llvm/test/Transforms/InstCombine/select-of-bittest.ll
+++ b/llvm/test/Transforms/InstCombine/select-of-bittest.ll
@@ -3,7 +3,408 @@
 
 ; https://bugs.llvm.org/show_bug.cgi?id=36950
 
-; These all should be just and+icmp, there should be no select.
+; ====================== AND =======================
+define i8 @src_and_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 2, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %x, 3
+  %and1 = and i8 %x, 2
+  %and2 = and i8 %and, %x
+  %cmp = icmp eq i8 %and2, 2
+  %cond = select i1 %cmp, i8 %and1, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_and_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 2, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8><i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_and_bit_ne(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_and_bit_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[X:%.*]], 3
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[AND]], 2
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 2, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %x, 3
+  %and1 = and i8 %x, 2
+  %and2 = and i8 %and, %x
+  %cmp = icmp ne i8 %and2, 2
+  %cond = select i1 %cmp, i8 1, i8 %and1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_and_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 2, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_and_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_and_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 poison, i8 3>
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[AND]], <i8 2, i8 2>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 2, i8 2>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %x, <i8 poison, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 2>
+  %and2 = and <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %and2, <i8 2, i8 2>
+  %cond = select <2 x i1> %cmp, <2 x i8><i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+; ====================== OR =======================
+define i8 @src_or_bit(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit(
+; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %z, 3
+  %and1 = shl i8 %y, 2
+  %shl = and i8 %and1, 12
+  %or = or i8 %shl, %x
+  %cmp = icmp eq i8 %or, 3
+  %or2 = or i8 %and, %x
+  %cond = select i1 %cmp, i8 %or2, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_or_bit_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+  %shl = and <2 x i8> %and1, <i8 12, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 poison>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+  %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 poison, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+  %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp eq <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> %or2, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_or_bit_ne(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @src_or_bit_ne(
+; CHECK-NEXT:    [[AND1:%.*]] = shl i8 [[Y:%.*]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = and i8 [[AND1]], 12
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[OR]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 3, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %z, 3
+  %and1 = shl i8 %y, 2
+  %shl = and i8 %and1, 12
+  %or = or i8 %shl, %x
+  %cmp = icmp ne i8 %or, 3
+  %or2 = or i8 %and, %x
+  %cond = select i1 %cmp, i8 1, i8 %or2
+  ret i8 %cond
+}
+
+define <2 x i8> @src_or_bit_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_ne(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 2>
+  %shl = and <2 x i8> %and1, <i8 12, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 2, i8 poison>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 12, i8 poison>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 3, i8 poison>
+  %and1 = shl <2 x i8> %y, <i8 2, i8 poison>
+  %shl = and <2 x i8> %and1, <i8 12, i8 poison>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
+; CHECK-LABEL: @src_or_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND1:%.*]] = shl <2 x i8> [[Y:%.*]], <i8 poison, i8 2>
+; CHECK-NEXT:    [[SHL:%.*]] = and <2 x i8> [[AND1]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[OR:%.*]] = or <2 x i8> [[SHL]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[OR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %z, <i8 poison, i8 3>
+  %and1 = shl <2 x i8> %y, <i8 poison, i8 2>
+  %shl = and <2 x i8> %and1, <i8 poison, i8 12>
+  %or = or <2 x i8> %shl, %x
+  %cmp = icmp ne <2 x i8> %or, <i8 3, i8 3>
+  %or2 = or <2 x i8> %and, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %or2
+  ret <2 x i8> %cond
+}
+
+; ====================== XOR =======================
+define i8 @src_xor_bit(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i8 3, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %y, 12
+  %xor = xor i8 %and, %x
+  %cmp = icmp eq i8 %xor, 3
+  %and1 = and i8 %x, 3
+  %cond = select i1 %cmp, i8 %and1, i8 1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_xor_bit_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 12, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison2(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp eq <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> %and1, <2 x i8> <i8 1, i8 1>
+  ret <2 x i8> %cond
+}
+
+define i8 @src_xor_bit_ne(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_xor_bit_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[Y:%.*]], 12
+; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[XOR]], 3
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i8 3, i8 1
+; CHECK-NEXT:    ret i8 [[COND]]
+;
+  %and = and i8 %y, 12
+  %xor = xor i8 %and, %x
+  %cmp = icmp ne i8 %xor, 3
+  %and1 = and i8 %x, 3
+  %cond = select i1 %cmp, i8 1, i8 %and1
+  ret i8 %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 12, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 12, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 poison, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_xor_bit_vec_poison2_ne(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_xor_bit_vec_poison2_ne(
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i8> [[Y:%.*]], <i8 poison, i8 12>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[AND]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[XOR]], <i8 3, i8 3>
+; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> <i8 3, i8 3>, <2 x i8> <i8 1, i8 1>
+; CHECK-NEXT:    ret <2 x i8> [[COND]]
+;
+  %and = and <2 x i8> %y, <i8 poison, i8 12>
+  %xor = xor <2 x i8> %and, %x
+  %cmp = icmp ne <2 x i8> %xor, <i8 3, i8 3>
+  %and1 = and <2 x i8> %x, <i8 3, i8 3>
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 1, i8 1>, <2 x i8> %and1
+  ret <2 x i8> %cond
+}
 
 define i32 @and_lshr_and(i32 %arg) {
 ; CHECK-LABEL: @and_lshr_and(
@@ -590,13 +991,13 @@ define i32 @n5(i32 %arg) {
 ; CHECK-LABEL: @n5(
 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[ARG:%.*]], 2
 ; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T]], 0
-; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 2
+; CHECK-NEXT:    [[T2:%.*]] = and i32 [[ARG]], 3
 ; CHECK-NEXT:    [[T3:%.*]] = select i1 [[T1]], i32 [[T2]], i32 1
 ; CHECK-NEXT:    ret i32 [[T3]]
 ;
   %t = and i32 %arg, 2
   %t1 = icmp eq i32 %t, 0
-  %t2 = and i32 %arg, 2 ; 2 instead of 1
+  %t2 = and i32 %arg, 3 ; 3 instead of 2
   %t3 = select i1 %t1, i32 %t2, i32 1
   ret i32 %t3
 }
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index b37e9175b26a5..6f95c379e9f29 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3759,18 +3759,170 @@ exit:
 }
 
 ; Select icmp and/or/xor
+; X|Y==-1?X^Y:-1
+define i32 @src_or_disjoint_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 -1
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp eq i32 %or.disjoint, -1
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 %xor, i32 -1
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_comm(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_comm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 -1
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp eq i32 %or.disjoint, -1
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 %xor, i32 -1
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 -1
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp ne i32 %or.disjoint, -1
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 -1, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_ne_comm(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne_comm(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 -1
+;
+entry:
+  %or.disjoint = or disjoint i32 %y, %x
+  %cmp = icmp ne i32 %or.disjoint, -1
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 -1, i32 %xor
+  ret i32 %cond
+}
+
+define <2 x i8> @src_or_disjoint_xor_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_vec(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+entry:
+  %or.disjoint = or disjoint <2 x i8> %x, %y
+  %cmp = icmp eq <2 x i8> %or.disjoint, <i8 -1, i8 -1>
+  %xor = xor <2 x i8> %x, %y
+  %cond = select <2 x i1> %cmp, <2 x i8> %xor, <2 x i8> <i8 -1, i8 -1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_disjoint_xor_comm_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_comm_vec(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+entry:
+  %or.disjoint = or disjoint <2 x i8> %x, %y
+  %cmp = icmp eq <2 x i8> %or.disjoint, <i8 -1, i8 -1>
+  %xor = xor <2 x i8> %x, %y
+  %cond = select <2 x i1> %cmp, <2 x i8> %xor, <2 x i8> <i8 -1, i8 -1>
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_disjoint_xor_ne_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne_vec(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+entry:
+  %or.disjoint = or disjoint <2 x i8> %x, %y
+  %cmp = icmp ne <2 x i8> %or.disjoint, <i8 -1, i8 -1>
+  %xor = xor <2 x i8> %x, %y
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 -1, i8 -1>, <2 x i8> %xor
+  ret <2 x i8> %cond
+}
+
+define <2 x i8> @src_or_disjoint_xor_ne_comm_vec(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne_comm_vec(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret <2 x i8> <i8 -1, i8 -1>
+;
+entry:
+  %or.disjoint = or disjoint <2 x i8> %y, %x
+  %cmp = icmp ne <2 x i8> %or.disjoint, <i8 -1, i8 -1>
+  %xor = xor <2 x i8> %y, %x
+  %cond = select <2 x i1> %cmp, <2 x i8> <i8 -1, i8 -1>, <2 x i8> %xor
+  ret <2 x i8> %cond
+}
+
+define i32 @src_or_disjoint_xor_poison(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_poison(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp eq i32 %or.disjoint, poison
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 %xor, i32 poison
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_comm_poison(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_comm_poison(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp eq i32 %or.disjoint, poison
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 %xor, i32 poison
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_ne_poison(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne_poison(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %or.disjoint = or disjoint i32 %x, %y
+  %cmp = icmp ne i32 %or.disjoint, poison
+  %xor = xor i32 %x, %y
+  %cond = select i1 %cmp, i32 poison, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_or_disjoint_xor_ne_comm_poison(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_disjoint_xor_ne_comm_poison(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %or.disjoint = or disjoint i32 %y, %x
+  %cmp = icmp ne i32 %or.disjoint, poison
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 poison, i32 %xor
+  ret i32 %cond
+}
+
 ; https://alive2.llvm.org/ce/z/QXQDwF
 ; X&Y==C?X|Y:X^Y, X&Y==C?X^Y:X|Y
-; TODO: X&Y==0 could imply no_common_bit to TrueValue
 define i32 @src_and_eq_0_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_0_or_xor(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[XOR]]
 ;
 entry:
   %and = and i32 %y, %x
@@ -3781,16 +3933,24 @@ entry:
   ret i32 %cond
 }
 
-; TODO: X&Y==0 could imply no_common_bit to TrueValue
+define i32 @src_and_ne_0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_0_xor_or(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[XOR]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, 0
+  %or = or i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
 define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_0_xor_or(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
 entry:
   %and = and i32 %y, %x
@@ -3801,15 +3961,26 @@ entry:
   ret i32 %cond
 }
 
-; TODO: X&Y==-1 could imply all_common_bit to TrueValue
+define i32 @src_and_ne_0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_0_or_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, 0
+  %xor = xor i32 %y, %x
+  %or = or i32 %y, %x
+  %cond = select i1 %cmp, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
 define i32 @src_and_eq_neg1_or_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_neg1_or_xor(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y]], [[X]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3821,15 +3992,29 @@ entry:
   ret i32 %cond
 }
 
-; TODO: X&Y==-1 could imply all_common_bit to TrueValue
+define i32 @src_and_ne_neg1_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_neg1_xor_or(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], -1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 -1, i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, -1
+  %or = or i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
 define i32 @src_and_eq_neg1_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_and_eq_neg1_xor_or(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], -1
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[OR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3841,6 +4026,22 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_and_ne_neg1_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_and_ne_neg1_or_xor(
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and = and i32 %y, %x
+  %cmp = icmp ne i32 %and, -1
+  %xor = xor i32 %y, %x
+  %or = or i32 %y, %x
+  %cond = select i1 %cmp, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
 define i32 @src_and_eq_C_or_xororC(i32 %x, i32 %y, i32 %c) {
 ; CHECK-LABEL: @src_and_eq_C_or_xororC(
 ; CHECK-NEXT:  entry:
@@ -3936,15 +4137,13 @@ entry:
 
 ; https://alive2.llvm.org/ce/z/9RPwfN
 ; X|Y==C?X&Y:X^Y, X|Y==C?X^Y:X&Y
-; TODO: X|Y==0 could imply no_common_bit to TrueValue
 define i32 @src_or_eq_0_and_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_eq_0_and_xor(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], [[X]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[XOR]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3956,15 +4155,29 @@ entry:
   ret i32 %cond
 }
 
-; TODO: X|Y==0 could imply no_common_bit to TrueValue
+define i32 @src_or_ne_0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_ne_0_xor_and(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %y, %x
+  %cmp = icmp ne i32 %or, 0
+  %and = and i32 %y, %x
+  %xor = xor i32 %y, %x
+  %cond = select i1 %cmp, i32 %xor, i32 %and
+  ret i32 %cond
+}
+
 define i32 @src_or_eq_0_xor_and(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_eq_0_xor_and(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 0, i32 [[AND]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
 entry:
@@ -3976,6 +4189,22 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_or_ne_0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_or_ne_0_and_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP_NOT]], i32 0, i32 [[AND]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %y, %x
+  %cmp = icmp ne i32 %or, 0
+  %xor = xor i32 %y, %x
+  %and = and i32 %y, %x
+  %cond = select i1 %cmp, i32 %and, i32 %xor
+  ret i32 %cond
+}
+
 define i32 @src_or_eq_neg1_and_xor(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_or_eq_neg1_and_xor(
 ; CHECK-NEXT:  entry:
@@ -4189,6 +4418,172 @@ entry:
   ret i32 %cond
 }
 
+define i32 @src_select_or_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_eq0_or_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OR0:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp eq i32 %or, 0
+  %xor = xor i32 %x, %y
+  %cond = select i1 %or0, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_select_or_ne0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_ne0_xor_or(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[OR0_NOT:%.*]] = icmp eq i32 [[OR]], 0
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0_NOT]], i32 0, i32 [[XOR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp ne i32 %or, 0
+  %xor = xor i32 %x, %y
+  %cond = select i1 %or0, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_or_eq0_and_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_eq0_and_or(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp eq i32 %or, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %or0, i32 %and, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_or_ne0_or_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_ne0_or_and(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp ne i32 %or, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %or0, i32 %or, i32 %and
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_eq0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_eq0_and_xor(
+; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp eq i32 %xor, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %xor0, i32 %and, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_ne0_xor_and(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_ne0_xor_and(
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, 0
+  %and = and i32 %x, %y
+  %cond = select i1 %xor0, i32 %xor, i32 %and
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_eq0_or_xor(
+; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp eq i32 %xor, 0
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_ne0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_ne0_xor_or(
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, 0
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_or_eq0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_eq0_xor_or(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp eq i32 %or, 0
+  %xor = xor i32 %x, %y
+  %cond = select i1 %or0, i32 %xor, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_or_ne0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_or_ne0_or_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %or = or i32 %x, %y
+  %or0 = icmp ne i32 %or, 0
+  %xor = xor i32 %x, %y
+  %cond = select i1 %or0, i32 %or, i32 %xor
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_max_negative_int(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp eq i32 %xor, -1
+  %and = and i32 %x, %y
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %and, i32 %or
+  ret i32 %cond
+}
+
+define i32 @src_select_xor_max_negative_int_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_select_xor_max_negative_int_ne(
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR0_NOT:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0_NOT]], i32 0, i32 [[OR]]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %xor = xor i32 %x, %y
+  %xor0 = icmp ne i32 %xor, -1
+  %and = and i32 %x, %y
+  %or = or i32 %x, %y
+  %cond = select i1 %xor0, i32 %or, i32 %and
+  ret i32 %cond
+}
+
 ; Select icmp and/or/xor
 ; NO TRANSFORMED - select condition is compare with not 0
 define i32 @src_select_and_min_positive_int(i32 %x, i32 %y) {
@@ -4361,23 +4756,6 @@ define i32 @src_select_xor_min_negative_int(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-define i32 @src_select_xor_max_negative_int(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_select_xor_max_negative_int(
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[XOR]], -1
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-  %xor = xor i32 %x, %y
-  %xor0 = icmp eq i32 %xor, -1
-  %and = and i32 %x, %y
-  %or = or i32 %x, %y
-  %cond = select i1 %xor0, i32 %and, i32 %or
-  ret i32 %cond
-}
-
 ; Select icmp and/or/xor
 ; https://alive2.llvm.org/ce/z/BVgrJ-
 ; NO TRANSFORMED - not supported
@@ -4456,51 +4834,6 @@ define i32 @src_no_trans_select_or_eq0_or_and(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-define i32 @src_no_trans_select_or_eq0_or_xor(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_or_eq0_or_xor(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0]], i32 0, i32 [[XOR]]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-  %or = or i32 %x, %y
-  %or0 = icmp eq i32 %or, 0
-  %xor = xor i32 %x, %y
-  %cond = select i1 %or0, i32 %or, i32 %xor
-  ret i32 %cond
-}
-
-define i32 @src_no_trans_select_or_eq0_and_or(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_or_eq0_and_or(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0]], i32 [[AND]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-  %or = or i32 %x, %y
-  %or0 = icmp eq i32 %or, 0
-  %and = and i32 %x, %y
-  %cond = select i1 %or0, i32 %and, i32 %or
-  ret i32 %cond
-}
-
-define i32 @src_no_trans_select_or_eq0_xor_or(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_or_eq0_xor_or(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[OR0:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[OR0]], i32 [[XOR]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
-;
-  %or = or i32 %x, %y
-  %or0 = icmp eq i32 %or, 0
-  %xor = xor i32 %x, %y
-  %cond = select i1 %or0, i32 %xor, i32 %or
-  ret i32 %cond
-}
-
 define i32 @src_no_trans_select_and_ne0_xor_or(i32 %x, i32 %y) {
 ; CHECK-LABEL: @src_no_trans_select_and_ne0_xor_or(
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
@@ -4530,8 +4863,8 @@ define i32 @src_no_trans_select_xor_eq0_xor_and(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_xor_eq0_xor_or(
+define i32 @src_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_trans_select_xor_eq0_xor_or(
 ; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
 ; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 0, i32 [[OR]]
@@ -4544,12 +4877,11 @@ define i32 @src_no_trans_select_xor_eq0_xor_or(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_xor_eq0_and_xor(
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[AND]], i32 [[XOR]]
+define i32 @src_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_trans_select_xor_eq0_and_xor(
+; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y
@@ -4559,13 +4891,11 @@ define i32 @src_no_trans_select_xor_eq0_and_xor(i32 %x, i32 %y) {
   ret i32 %cond
 }
 
-; https://alive2.llvm.org/ce/z/SBe8ei
-define i32 @src_no_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) {
-; CHECK-LABEL: @src_no_trans_select_xor_eq0_or_xor(
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[OR]], i32 [[XOR]]
+define i32 @src_trans_select_xor_eq0_or_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @src_trans_select_xor_eq0_or_xor(
+; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[XOR0]], i32 0, i32 [[Y]]
+; CHECK-NEXT:    [[COND:%.*]] = xor i32 [[XOR]], [[X]]
 ; CHECK-NEXT:    ret i32 [[COND]]
 ;
   %xor = xor i32 %x, %y