Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -195,7 +195,20 @@
   KnownBits RHSKnown(IT->getBitWidth());
   computeKnownBits(LHS, LHSKnown, DL, 0, AC, CxtI, DT);
   computeKnownBits(RHS, RHSKnown, DL, 0, AC, CxtI, DT);
-  return (LHSKnown.Zero | RHSKnown.Zero).isAllOnesValue();
+  if ((LHSKnown.Zero | RHSKnown.Zero).isAllOnesValue())
+    return true;
+  // Try to see if both sides are masked by the same mask (inverted on one side)
+  // I.e.  binop (x & m), (y & ~m)
+  Value *A, *B, *C, *D;
+  if (match(LHS, m_And(m_Value(A), m_Value(B))) &&
+      match(RHS, m_And(m_Value(C), m_Value(D)))) {
+    if (match(A, m_Not(m_CombineOr(m_Specific(C), m_Specific(D)))) ||
+        match(B, m_Not(m_CombineOr(m_Specific(C), m_Specific(D)))) ||
+        match(C, m_Not(m_CombineOr(m_Specific(A), m_Specific(B)))) ||
+        match(D, m_Not(m_CombineOr(m_Specific(A), m_Specific(B)))))
+      return true;
+  }
+  return false;
 }
 
 bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI) {
Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2446,6 +2446,10 @@
   if (Value *V = SimplifyBSwap(I, Builder))
     return replaceInstUsesWith(I, V);
 
+  // A^B --> A|B iff A and B have no bits set in common.
+  if (haveNoCommonBitsSet(Op0, Op1, DL, &AC, &I, &DT))
+    return BinaryOperator::CreateOr(Op0, Op1);
+
   // Apply DeMorgan's Law for 'nand' / 'nor' logic with an inverted operand.
   Value *X, *Y;
 
Index: test/Transforms/InstCombine/logical-select.ll
===================================================================
--- test/Transforms/InstCombine/logical-select.ll
+++ test/Transforms/InstCombine/logical-select.ll
@@ -399,11 +399,8 @@
 
 define i1 @bools_multi_uses2(i1 %a, i1 %b, i1 %c) {
 ; CHECK-LABEL: @bools_multi_uses2(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[C:%.*]], true
-; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[NOT]], [[A:%.*]]
-; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[C]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = xor i1 [[AND1]], [[AND2]]
-; CHECK-NEXT:    ret i1 [[ADD]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %not = xor i1 %c, -1
   %and1 = and i1 %not, %a
Index: test/Transforms/InstCombine/masked-merge.ll
===================================================================
--- test/Transforms/InstCombine/masked-merge.ll
+++ test/Transforms/InstCombine/masked-merge.ll
@@ -59,7 +59,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %and = and i32 %x, %m
@@ -74,7 +74,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i32> [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor <2 x i32> [[M]], <i32 -1, i32 -1>
 ; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i32> [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i32> [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or <2 x i32> [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret <2 x i32> [[XOR]]
 ;
   %and = and <2 x i32> %x, %m
@@ -89,7 +89,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 undef, i32 -1>
 ; CHECK-NEXT:    [[AND1:%.*]] = and <3 x i32> [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor <3 x i32> [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or <3 x i32> [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret <3 x i32> [[XOR]]
 ;
   %and = and <3 x i32> %x, %m
@@ -337,7 +337,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %and = and i32 %m, %x ; swapped order
@@ -353,7 +353,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %y = call i32 @gen32()
@@ -369,7 +369,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND1]], [[AND]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND1]], [[AND]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %and = and i32 %x, %m
@@ -386,7 +386,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND]], [[AND1]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %y = call i32 @gen32()
@@ -402,7 +402,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND1]], [[AND]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND1]], [[AND]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %and = and i32 %m, %x ; swapped order
@@ -418,7 +418,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND1]], [[AND]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND1]], [[AND]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %y = call i32 @gen32()
@@ -436,7 +436,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND1]], [[AND]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND1]], [[AND]]
 ; CHECK-NEXT:    ret i32 [[XOR]]
 ;
   %y = call i32 @gen32()
@@ -509,7 +509,7 @@
 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[M]], -1
 ; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[XOR:%.*]] = or i32 [[AND]], [[AND1]]
 ; CHECK-NEXT:    call void @use32(i32 [[AND]])
 ; CHECK-NEXT:    call void @use32(i32 [[NEG]])
 ; CHECK-NEXT:    call void @use32(i32 [[AND1]])