Hi All,

I've re-spun the patch with the changes requested.


This is only done when not honoring signaling NaNs.
This transormation is done at expand time by using
a new optab "xorsign". If the optab is not available
then copysign is expanded as normal.

Bootstrapped on both aarch64-none-linux-gnu and x86_64 with no issues.
Regression done on aarch64-none-linux-gnu and no regressions.

Ok for trunk?

gcc/
2017-07-10  Tamar Christina  <tamar.christ...@arm.com>
            Andrew Pinski <pins...@gmail.com>

        PR middle-end/19706
        * expr.c (is_copysign_call_with_1): New.
        (maybe_expand_mult_copysign): Likewise.
        (expand_expr_real_2): Expand copysign.
        * optabs.def (xorsign_optab): New.

________________________________________
From: Andrew Pinski <pins...@gmail.com>
Sent: Monday, July 10, 2017 12:21:29 AM
To: Tamar Christina
Cc: GCC Patches; nd; l...@redhat.com; i...@airs.com; rguent...@suse.de
Subject: Re: [GCC][PATCH][mid-end] Optimize x * copysign (1.0, y) [Patch (1/2)]

On Mon, Jun 12, 2017 at 12:56 AM, Tamar Christina
<tamar.christ...@arm.com> wrote:
> Hi All,
>
> this patch implements a optimization rewriting
>
> x * copysign (1.0, y) and
> x * copysign (-1.0, y)
>
> to:
>
> x ^ (y & (1 << sign_bit_position))
>
> This is done by creating a special builtin during matching and generate the
> appropriate instructions during expand. This new builtin is called XORSIGN.
>
> The expansion of xorsign depends on if the backend has an appropriate optab
> available. If this is not the case then we use a modified version of the 
> existing
> copysign which does not take the abs value of the first argument as a fall 
> back.
>
> This patch is a revival of a previous patch
> https://gcc.gnu.org/ml/gcc-patches/2015-10/msg00069.html
>
> Bootstrapped on both aarch64-none-linux-gnu and x86_64 with no issues.
> Regression done on aarch64-none-linux-gnu and no regressions.


Note this is also PR 19706.

Thanks,
Andrew

>
> Ok for trunk?
>
> gcc/
> 2017-06-07  Tamar Christina  <tamar.christ...@arm.com>
>
>         * builtins.def (BUILT_IN_XORSIGN, BUILT_IN_XORSIGNF): New.
>         (BUILT_IN_XORSIGNL, BUILT_IN_XORSIGN_FLOAT_NX): Likewise.
>         * match.pd (mult (COPYSIGN:s real_onep @0) @1): New simplifier.
>         (mult (COPYSIGN:s real_mus_onep @0) @1): Likewise.
>         (copysigns @0 (negate @1)): Likewise.
>         * builtins.c (expand_builtin_copysign): Promoted local to argument.
>         (expand_builtin): Added CASE_FLT_FN_FLOATN_NX (BUILT_IN_XORSIGN) and
>         CASE_FLT_FN (BUILT_IN_XORSIGN).
>         (BUILT_IN_COPYSIGN): Updated function call.
>         * optabs.h (expand_copysign): New bool.
>         (expand_xorsign): New.
>         * optabs.def (xorsign_optab): New.
>         * optabs.c (expand_copysign): New parameter.
>         * fortran/f95-lang.c (xorsignl, xorsign, xorsignf): New.
>         * fortran/mathbuiltins.def (XORSIGN): New.
>
> gcc/testsuite/
> 2017-06-07  Tamar Christina  <tamar.christ...@arm.com>
>
>         * gcc.dg/tree-ssa/xorsign.c: New.
>         * gcc.dg/xorsign_exec.c: New.
>         * gcc.dg/vec-xorsign_exec.c: New.
>         * gcc.dg/tree-ssa/reassoc-39.c (f2, f3): Updated constant to 2.
diff --git a/gcc/expr.c b/gcc/expr.c
index 5febf07929d0add0ad0ae1356baef008524f0c7c..0193231bc857bdea3e02b2845e62883e1b5c291b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8182,6 +8182,86 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
   return NULL_RTX;
 }
 
+/* Check to see if the CALL statement is an invocation of copysign
+   with 1. being the first argument.  */
+static bool
+is_copysign_call_with_1 (gimple *call)
+{
+  if (!is_gimple_call (call))
+    return false;
+
+  enum combined_fn code = gimple_call_combined_fn (call);
+
+  if (code == CFN_LAST)
+    return false;
+
+  gcall *c = as_a<gcall*> (call);
+
+  if (builtin_fn_p (code))
+    {
+      switch (as_builtin_fn (code))
+	{
+	CASE_FLT_FN (BUILT_IN_COPYSIGN):
+	CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
+	  return real_onep (gimple_call_arg (c, 0));
+	default:
+	  return false;
+	}
+    }
+
+  if (internal_fn_p (code))
+    {
+      switch (as_internal_fn (code))
+	{
+	case IFN_COPYSIGN:
+	  return real_onep (gimple_call_arg (c, 0));
+	default:
+	  return false;
+	}
+    }
+
+   return false;
+}
+
+/* Try to expand the pattern x * copysign (1, y) into xorsign (x, y).
+   This only happens when the the xorsign optab is defined, if the
+   pattern is not a xorsign pattern or if expension failes NULL_RTX is
+   returned, otherwise the RTX from the optab expansion is returned.  */
+static rtx
+maybe_expand_mult_copysign (tree treeop0, tree treeop1, rtx target)
+{
+  tree type = TREE_TYPE (treeop0);
+  rtx op0, op1;
+
+  if (HONOR_SNANS (type))
+    return NULL_RTX;
+
+  if (TREE_CODE (treeop0) == SSA_NAME && TREE_CODE (treeop1) == SSA_NAME)
+    {
+      gimple *call0 = SSA_NAME_DEF_STMT (treeop0);
+      if (!is_copysign_call_with_1 (call0))
+	{
+	  /* IPA sometimes inlines and then extracts the function again,
+	     resulting in an incorrect order, so check both ways.  */
+	  call0 = SSA_NAME_DEF_STMT (treeop1);
+	  if (!is_copysign_call_with_1 (call0))
+	    return NULL_RTX;
+
+	  treeop1 = treeop0;
+	}
+
+	gcall *c = as_a<gcall*> (call0);
+	treeop0 = gimple_call_arg (c, 1);
+
+	expand_operands (treeop1, treeop0, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+
+	return expand_binop (TYPE_MODE (type), xorsign_optab, op0, op1,
+			     target, 0, OPTAB_DIRECT);
+    }
+
+  return NULL_RTX;
+}
+
 rtx
 expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		    enum expand_modifier modifier)
@@ -8791,6 +8871,10 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
       if (modifier == EXPAND_STACK_PARM)
 	target = 0;
 
+      temp = maybe_expand_mult_copysign (treeop0, treeop1, target);
+      if (temp)
+	return temp;
+
       expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
       return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
 
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 504c655be0210a72e7f0f34cde0131e21ccf8089..507af9ea81c42eba98780ef326c22847fdd2c043 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -253,6 +253,7 @@ OPTAB_D (asin_optab, "asin$a2")
 OPTAB_D (atan2_optab, "atan2$a3")
 OPTAB_D (atan_optab, "atan$a2")
 OPTAB_D (copysign_optab, "copysign$F$a3")
+OPTAB_D (xorsign_optab, "xorsign$F$a3")
 OPTAB_D (cos_optab, "cos$a2")
 OPTAB_D (exp10_optab, "exp10$a2")
 OPTAB_D (exp2_optab, "exp2$a2")

Reply via email to