diff options
author | Sanjay Patel <spatel@rotateright.com> | 2019-12-02 09:21:59 -0500 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2019-12-02 09:23:12 -0500 |
commit | af0babc90a5c35cbecce4cc4a27e0396fe03f588 (patch) | |
tree | 97887a62c2953761c03e351ae887ceb6fd75eeb5 | |
parent | 62364965619bd7e8847418b21ec327a78bd1624c (diff) | |
download | bcm5719-llvm-af0babc90a5c35cbecce4cc4a27e0396fe03f588.tar.gz bcm5719-llvm-af0babc90a5c35cbecce4cc4a27e0396fe03f588.zip |
[InstCombine] fold copysign with constant sign argument to (fneg+)fabs
If the sign of the sign argument is known (this could be extended to use ValueTracking),
then we can use fneg+fabs to clear/set the sign bit of the magnitude argument.
http://llvm.org/docs/LangRef.html#llvm-copysign-intrinsic
This transform is already done in DAGCombiner, but we can do it sooner in IR as
suggested in PR44153:
https://bugs.llvm.org/show_bug.cgi?id=44153
We have effectively no analysis for copysign in IR, so we are taking the unusual step
of increasing the number of IR instructions for the negative constant case.
Differential Revision: https://reviews.llvm.org/D70792
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 15 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/copysign.ll | 18 |
2 files changed, 25 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 23ca03ff68b..536e84b4a35 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2279,6 +2279,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { break; } + case Intrinsic::copysign: { + const APFloat *C; + if (match(II->getArgOperand(1), m_APFloat(C))) { + // If we know the sign bit of the sign argument, reduce to FABS/FNABS: + // copysign X, PosC --> fabs X + // copysign X, NegC --> fneg (fabs X) + Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, + II->getArgOperand(0), II); + if (C->isNegative()) + Fabs = Builder.CreateFNegFMF(Fabs, II); + + return replaceInstUsesWith(*II, Fabs); + } + break; + } case Intrinsic::fabs: { Value *Cond; Constant *LHS, *RHS; diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll index 5d30f346807..49ca1b87d0d 100644 --- a/llvm/test/Transforms/InstCombine/copysign.ll +++ b/llvm/test/Transforms/InstCombine/copysign.ll @@ -6,8 +6,8 @@ declare <3 x double> @llvm.copysign.v3f64(<3 x double>, <3 x double>) define float @positive_sign_arg(float %x) { ; CHECK-LABEL: @positive_sign_arg( -; CHECK-NEXT: [[R:%.*]] = call arcp float @llvm.copysign.f32(float [[X:%.*]], float 0.000000e+00) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = call arcp float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %r = call arcp float @llvm.copysign.f32(float %x, float 0.0) ret float %r @@ -15,8 +15,8 @@ define float @positive_sign_arg(float %x) { define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) { ; CHECK-LABEL: @positive_sign_arg_vec_splat( -; CHECK-NEXT: [[R:%.*]] = call ninf <3 x double> @llvm.copysign.v3f64(<3 x double> [[X:%.*]], <3 x double> <double 4.200000e+01, double 4.200000e+01, double 4.200000e+01>) -; CHECK-NEXT: ret <3 x double> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = call ninf <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]]) +; CHECK-NEXT: ret <3 x double> [[TMP1]] ; %r = call ninf <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double 42.0, double 42.0, double 42.0>) ret <3 x double> %r @@ -24,8 +24,9 @@ define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) { define float @negative_sign_arg(float %x) { ; CHECK-LABEL: @negative_sign_arg( -; CHECK-NEXT: [[R:%.*]] = call nnan float @llvm.copysign.f32(float [[X:%.*]], float -0.000000e+00) -; CHECK-NEXT: ret float [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = fneg nnan float [[TMP1]] +; CHECK-NEXT: ret float [[TMP2]] ; %r = call nnan float @llvm.copysign.f32(float %x, float -0.0) ret float %r @@ -33,8 +34,9 @@ define float @negative_sign_arg(float %x) { define <3 x double> @negative_sign_arg_vec_splat(<3 x double> %x) { ; CHECK-LABEL: @negative_sign_arg_vec_splat( -; CHECK-NEXT: [[R:%.*]] = call fast <3 x double> @llvm.copysign.v3f64(<3 x double> [[X:%.*]], <3 x double> <double -4.200000e+01, double -4.200000e+01, double -4.200000e+01>) -; CHECK-NEXT: ret <3 x double> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = call fast <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = fneg fast <3 x double> [[TMP1]] +; CHECK-NEXT: ret <3 x double> [[TMP2]] ; %r = call fast <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double -42.0, double -42.0, double -42.0>) ret <3 x double> %r |