diff options
author | Dan Gohman <gohman@apple.com> | 2009-08-12 16:33:09 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2009-08-12 16:33:09 +0000 |
commit | fa94b948d9a0aaaad98901815e56b676803ad259 (patch) | |
tree | fe5f5ff724d6bd1e9a39ed0c49b4d4148856e70d | |
parent | 2df6e6467f679984e98612e695682fcc834bd95f (diff) |
Optimize (x/C)*C to x if the division is exact.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78811 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 11 | ||||
-rw-r--r-- | test/Transforms/InstCombine/exact-sdiv.ll | 37 |
2 files changed, 47 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 514e91bdef..669ef2d516 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -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()) { diff --git a/test/Transforms/InstCombine/exact-sdiv.ll b/test/Transforms/InstCombine/exact-sdiv.ll index 9ed524f8ec..8379825406 100644 --- a/test/Transforms/InstCombine/exact-sdiv.ll +++ b/test/Transforms/InstCombine/exact-sdiv.ll @@ -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 +} |