Add another optimization from PR2330. Also catch some missing cases that are
authorNick Lewycky <nicholas@mxc.ca>
Fri, 11 Jul 2008 07:20:53 +0000 (07:20 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Fri, 11 Jul 2008 07:20:53 +0000 (07:20 +0000)
similar.

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

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/2008-07-10-ICmpBinOp.ll [new file with mode: 0644]

index e65cfacc81e387cce67c45dc54e7ee0c55254f29..727f7bdcd1ea8b087f689e16e2c60428f45c3cfd 100644 (file)
@@ -5480,6 +5480,45 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
         return R;
   }
   
+  // See if it's the same type of instruction on the left and right.
+  if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
+    if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
+      if (Op0I->getOpcode() == Op1I->getOpcode() && Op0I->hasOneUse() &&
+          Op1I->hasOneUse() && Op0I->getOperand(1) == Op1I->getOperand(1) &&
+          I.isEquality()) {
+       switch (Op0I->getOpcode()) {
+        default: break;
+        case Instruction::Add:
+        case Instruction::Sub:
+        case Instruction::Xor:
+          // a+x icmp eq/ne b+x --> a icmp b
+          return new ICmpInst(I.getPredicate(), Op0I->getOperand(0),
+                              Op1I->getOperand(0));
+          break;
+        case Instruction::Mul:
+          if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
+            // a * Cst icmp eq/ne b * Cst --> a & 0x7f icmp b & 0x7f
+            if (!CI->isZero() && !CI->isOne()) {
+              const APInt &AP = CI->getValue();
+              ConstantInt *Mask = ConstantInt::get(
+                                      APInt::getLowBitsSet(AP.getBitWidth(),
+                                                           AP.getBitWidth() -
+                                                      AP.countTrailingZeros()));
+              Instruction *And1 = BinaryOperator::CreateAnd(Op0I->getOperand(0),
+                                                            Mask);
+              Instruction *And2 = BinaryOperator::CreateAnd(Op1I->getOperand(0),
+                                                            Mask);
+              InsertNewInstBefore(And1, I);
+              InsertNewInstBefore(And2, I);
+              return new ICmpInst(I.getPredicate(), And1, And2);
+            }
+          }
+          break;
+        }
+      }
+    }
+  }
+  
   // ~x < ~y --> y < x
   { Value *A, *B;
     if (match(Op0, m_Not(m_Value(A))) &&
diff --git a/test/Transforms/InstCombine/2008-07-10-ICmpBinOp.ll b/test/Transforms/InstCombine/2008-07-10-ICmpBinOp.ll
new file mode 100644 (file)
index 0000000..50533db
--- /dev/null
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep add
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep mul
+; PR2330
+
+define i1 @f(i32 %x, i32 %y) nounwind {
+entry:
+  %A = add i32 %x, 5
+  %B = add i32 %y, 5
+  %C = icmp eq i32 %A, %B
+  ret i1 %C
+}
+
+define i1 @g(i32 %x, i32 %y) nounwind {
+entry:
+  %A = mul i32 %x, 5
+  %B = mul i32 %y, 5
+  %C = icmp eq i32 %A, %B
+  ret i1 %C
+}