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")