From 0155ad4011c58e3608d88e76d1fa0f628ccedcdb Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Wed, 14 Oct 2015 12:54:03 +0000 Subject: [PATCH] re PR tree-optimization/67815 (Optimize const1 * copysign (const2, y) into copysign (const1 * const2, y) if const1 > 0 or -copysign (const1 * const2, y) if const1 < 0) PR tree-optimization/67815 * tree-ssa-reassoc.c (attempt_builtin_copysign): New function. (reassociate_bb): Call it. * gcc.dg/tree-ssa/reassoc-39.c: New test. * gcc.dg/tree-ssa/reassoc-40.c: New test. * gcc.dg/tree-ssa/reassoc-41.c: New test. From-SVN: r228809 --- gcc/ChangeLog | 6 ++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-39.c | 41 +++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-40.c | 21 +++++++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-41.c | 21 +++++++ gcc/tree-ssa-reassoc.c | 99 ++++++++++++++++++++++++++++++ 6 files changed, 195 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/reassoc-39.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/reassoc-40.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/reassoc-41.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2dcb640..d85a270 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-10-14 Marek Polacek + + PR tree-optimization/67815 + * tree-ssa-reassoc.c (attempt_builtin_copysign): New function. + (reassociate_bb): Call it. + 2015-10-14 Richard Biener * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index da00152..670b9e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-10-14 Marek Polacek + + PR tree-optimization/67815 + * gcc.dg/tree-ssa/reassoc-39.c: New test. + * gcc.dg/tree-ssa/reassoc-40.c: New test. + * gcc.dg/tree-ssa/reassoc-41.c: New test. + 2015-10-14 Dominik Vogt * gcc.dg/pragma-pop_options-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-39.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-39.c new file mode 100644 index 0000000..589d06b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-39.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/67815 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -fdump-tree-reassoc1-details" } */ + +float +f0 (float x) +{ + return 7.5 * __builtin_copysignf (2.0, x); +} + +float +f1 (float x) +{ + return -7.5 * __builtin_copysignf (2.0, x); +} + +double +f2 (double x, double y) +{ + return x * ((1.0/12) * __builtin_copysign (1.0, y)); +} + +double +f3 (double x, double y) +{ + return (x * (-1.0/12)) * __builtin_copysign (1.0, y); +} + +double +f4 (double x, double y, double z) +{ + return (x * z) * ((1.0/12) * __builtin_copysign (4.0, y)); +} + +double +f5 (double x, double y, double z) +{ + return (x * (-1.0/12)) * z * __builtin_copysign (2.0, y); +} + +/* { dg-final { scan-tree-dump-times "Optimizing copysign" 6 "reassoc1"} }*/ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-40.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-40.c new file mode 100644 index 0000000..d65bcc1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-40.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/67815 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -frounding-math -fdump-tree-reassoc1-details" } */ + +/* Test that the copysign reassoc optimization doesn't fire for + -frounding-math (i.e. HONOR_SIGN_DEPENDENT_ROUNDING) if the multiplication + is inexact. */ + +double +f1 (double y) +{ + return (1.2 * __builtin_copysign (1.1, y)); +} + +double +f2 (double y) +{ + return (-1.2 * __builtin_copysign (1.1, y)); +} + +/* { dg-final { scan-tree-dump-not "Optimizing copysign" "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-41.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-41.c new file mode 100644 index 0000000..8a18b88 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-41.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/67815 */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -fno-rounding-math -fdump-tree-reassoc1-details" } */ + +/* Test that the copysign reassoc optimization does fire for + -fno-rounding-math (i.e. HONOR_SIGN_DEPENDENT_ROUNDING) if the multiplication + is inexact. */ + +double +f1 (double y) +{ + return (1.2 * __builtin_copysign (1.1, y)); +} + +double +f2 (double y) +{ + return (-1.2 * __builtin_copysign (1.1, y)); +} + +/* { dg-final { scan-tree-dump-times "Optimizing copysign" 2 "reassoc1"} }*/ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 879722e..62438dd 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -4622,6 +4622,102 @@ attempt_builtin_powi (gimple *stmt, vec *ops) return result; } +/* Attempt to optimize + CST1 * copysign (CST2, y) -> copysign (CST1 * CST2, y) if CST1 > 0, or + CST1 * copysign (CST2, y) -> -copysign (CST1 * CST2, y) if CST1 < 0. */ + +static void +attempt_builtin_copysign (vec *ops) +{ + operand_entry *oe; + unsigned int i; + unsigned int length = ops->length (); + tree cst = ops->last ()->op; + + if (length == 1 || TREE_CODE (cst) != REAL_CST) + return; + + FOR_EACH_VEC_ELT (*ops, i, oe) + { + if (TREE_CODE (oe->op) == SSA_NAME + && has_single_use (oe->op)) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (oe->op); + if (is_gimple_call (def_stmt)) + { + tree fndecl = gimple_call_fndecl (def_stmt); + tree arg0, arg1; + switch (DECL_FUNCTION_CODE (fndecl)) + { + CASE_FLT_FN (BUILT_IN_COPYSIGN): + arg0 = gimple_call_arg (def_stmt, 0); + arg1 = gimple_call_arg (def_stmt, 1); + /* The first argument of copysign must be a constant, + otherwise there's nothing to do. */ + if (TREE_CODE (arg0) == REAL_CST) + { + tree mul = const_binop (MULT_EXPR, TREE_TYPE (cst), + cst, arg0); + /* If we couldn't fold to a single constant, skip it. + That happens e.g. for inexact multiplication when + -frounding-math. */ + if (mul == NULL_TREE) + break; + /* Instead of adjusting the old DEF_STMT, let's build + a new call to not leak the LHS and prevent keeping + bogus debug statements. DCE will clean up the old + call. */ + gcall *call = gimple_build_call (fndecl, 2, mul, arg1); + tree lhs = make_ssa_name (TREE_TYPE (arg0)); + gimple_call_set_lhs (call, lhs); + gimple_set_location (call, gimple_location (def_stmt)); + insert_stmt_after (call, def_stmt); + /* We've used the constant, get rid of it. */ + ops->pop (); + bool cst1_neg = real_isneg (TREE_REAL_CST_PTR (cst)); + /* Handle the CST1 < 0 case by negating the result. */ + if (cst1_neg) + { + tree negrhs = make_ssa_name (TREE_TYPE (lhs)); + gimple *negate_stmt + = gimple_build_assign (negrhs, NEGATE_EXPR, lhs); + insert_stmt_after (negate_stmt, call); + oe->op = negrhs; + } + else + oe->op = lhs; + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Optimizing copysign: "); + print_generic_expr (dump_file, cst, 0); + fprintf (dump_file, " * "); + print_generic_expr (dump_file, + gimple_call_fn (def_stmt), 0); + fprintf (dump_file, " ("); + print_generic_expr (dump_file, arg0, 0); + fprintf (dump_file, ", "); + print_generic_expr (dump_file, arg1, 0); + fprintf (dump_file, ") into %s", + cst1_neg ? "-" : ""); + print_generic_expr (dump_file, + gimple_call_fn (def_stmt), 0); + fprintf (dump_file, " ("); + print_generic_expr (dump_file, mul, 0); + fprintf (dump_file, ", "); + print_generic_expr (dump_file, arg1, 0); + fprintf (dump_file, "\n"); + } + return; + } + break; + default: + break; + } + } + } + } +} + /* Transform STMT at *GSI into a copy by replacing its rhs with NEW_RHS. */ static void @@ -4764,6 +4860,9 @@ reassociate_bb (basic_block bb) if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR) optimize_range_tests (rhs_code, &ops); + if (rhs_code == MULT_EXPR) + attempt_builtin_copysign (&ops); + if (first_pass_instance && rhs_code == MULT_EXPR && flag_unsafe_math_optimizations) -- 2.7.4