[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner sabre at nondot.org
Sun Mar 18 15:51:51 PDT 2007



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.661 -> 1.662
---
Log message:

Implement InstCombine/and-xor-merge.ll:test[12].
Rearrange some code to simplify it now that shifts are binops


---
Diffs of the changes:  (+95 -53)

 InstructionCombining.cpp |  148 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 95 insertions(+), 53 deletions(-)


Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.661 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.662
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.661	Wed Mar 14 04:07:33 2007
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sun Mar 18 17:51:34 2007
@@ -12,10 +12,10 @@
 // simplification happens.
 //
 // This pass combines things like:
-//    %Y = add int %X, 1
-//    %Z = add int %Y, 1
+//    %Y = add i32 %X, 1
+//    %Z = add i32 %Y, 1
 // into:
-//    %Z = add int %X, 2
+//    %Z = add i32 %X, 2
 //
 // This is a simple worklist driven algorithm.
 //
@@ -4789,58 +4789,115 @@
 
   if (Value *X = dyn_castNotVal(Op1))   // A ^ ~A == -1
     if (X == Op0)
-      return ReplaceInstUsesWith(I,
-                                ConstantInt::getAllOnesValue(I.getType()));
+      return ReplaceInstUsesWith(I, ConstantInt::getAllOnesValue(I.getType()));
 
-  if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1))
-    if (Op1I->getOpcode() == Instruction::Or) {
-      if (Op1I->getOperand(0) == Op0) {              // B^(B|A) == (A|B)^B
+  
+  BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1);
+  if (Op1I) {
+    Value *A, *B;
+    if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) {
+      if (A == Op0) {              // B^(B|A) == (A|B)^B
         Op1I->swapOperands();
         I.swapOperands();
         std::swap(Op0, Op1);
-      } else if (Op1I->getOperand(1) == Op0) {       // B^(A|B) == (A|B)^B
+      } else if (B == Op0) {       // B^(A|B) == (A|B)^B
         I.swapOperands();     // Simplified below.
         std::swap(Op0, Op1);
       }
-    } else if (Op1I->getOpcode() == Instruction::Xor) {
-      if (Op0 == Op1I->getOperand(0))                        // A^(A^B) == B
-        return ReplaceInstUsesWith(I, Op1I->getOperand(1));
-      else if (Op0 == Op1I->getOperand(1))                   // A^(B^A) == B
-        return ReplaceInstUsesWith(I, Op1I->getOperand(0));
-    } else if (Op1I->getOpcode() == Instruction::And && Op1I->hasOneUse()) {
-      if (Op1I->getOperand(0) == Op0)                      // A^(A&B) -> A^(B&A)
+    } else if (match(Op1I, m_Xor(m_Value(A), m_Value(B)))) {
+      if (Op0 == A)                                          // A^(A^B) == B
+        return ReplaceInstUsesWith(I, B);
+      else if (Op0 == B)                                     // A^(B^A) == B
+        return ReplaceInstUsesWith(I, A);
+    } else if (match(Op1I, m_And(m_Value(A), m_Value(B))) && Op1I->hasOneUse()){
+      if (A == Op0)                                        // A^(A&B) -> A^(B&A)
         Op1I->swapOperands();
-      if (Op0 == Op1I->getOperand(1)) {                    // A^(B&A) -> (B&A)^A
+      if (B == Op0) {                                      // A^(B&A) -> (B&A)^A
         I.swapOperands();     // Simplified below.
         std::swap(Op0, Op1);
       }
     }
-
-  if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0))
-    if (Op0I->getOpcode() == Instruction::Or && Op0I->hasOneUse()) {
-      if (Op0I->getOperand(0) == Op1)                // (B|A)^B == (A|B)^B
-        Op0I->swapOperands();
-      if (Op0I->getOperand(1) == Op1) {              // (A|B)^B == A & ~B
-        Instruction *NotB = BinaryOperator::createNot(Op1, "tmp");
-        InsertNewInstBefore(NotB, I);
-        return BinaryOperator::createAnd(Op0I->getOperand(0), NotB);
+  }
+  
+  BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0);
+  if (Op0I) {
+    Value *A, *B;
+    if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && Op0I->hasOneUse()) {
+      if (A == Op1)                                  // (B|A)^B == (A|B)^B
+        std::swap(A, B);
+      if (B == Op1) {                                // (A|B)^B == A & ~B
+        Instruction *NotB =
+          InsertNewInstBefore(BinaryOperator::createNot(Op1, "tmp"), I);
+        return BinaryOperator::createAnd(A, NotB);
       }
-    } else if (Op0I->getOpcode() == Instruction::Xor) {
-      if (Op1 == Op0I->getOperand(0))                        // (A^B)^A == B
-        return ReplaceInstUsesWith(I, Op0I->getOperand(1));
-      else if (Op1 == Op0I->getOperand(1))                   // (B^A)^A == B
-        return ReplaceInstUsesWith(I, Op0I->getOperand(0));
-    } else if (Op0I->getOpcode() == Instruction::And && Op0I->hasOneUse()) {
-      if (Op0I->getOperand(0) == Op1)                      // (A&B)^A -> (B&A)^A
-        Op0I->swapOperands();
-      if (Op0I->getOperand(1) == Op1 &&                    // (B&A)^A == ~B & A
+    } else if (match(Op0I, m_Xor(m_Value(A), m_Value(B)))) {
+      if (Op1 == A)                                          // (A^B)^A == B
+        return ReplaceInstUsesWith(I, B);
+      else if (Op1 == B)                                     // (B^A)^A == B
+        return ReplaceInstUsesWith(I, A);
+    } else if (match(Op0I, m_And(m_Value(A), m_Value(B))) && Op0I->hasOneUse()){
+      if (A == Op1)                                        // (A&B)^A -> (B&A)^A
+        std::swap(A, B);
+      if (B == Op1 &&                                      // (B&A)^A == ~B & A
           !isa<ConstantInt>(Op1)) {  // Canonical form is (B&C)^C
-        Instruction *N = BinaryOperator::createNot(Op0I->getOperand(0), "tmp");
-        InsertNewInstBefore(N, I);
+        Instruction *N =
+          InsertNewInstBefore(BinaryOperator::createNot(A, "tmp"), I);
         return BinaryOperator::createAnd(N, Op1);
       }
     }
-
+  }
+  
+  // (X >> Z) ^ (Y >> Z)  -> (X^Y) >> Z  for all shifts.
+  if (Op0I && Op1I && Op0I->isShift() && 
+      Op0I->getOpcode() == Op1I->getOpcode() && 
+      Op0I->getOperand(1) == Op1I->getOperand(1) &&
+      (Op1I->hasOneUse() || Op1I->hasOneUse())) {
+    Instruction *NewOp =
+      InsertNewInstBefore(BinaryOperator::createXor(Op0I->getOperand(0),
+                                                    Op1I->getOperand(0),
+                                                    Op0I->getName()), I);
+    return BinaryOperator::create(Op1I->getOpcode(), NewOp, 
+                                  Op1I->getOperand(1));
+  }
+    
+  if (Op0I && Op1I) {
+    Value *A, *B, *C, *D;
+    // (A & B)^(A | B) -> A ^ B
+    if (match(Op0I, m_And(m_Value(A), m_Value(B))) &&
+        match(Op1I, m_Or(m_Value(C), m_Value(D)))) {
+      if ((A == C && B == D) || (A == D && B == C)) 
+        return BinaryOperator::createXor(A, B);
+    }
+    // (A | B)^(A & B) -> A ^ B
+    if (match(Op0I, m_Or(m_Value(A), m_Value(B))) &&
+        match(Op1I, m_And(m_Value(C), m_Value(D)))) {
+      if ((A == C && B == D) || (A == D && B == C)) 
+        return BinaryOperator::createXor(A, B);
+    }
+    
+    // (A & B)^(C & D)
+    if ((Op0I->hasOneUse() || Op1I->hasOneUse()) &&
+        match(Op0I, m_And(m_Value(A), m_Value(B))) &&
+        match(Op1I, m_And(m_Value(C), m_Value(D)))) {
+      // (X & Y)^(X & Y) -> (Y^Z) & X
+      Value *X = 0, *Y = 0, *Z = 0;
+      if (A == C)
+        X = A, Y = B, Z = D;
+      else if (A == D)
+        X = A, Y = B, Z = C;
+      else if (B == C)
+        X = B, Y = A, Z = D;
+      else if (B == D)
+        X = B, Y = A, Z = C;
+      
+      if (X) {
+        Instruction *NewOp =
+        InsertNewInstBefore(BinaryOperator::createXor(Y, Z, Op0->getName()), I);
+        return BinaryOperator::createAnd(NewOp, X);
+      }
+    }
+  }
+    
   // (icmp1 A, B) ^ (icmp2 A, B) --> (icmp3 A, B)
   if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
     if (Instruction *R = AssociativeOpt(I, FoldICmpLogical(*this, RHS)))
@@ -4865,21 +4922,6 @@
         }
       }
 
-  // (X >> Z) ^ (Y >> Z)  -> (X^Y) >> Z  for all shifts.
-  if (BinaryOperator *SI1 = dyn_cast<BinaryOperator>(Op1)) {
-    if (BinaryOperator *SI0 = dyn_cast<BinaryOperator>(Op0))
-      if (SI0->isShift() && SI0->getOpcode() == SI1->getOpcode() && 
-          SI0->getOperand(1) == SI1->getOperand(1) &&
-          (SI0->hasOneUse() || SI1->hasOneUse())) {
-        Instruction *NewOp =
-        InsertNewInstBefore(BinaryOperator::createXor(SI0->getOperand(0),
-                                                      SI1->getOperand(0),
-                                                      SI0->getName()), I);
-        return BinaryOperator::create(SI1->getOpcode(), NewOp, 
-                                      SI1->getOperand(1));
-      }
-  }
-    
   return Changed ? &I : 0;
 }
 






More information about the llvm-commits mailing list