Add instruction combining for ((A&~B)|(~A&B)) -> A^B and all permutations.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60291 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index ace3ff8..c79bf9c 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -4638,6 +4638,29 @@
       return Match;
     if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C))
       return Match;
+
+    V1 = V2 = 0;
+
+    // ((A&~B)|(~A&B)) -> A^B
+    if ((match(C, m_Not(m_Value(V1))) &&
+         match(B, m_Not(m_Value(V2)))))
+      if (V1 == D && V2 == A)
+        return BinaryOperator::CreateXor(V1, V2);
+    // ((~B&A)|(~A&B)) -> A^B
+    if ((match(A, m_Not(m_Value(V1))) &&
+         match(B, m_Not(m_Value(V2)))))
+      if (V1 == D && V2 == C)
+        return BinaryOperator::CreateXor(V1, V2);
+    // ((A&~B)|(B&~A)) -> A^B
+    if ((match(C, m_Not(m_Value(V1))) &&
+         match(D, m_Not(m_Value(V2)))))
+      if (V1 == B && V2 == A)
+        return BinaryOperator::CreateXor(V1, V2);
+    // ((~B&A)|(B&~A)) -> A^B
+    if ((match(A, m_Not(m_Value(V1))) &&
+         match(D, m_Not(m_Value(V2)))))
+      if (V1 == B && V2 == C)
+        return BinaryOperator::CreateXor(V1, V2);
   }
   
   // (X >> Z) | (Y >> Z)  -> (X|Y) >> Z  for all shifts.