From 8f844490938e53e21040413d48d9eea926a06dcc Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 May 2014 03:03:05 +0000 Subject: [PATCH] Optimize integral reciprocal (udiv 1, x and sdiv 1, x) to not use division. This fires exactly once in a clang bootstrap, but covers a few different results from http://www.cs.utah.edu/~regehr/souper/ git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208750 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 21 ++++++++++++++++++++- test/Transforms/InstCombine/div.ll | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 78689933f49..9996ebc2e74 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -727,7 +727,7 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode()) if (ConstantInt *LHSRHS = dyn_cast(LHS->getOperand(1))) { if (MultiplyOverflows(RHS, LHSRHS, - I.getOpcode()==Instruction::SDiv)) + I.getOpcode() == Instruction::SDiv)) return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0), ConstantExpr::getMul(RHS, LHSRHS)); @@ -743,6 +743,25 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { } } + if (ConstantInt *One = dyn_cast(Op0)) { + if (One->isOne() && !I.getType()->isIntegerTy(1)) { + bool isSigned = I.getOpcode() == Instruction::SDiv; + if (isSigned) { + // If Op1 is 0 then it's undefined behaviour, if Op1 is 1 then the + // result is one, if Op1 is -1 then the result is minus one, otherwise + // it's zero. + Value *Inc = Builder->CreateAdd(Op1, One); + Value *Cmp = Builder->CreateICmpULT( + Inc, ConstantInt::get(I.getType(), 3)); + return SelectInst::Create(Cmp, Op1, ConstantInt::get(I.getType(), 0)); + } else { + // If Op1 is 0 then it's undefined behaviour. If Op1 is 1 then the + // result is one, otherwise it's zero. + return new ZExtInst(Builder->CreateICmpEQ(Op1, One), I.getType()); + } + } + } + // See if we can fold away this div instruction. if (SimplifyDemandedInstructionBits(I)) return &I; diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index 1bf486fa336..9c7ba9b0305 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -156,3 +156,22 @@ define <2 x i64> @test18(<2 x i64> %x) nounwind { ; CHECK-NEXT: sub <2 x i64> zeroinitializer, %x ; CHECK-NEXT: ret <2 x i64> } + +define i32 @test19(i32 %x) { + %A = udiv i32 1, %x + ret i32 %A +; CHECK-LABEL: @test19( +; CHECK-NEXT: icmp eq i32 %x, 1 +; CHECK-NEXT: zext i1 %{{.*}} to i32 +; CHECK-NEXT ret i32 +} + +define i32 @test20(i32 %x) { + %A = sdiv i32 1, %x + ret i32 %A +; CHECK-LABEL: @test20( +; CHECK-NEXT: add i32 %x, 1 +; CHECK-NEXT: icmp ult i32 %{{.*}}, 3 +; CHECK-NEXT: select i1 %{{.*}}, i32 %x, i32 {{.*}} +; CHECK-NEXT: ret i32 +} -- 2.11.0