[llvm] af0babc - [InstCombine] fold copysign with constant sign argument to (fneg+)fabs

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 2 06:24:02 PST 2019


Author: Sanjay Patel
Date: 2019-12-02T09:23:12-05:00
New Revision: af0babc90a5c35cbecce4cc4a27e0396fe03f588

URL: https://github.com/llvm/llvm-project/commit/af0babc90a5c35cbecce4cc4a27e0396fe03f588
DIFF: https://github.com/llvm/llvm-project/commit/af0babc90a5c35cbecce4cc4a27e0396fe03f588.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/test/Transforms/InstCombine/copysign.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 23ca03ff68b0..536e84b4a35e 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 5d30f346807d..49ca1b87d0de 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


        


More information about the llvm-commits mailing list