[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