Move some those Xor simplifications which don't require creating new
authorDuncan Sands <baldrick@free.fr>
Wed, 17 Nov 2010 18:52:15 +0000 (18:52 +0000)
committerDuncan Sands <baldrick@free.fr>
Wed, 17 Nov 2010 18:52:15 +0000 (18:52 +0000)
instructions out of InstCombine and into InstructionSimplify.  While
there, introduce an m_AllOnes pattern to simplify matching with integers
and vectors with all bits equal to one.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119536 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/InstructionSimplify.h
include/llvm/Support/PatternMatch.h
lib/Analysis/InstructionSimplify.cpp
lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

index 965e71be4110f8b3fe8db18c17f2a487dd02a8b4..f88fc46c3113b10d9f4ee59a48d36ff5a0052607 100644 (file)
@@ -37,6 +37,11 @@ namespace llvm {
   Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
                         const DominatorTree *DT = 0);
 
+  /// SimplifyXorInst - Given operands for a Xor, see if we can
+  /// fold the result.  If not, this returns null.
+  Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
+                         const DominatorTree *DT = 0);
+
   /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
   /// fold the result.  If not, this returns null.
   Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
index bee676863780e107257ada795b0a2dcc4a4a2a8a..8b5812141df91c48d2fb825660f4cb42f2876608 100644 (file)
@@ -96,9 +96,23 @@ struct one_ty {
   }
 };
 
-/// m_One() - Match a an integer 1.
+/// m_One() - Match an integer 1.
 inline one_ty m_One() { return one_ty(); }
   
+struct all_ones_ty {
+  template<typename ITy>
+  bool match(ITy *V) {
+    if (const ConstantInt *C = dyn_cast<ConstantInt>(V))
+      return C->isAllOnesValue();
+    if (const ConstantVector *C = dyn_cast<ConstantVector>(V))
+      return C->isAllOnesValue();
+    return false;
+  }
+};
+
+/// m_AllOnes() - Match an integer or vector with all bits set to true.
+inline all_ones_ty m_AllOnes() { return all_ones_ty(); }
+
 
 template<typename Class>
 struct bind_ty {
index 5ad842b38f131697881acc6c638b262a7ce2d5f9..7848d5086657c4838f4a81e1c91b44eb62eb056e 100644 (file)
@@ -276,23 +276,13 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
   if (Op0 == Op1)
     return Op0;
 
-  // X & <0,0> = <0,0>
-  if (isa<ConstantAggregateZero>(Op1))
+  // X & 0 = 0
+  if (match(Op1, m_Zero()))
     return Op1;
 
-  // X & <-1,-1> = X
-  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
-    if (CP->isAllOnesValue())
-      return Op0;
-
-  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
-    // X & 0 = 0
-    if (Op1CI->isZero())
-      return Op1CI;
-    // X & -1 = X
-    if (Op1CI->isAllOnesValue())
-      return Op0;
-  }
+  // X & -1 = X
+  if (match(Op1, m_AllOnes()))
+    return Op0;
 
   // A & ~A  =  ~A & A  =  0
   Value *A, *B;
@@ -365,23 +355,13 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
   if (Op0 == Op1)
     return Op0;
 
-  // X | <0,0> = X
-  if (isa<ConstantAggregateZero>(Op1))
+  // X | 0 = X
+  if (match(Op1, m_Zero()))
     return Op0;
 
-  // X | <-1,-1> = <-1,-1>
-  if (ConstantVector *CP = dyn_cast<ConstantVector>(Op1))
-    if (CP->isAllOnesValue())
-      return Op1;
-
-  if (ConstantInt *Op1CI = dyn_cast<ConstantInt>(Op1)) {
-    // X | 0 = X
-    if (Op1CI->isZero())
-      return Op0;
-    // X | -1 = -1
-    if (Op1CI->isAllOnesValue())
-      return Op1CI;
-  }
+  // X | -1 = -1
+  if (match(Op1, m_AllOnes()))
+    return Op1;
 
   // A | ~A  =  ~A | A  =  -1
   Value *A, *B;
@@ -431,6 +411,71 @@ Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
   return ::SimplifyOrInst(Op0, Op1, TD, DT, RecursionLimit);
 }
 
+/// SimplifyXorInst - Given operands for a Xor, see if we can
+/// fold the result.  If not, this returns null.
+static Value *SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD,
+                              const DominatorTree *DT, unsigned MaxRecurse) {
+  if (Constant *CLHS = dyn_cast<Constant>(Op0)) {
+    if (Constant *CRHS = dyn_cast<Constant>(Op1)) {
+      Constant *Ops[] = { CLHS, CRHS };
+      return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(),
+                                      Ops, 2, TD);
+    }
+
+    // Canonicalize the constant to the RHS.
+    std::swap(Op0, Op1);
+  }
+
+  // A ^ undef -> undef
+  if (isa<UndefValue>(Op1))
+    return UndefValue::get(Op0->getType());
+
+  // A ^ 0 = A
+  if (match(Op1, m_Zero()))
+    return Op0;
+
+  // A ^ A = 0
+  if (Op0 == Op1)
+    return Constant::getNullValue(Op0->getType());
+
+  // A ^ ~A  =  ~A ^ A  =  -1
+  Value *A, *B;
+  if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
+      (match(Op1, m_Not(m_Value(A))) && A == Op0))
+    return Constant::getAllOnesValue(Op0->getType());
+
+  // (A ^ B) ^ A = B
+  if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
+      (A == Op1 || B == Op1))
+    return A == Op1 ? B : A;
+
+  // A ^ (A ^ B) = B
+  if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
+      (A == Op0 || B == Op0))
+    return A == Op0 ? B : A;
+
+  // If the operation is with the result of a select instruction, check whether
+  // operating on either branch of the select always yields the same value.
+  if (MaxRecurse && (isa<SelectInst>(Op0) || isa<SelectInst>(Op1)))
+    if (Value *V = ThreadBinOpOverSelect(Instruction::Xor, Op0, Op1, TD, DT,
+                                         MaxRecurse-1))
+      return V;
+
+  // If the operation is with the result of a phi instruction, check whether
+  // operating on all incoming values of the phi always yields the same value.
+  if (MaxRecurse && (isa<PHINode>(Op0) || isa<PHINode>(Op1)))
+    if (Value *V = ThreadBinOpOverPHI(Instruction::Xor, Op0, Op1, TD, DT,
+                                      MaxRecurse-1))
+      return V;
+
+  return 0;
+}
+
+Value *llvm::SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD,
+                             const DominatorTree *DT) {
+  return ::SimplifyXorInst(Op0, Op1, TD, DT, RecursionLimit);
+}
+
 static const Type *GetCompareTy(Value *Op) {
   return CmpInst::makeCmpResultType(Op->getType());
 }
@@ -774,6 +819,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
   case Instruction::Or:
     Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, DT);
     break;
+  case Instruction::Xor:
+    Result = SimplifyXorInst(I->getOperand(0), I->getOperand(1), TD, DT);
+    break;
   case Instruction::ICmp:
     Result = SimplifyICmpInst(cast<ICmpInst>(I)->getPredicate(),
                               I->getOperand(0), I->getOperand(1), TD, DT);
index 864b47758b2416bc7f8282e92fa9a8469fd9a0c0..a2569be16bd9f647deae0b2aa6e9259b7226b4dc 100644 (file)
@@ -1976,25 +1976,13 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
   bool Changed = SimplifyAssociativeOrCommutative(I);
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
 
-  if (isa<UndefValue>(Op1)) {
-    if (isa<UndefValue>(Op0))
-      // Handle undef ^ undef -> 0 special case. This is a common
-      // idiom (misuse).
-      return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
-    return ReplaceInstUsesWith(I, Op1);  // X ^ undef -> undef
-  }
+  if (Value *V = SimplifyXorInst(Op0, Op1, TD))
+    return ReplaceInstUsesWith(I, V);
 
-  // xor X, X = 0
-  if (Op0 == Op1)
-    return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
-  
   // See if we can simplify any instructions used by the instruction whose sole 
   // purpose is to compute bits we don't care about.
   if (SimplifyDemandedInstructionBits(I))
     return &I;
-  if (I.getType()->isVectorTy())
-    if (isa<ConstantAggregateZero>(Op1))
-      return ReplaceInstUsesWith(I, Op0);  // X ^ <0,0> -> X
 
   // Is this a ~ operation?
   if (Value *NotOp = dyn_castNotVal(&I)) {
@@ -2113,15 +2101,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
         return NV;
   }
 
-  if (Value *X = dyn_castNotVal(Op0))   // ~A ^ A == -1
-    if (X == Op1)
-      return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
-
-  if (Value *X = dyn_castNotVal(Op1))   // A ^ ~A == -1
-    if (X == Op0)
-      return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
-
-  
   BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
   if (Op1I) {
     Value *A, *B;
@@ -2134,10 +2113,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
         I.swapOperands();     // Simplified below.
         std::swap(Op0, Op1);
       }
-    } else if (match(Op1I, m_Xor(m_Specific(Op0), m_Value(B)))) {
-      return ReplaceInstUsesWith(I, B);                      // A^(A^B) == B
-    } else if (match(Op1I, m_Xor(m_Value(A), m_Specific(Op0)))) {
-      return ReplaceInstUsesWith(I, A);                      // A^(B^A) == B
     } else if (match(Op1I, m_And(m_Value(A), m_Value(B))) && 
                Op1I->hasOneUse()){
       if (A == Op0) {                                      // A^(A&B) -> A^(B&A)
@@ -2160,10 +2135,6 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
         std::swap(A, B);
       if (B == Op1)                                  // (A|B)^B == A & ~B
         return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1, "tmp"));
-    } else if (match(Op0I, m_Xor(m_Specific(Op1), m_Value(B)))) {
-      return ReplaceInstUsesWith(I, B);                      // (A^B)^A == B
-    } else if (match(Op0I, m_Xor(m_Value(A), m_Specific(Op1)))) {
-      return ReplaceInstUsesWith(I, A);                      // (B^A)^A == B
     } else if (match(Op0I, m_And(m_Value(A), m_Value(B))) && 
                Op0I->hasOneUse()){
       if (A == Op1)                                        // (A&B)^A -> (B&A)^A