From a7cee55762c6564de9dfc90985fe5c14cad7f9ee Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 24 Feb 2021 16:12:48 -0500 Subject: [PATCH] [InstCombine] fold fdiv with powi divisor (PR49147) This extends b40fde062c for the especially non-standard powi pattern. We want to avoid being completely wrong on the negation-of-int-min corner case, so I'm adding an extra FMF check for 'ninf' assuming that gives us the flexibility to handle that possibility. https://llvm.org/PR49147 --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 11 +++++++++++ llvm/test/Transforms/InstCombine/fdiv.ll | 11 ++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 5cfa9223fc36..e164a6122b70 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1294,6 +1294,17 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I, Args.push_back(II->getArgOperand(0)); Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(1), &I)); break; + case Intrinsic::powi: + // Require 'ninf' assuming that makes powi(X, -INT_MIN) acceptable. + // That is, X ** (huge negative number) is 0.0, ~1.0, or INF and so + // dividing by that is INF, ~1.0, or 0.0. Code that uses powi allows + // non-standard results, so this corner case should be acceptable if the + // code rules out INF values. + if (!I.hasNoInfs()) + return nullptr; + Args.push_back(II->getArgOperand(0)); + Args.push_back(Builder.CreateNeg(II->getArgOperand(1))); + break; case Intrinsic::exp: case Intrinsic::exp2: Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(0), &I)); diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll index 0028bf60b842..ff4fa2bf8ff4 100644 --- a/llvm/test/Transforms/InstCombine/fdiv.ll +++ b/llvm/test/Transforms/InstCombine/fdiv.ll @@ -865,8 +865,9 @@ define <2 x half> @exp2_recip(<2 x half> %x, <2 x half> %y) { define float @powi_divisor(float %x, i32 %y, float %z) { ; CHECK-LABEL: @powi_divisor( -; CHECK-NEXT: [[P:%.*]] = call float @llvm.powi.f32(float [[X:%.*]], i32 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fdiv reassoc ninf arcp float [[Z:%.*]], [[P]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc ninf arcp float @llvm.powi.f32(float [[X:%.*]], i32 [[TMP1]]) +; CHECK-NEXT: [[R:%.*]] = fmul reassoc ninf arcp float [[TMP2]], [[Z:%.*]] ; CHECK-NEXT: ret float [[R]] ; %p = call float @llvm.powi.f32(float %x, i32 %y) @@ -919,9 +920,9 @@ define float @powi_divisor_not_enough_fmf2(float %x, i32 %y, float %z) { define <2 x half> @powi_recip(<2 x half> %x, i32 %y) { ; CHECK-LABEL: @powi_recip( -; CHECK-NEXT: [[P:%.*]] = call <2 x half> @llvm.powi.v2f16(<2 x half> [[X:%.*]], i32 [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nnan ninf arcp <2 x half> , [[P]] -; CHECK-NEXT: ret <2 x half> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc nnan ninf arcp <2 x half> @llvm.powi.v2f16(<2 x half> [[X:%.*]], i32 [[TMP1]]) +; CHECK-NEXT: ret <2 x half> [[TMP2]] ; %p = call <2 x half> @llvm.powi.v2f16(<2 x half> %x, i32 %y) %r = fdiv reassoc arcp nnan ninf <2 x half> , %p