From fa94b948d9a0aaaad98901815e56b676803ad259 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 12 Aug 2009 16:33:09 +0000 Subject: [PATCH] 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 --- .../Scalar/InstructionCombining.cpp | 11 +++++- test/Transforms/InstCombine/exact-sdiv.ll | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 514e91bdef3..669ef2d5165 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(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(&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 9ed524f8ec7..8379825406d 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 +} -- 2.34.1