Commit 0155ad40 by Marek Polacek Committed by Marek Polacek

re PR tree-optimization/67815 (Optimize const1 * copysign (const2, y) into…

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
parent d5efd449
2015-10-14 Marek Polacek <polacek@redhat.com>
PR tree-optimization/67815
* tree-ssa-reassoc.c (attempt_builtin_copysign): New function.
(reassociate_bb): Call it.
2015-10-14 Richard Biener <rguenther@suse.de>
* tree-vect-data-refs.c (vect_enhance_data_refs_alignment):
2015-10-14 Marek Polacek <polacek@redhat.com>
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 <vogt@linux.vnet.ibm.com>
* gcc.dg/pragma-pop_options-1.c: New test.
......
/* 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"} }*/
/* 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" } } */
/* 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"} }*/
......@@ -4622,6 +4622,102 @@ attempt_builtin_powi (gimple *stmt, vec<operand_entry *> *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<operand_entry *> *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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment