[llvm-commits] [llvm] r59800 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/2008-11-20-DivMulRem.ll

Nick Lewycky nicholas at mxc.ca
Thu Nov 20 23:34:01 PST 2008


Author: nicholas
Date: Fri Nov 21 01:33:58 2008
New Revision: 59800

URL: http://llvm.org/viewvc/llvm-project?rev=59800&view=rev
Log:
Optimize (x/y)*y into x-(x%y) in general. Div and rem are about the same, and
a subtract is cheaper than a multiply. This generalizes an existing transform.

Added:
    llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=59800&r1=59799&r2=59800&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Fri Nov 21 01:33:58 2008
@@ -2477,17 +2477,6 @@
         Constant *CP1 = Subtract(ConstantInt::get(I.getType(), 1), C2);
         return BinaryOperator::CreateMul(Op0, CP1);
       }
-
-      // X - ((X / Y) * Y) --> X % Y
-      if (Op1I->getOpcode() == Instruction::Mul)
-        if (Instruction *I = dyn_cast<Instruction>(Op1I->getOperand(0)))
-          if (Op0 == I->getOperand(0) &&
-              Op1I->getOperand(1) == I->getOperand(1)) {
-            if (I->getOpcode() == Instruction::SDiv)
-              return BinaryOperator::CreateSRem(Op0, Op1I->getOperand(1));
-            if (I->getOpcode() == Instruction::UDiv)
-              return BinaryOperator::CreateURem(Op0, Op1I->getOperand(1));
-          }
     }
   }
 
@@ -2622,6 +2611,40 @@
     if (Value *Op1v = dyn_castNegVal(I.getOperand(1)))
       return BinaryOperator::CreateMul(Op0v, Op1v);
 
+  // (X / Y) *  Y = X - (X % Y)
+  // (X / Y) * -Y = (X % Y) - X
+  {
+    Value *Op1 = I.getOperand(1);
+    BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0);
+    if (!BO ||
+        (BO->getOpcode() != Instruction::UDiv && 
+         BO->getOpcode() != Instruction::SDiv)) {
+      Op1 = Op0;
+      BO = dyn_cast<BinaryOperator>(I.getOperand(1));
+    }
+    Value *Neg = dyn_castNegVal(Op1);
+    if (BO && BO->hasOneUse() &&
+        (BO->getOperand(1) == Op1 || BO->getOperand(1) == Neg) &&
+        (BO->getOpcode() == Instruction::UDiv ||
+         BO->getOpcode() == Instruction::SDiv)) {
+      Value *Op0BO = BO->getOperand(0), *Op1BO = BO->getOperand(1);
+
+      Instruction *Rem;
+      if (BO->getOpcode() == Instruction::UDiv)
+        Rem = BinaryOperator::CreateURem(Op0BO, Op1BO);
+      else
+        Rem = BinaryOperator::CreateSRem(Op0BO, Op1BO);
+
+      InsertNewInstBefore(Rem, I);
+      Rem->takeName(BO);
+
+      if (Op1BO == Op1)
+        return BinaryOperator::CreateSub(Op0BO, Rem);
+      else
+        return BinaryOperator::CreateSub(Rem, Op0BO);
+    }
+  }
+
   if (I.getType() == Type::Int1Ty)
     return BinaryOperator::CreateAnd(Op0, I.getOperand(1));
 

Added: llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll?rev=59800&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll Fri Nov 21 01:33:58 2008
@@ -0,0 +1,34 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t
+; RUN: grep urem %t | count 3
+; RUN: grep srem %t | count 1
+; RUN: grep sub %t | count 2
+; RUN: grep add %t | count 1
+; PR3103
+
+define i8 @test1(i8 %x, i8 %y) {
+  %A = udiv i8 %x, %y
+  %B = mul i8 %A, %y
+  %C = sub i8 %x, %B
+  ret i8 %C
+}
+
+define i8 @test2(i8 %x, i8 %y) {
+  %A = sdiv i8 %x, %y
+  %B = mul i8 %A, %y
+  %C = sub i8 %x, %B
+  ret i8 %C
+}
+
+define i8 @test3(i8 %x, i8 %y) {
+  %A = udiv i8 %x, %y
+  %B = mul i8 %A, %y
+  %C = sub i8 %B, %x
+  ret i8 %C
+}
+
+define i8 @test4(i8 %x) {
+  %A = udiv i8 %x, 3
+  %B = mul i8 %A, -3
+  %C = sub i8 %x, %B
+  ret i8 %C
+}





More information about the llvm-commits mailing list