[PATCH] D70792: [InstCombine] fold copysign with constant sign argument to (fneg+)fabs

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 27 09:41:33 PST 2019


spatel created this revision.
spatel added reviewers: lebedev.ri, cameron.mcinally, mcberg2017, efriedma, nick.
Herald added subscribers: hiraditya, mcrosier.
Herald added a project: LLVM.

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 I think it's ok to take the unusual step of increasing the number of IR instructions for the negative constant case.


https://reviews.llvm.org/D70792

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


Index: llvm/test/Transforms/InstCombine/copysign.ll
===================================================================
--- llvm/test/Transforms/InstCombine/copysign.ll
+++ llvm/test/Transforms/InstCombine/copysign.ll
@@ -6,8 +6,8 @@
 
 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 <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 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 <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
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2279,6 +2279,21 @@
 
     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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70792.231276.patch
Type: text/x-patch
Size: 3424 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191127/1a8ccd0f/attachment.bin>


More information about the llvm-commits mailing list