Optimize (x/C)*C to x if the division is exact.
authorDan Gohman <gohman@apple.com>
Wed, 12 Aug 2009 16:33:09 +0000 (16:33 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 12 Aug 2009 16:33:09 +0000 (16:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78811 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/exact-sdiv.ll

index 514e91bdef32d6baea755388b86ba9983b571647..669ef2d5165f36ed8dc307b4d8bfe1dd74120f92 100644 (file)
@@ -2701,6 +2701,15 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
          BO->getOpcode() == Instruction::SDiv)) {
       Value *Op0BO = BO->getOperand(0), *Op1BO = BO->getOperand(1);
 
+      // If the division is exact, X % Y is zero.
+      if (SDivOperator *SDiv = dyn_cast<SDivOperator>(BO))
+        if (SDiv->isExact()) {
+          if (Op1BO == Op1)
+            return ReplaceInstUsesWith(I, Op0BO);
+          else
+            return BinaryOperator::CreateNeg(Op0BO);
+        }
+
       Instruction *Rem;
       if (BO->getOpcode() == Instruction::UDiv)
         Rem = BinaryOperator::CreateURem(Op0BO, Op1BO);
@@ -3060,7 +3069,7 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
     if (RHS->isAllOnesValue())
       return BinaryOperator::CreateNeg(Op0);
 
-    // sdiv X, C  --> ashr X, log2(C)
+    // sdiv X, C  -->  ashr X, log2(C)
     if (cast<SDivOperator>(&I)->isExact() &&
         RHS->getValue().isNonNegative() &&
         RHS->getValue().isPowerOf2()) {
index 9ed524f8ec7ae2b44fc86103779a31dd767accb9..8379825406d80995dcc65aaadc56bc66c8955f60 100644 (file)
@@ -13,3 +13,40 @@ define i32 @bar(i32 %x) {
   %y = sdiv exact i32 %x, 8
   ret i32 %y
 }
+
+; CHECK: i32 @a0
+; CHECK: %y = srem i32 %x, 3
+; CHECK: %z = sub i32 %x, %y
+; CHECK: ret i32 %z
+define i32 @a0(i32 %x) {
+  %y = sdiv i32 %x, 3
+  %z = mul i32 %y, 3
+  ret i32 %z
+}
+
+; CHECK: i32 @b0
+; CHECK: ret i32 %x
+define i32 @b0(i32 %x) {
+  %y = sdiv exact i32 %x, 3
+  %z = mul i32 %y, 3
+  ret i32 %z
+}
+
+; CHECK: i32 @a1
+; CHECK: %y = srem i32 %x, 3
+; CHECK: %z = sub i32 %y, %x
+; CHECK: ret i32 %z
+define i32 @a1(i32 %x) {
+  %y = sdiv i32 %x, 3
+  %z = mul i32 %y, -3
+  ret i32 %z
+}
+
+; CHECK: i32 @b1
+; CHECK: %z = sub i32 0, %x
+; CHECK: ret i32 %z
+define i32 @b1(i32 %x) {
+  %y = sdiv exact i32 %x, 3
+  %z = mul i32 %y, -3
+  ret i32 %z
+}