From d8dd0151fc12fbbb3f15f71174452c81001a902c Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 20 Feb 2018 23:51:16 +0000 Subject: [PATCH] [InstCombine] -X / C --> X / -C for FP We already do this in DAGCombiner, but it should also be good to eliminate the fsub use in IR. llvm-svn: 325648 --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 17 ++++++++++++----- llvm/test/Transforms/InstCombine/fdiv.ll | 18 ++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index cb42d24..ec62beb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1285,12 +1285,18 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { return nullptr; } -/// Try to convert X/C into X * (1/C). +/// Remove negation and try to convert division into multiplication. static Instruction *foldFDivConstantDivisor(BinaryOperator &I) { Constant *C; if (!match(I.getOperand(1), m_Constant(C))) return nullptr; + // -X / C --> X / -C + Value *X; + if (match(I.getOperand(0), m_FNeg(m_Value(X)))) + return BinaryOperator::CreateWithCopiedFlags(Instruction::FDiv, X, + ConstantExpr::getFNeg(C), &I); + // If the constant divisor has an exact inverse, this is always safe. If not, // then we can still create a reciprocal if fast-math-flags allow it and the // constant is a regular number (not zero, infinite, or denormal). @@ -1305,6 +1311,7 @@ static Instruction *foldFDivConstantDivisor(BinaryOperator &I) { if (!RecipC->isNormalFP()) return nullptr; + // X / C --> X * (1 / C) return BinaryOperator::CreateWithCopiedFlags( Instruction::FMul, I.getOperand(0), RecipC, &I); } @@ -1345,11 +1352,11 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) { SQ.getWithInstruction(&I))) return replaceInstUsesWith(I, V); - if (Instruction *FMul = foldFDivConstantDivisor(I)) - return FMul; + if (Instruction *R = foldFDivConstantDivisor(I)) + return R; - if (Instruction *NewFDiv = foldFDivConstantDividend(I)) - return NewFDiv; + if (Instruction *R = foldFDivConstantDividend(I)) + return R; if (isa(Op0)) if (SelectInst *SI = dyn_cast(Op1)) diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll index 506deaa..a70907e 100644 --- a/llvm/test/Transforms/InstCombine/fdiv.ll +++ b/llvm/test/Transforms/InstCombine/fdiv.ll @@ -215,45 +215,43 @@ define <2 x float> @fneg_fneg_vec(<2 x float> %x, <2 x float> %y) { define float @fneg_dividend_constant_divisor(float %x) { ; CHECK-LABEL: @fneg_dividend_constant_divisor( -; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], 3.000000e+00 +; CHECK-NEXT: [[DIV:%.*]] = fdiv nsz float [[X:%.*]], -3.000000e+00 ; CHECK-NEXT: ret float [[DIV]] ; %neg = fsub float -0.0, %x - %div = fdiv float %neg, 3.0 + %div = fdiv nsz float %neg, 3.0 ret float %div } define float @fneg_divisor_constant_dividend(float %x) { ; CHECK-LABEL: @fneg_divisor_constant_dividend( ; CHECK-NEXT: [[NEG:%.*]] = fsub float -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = fdiv float -3.000000e+00, [[NEG]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float -3.000000e+00, [[NEG]] ; CHECK-NEXT: ret float [[DIV]] ; %neg = fsub float -0.0, %x - %div = fdiv float -3.0, %neg + %div = fdiv nnan float -3.0, %neg ret float %div } define <2 x float> @fneg_dividend_constant_divisor_vec(<2 x float> %x) { ; CHECK-LABEL: @fneg_dividend_constant_divisor_vec( -; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> , [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> [[NEG]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf <2 x float> [[X:%.*]], ; CHECK-NEXT: ret <2 x float> [[DIV]] ; %neg = fsub <2 x float> , %x - %div = fdiv <2 x float> %neg, + %div = fdiv ninf <2 x float> %neg, ret <2 x float> %div } define <2 x float> @fneg_divisor_constant_dividend_vec(<2 x float> %x) { ; CHECK-LABEL: @fneg_divisor_constant_dividend_vec( ; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> , [[X:%.*]] -; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x float> , [[NEG]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv afn <2 x float> , [[NEG]] ; CHECK-NEXT: ret <2 x float> [[DIV]] ; %neg = fsub <2 x float> , %x - %div = fdiv <2 x float> , %neg + %div = fdiv afn <2 x float> , %neg ret <2 x float> %div } -- 2.7.4