From b59eee4039c12735d90507ac5508ba31cb76e785 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Wed, 18 Apr 2012 12:29:23 +0000 Subject: [PATCH] re PR tree-optimization/52976 (Revision 186384 breaks the polyhedron tests aermod.f90 and doduc.f90 at -O3 -ffast-math) gcc: 2012-04-18 Bill Schmidt PR tree-optimization/52976 * tree-ssa-reassoc.c (add_to_ops_vec_max_rank): Delete. (possibly_move_powi): New function. (rewrite_expr_tree): Call possibly_move_powi. (rewrite_expr_tree_parallel): Likewise. (attempt_builtin_powi): Change call of add_to_ops_vec_max_rank to call add_to_ops_vec instead. gcc/testsuite: 2012-04-18 Bill Schmidt PR tree-optimization/52976 gfortran.dg/reassoc_11.f: New test. From-SVN: r186568 --- gcc/ChangeLog | 10 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gfortran.dg/reassoc_11.f | 17 ++++++ gcc/tree-ssa-reassoc.c | 78 +++++++++++++++++--------- 4 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/reassoc_11.f diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 46cf8e48346..006a3ea697e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2012-04-18 Bill Schmidt + + PR tree-optimization/52976 + * tree-ssa-reassoc.c (add_to_ops_vec_max_rank): Delete. + (possibly_move_powi): New function. + (rewrite_expr_tree): Call possibly_move_powi. + (rewrite_expr_tree_parallel): Likewise. + (attempt_builtin_powi): Change call of add_to_ops_vec_max_rank to + call add_to_ops_vec instead. + 2012-04-18 Bill Schmidt PR tree-optimization/52976 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c8202e6b46..a07a031a4a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-04-18 Bill Schmidt + + PR tree-optimization/52976 + gfortran.dg/reassoc_11.f: New test. + 2012-04-18 Bill Schmidt PR tree-optimization/52976 diff --git a/gcc/testsuite/gfortran.dg/reassoc_11.f b/gcc/testsuite/gfortran.dg/reassoc_11.f new file mode 100644 index 00000000000..242201680b3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/reassoc_11.f @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-options "-O3 -ffast-math" } + +! This tests only for compile-time failure, which formerly occurred +! when a __builtin_powi was introduced by reassociation in a bad place. + + SUBROUTINE GRDURBAN(URBWSTR, ZIURB, GRIDHT) + + IMPLICIT NONE + INTEGER :: I + REAL :: SW2, URBWSTR, ZIURB, GRIDHT(87) + + SAVE + + SW2 = 1.6*(GRIDHT(I)/ZIURB)**0.667*URBWSTR**2 + + END diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 314b8041d9b..f440d174258 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -544,28 +544,6 @@ add_repeat_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op, reassociate_stats.pows_encountered++; } -/* Add an operand entry to *OPS for the tree operand OP, giving the - new entry a larger rank than any other operand already in *OPS. */ - -static void -add_to_ops_vec_max_rank (VEC(operand_entry_t, heap) **ops, tree op) -{ - operand_entry_t oe = (operand_entry_t) pool_alloc (operand_entry_pool); - operand_entry_t oe1; - unsigned i; - unsigned max_rank = 0; - - FOR_EACH_VEC_ELT (operand_entry_t, *ops, i, oe1) - if (oe1->rank > max_rank) - max_rank = oe1->rank; - - oe->op = op; - oe->rank = max_rank + 1; - oe->id = next_operand_entry_id++; - oe->count = 1; - VEC_safe_push (operand_entry_t, heap, *ops, oe); -} - /* Return true if STMT is reassociable operation containing a binary operation with tree code CODE, and is inside LOOP. */ @@ -2264,6 +2242,47 @@ remove_visited_stmt_chain (tree var) } } +/* If OP is an SSA name, find its definition and determine whether it + is a call to __builtin_powi. If so, move the definition prior to + STMT. Only do this during early reassociation. */ + +static void +possibly_move_powi (gimple stmt, tree op) +{ + gimple stmt2; + tree fndecl; + gimple_stmt_iterator gsi1, gsi2; + + if (!first_pass_instance + || !flag_unsafe_math_optimizations + || TREE_CODE (op) != SSA_NAME) + return; + + stmt2 = SSA_NAME_DEF_STMT (op); + + if (!is_gimple_call (stmt2) + || !has_single_use (gimple_call_lhs (stmt2))) + return; + + fndecl = gimple_call_fndecl (stmt2); + + if (!fndecl + || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) + return; + + switch (DECL_FUNCTION_CODE (fndecl)) + { + CASE_FLT_FN (BUILT_IN_POWI): + break; + default: + return; + } + + gsi1 = gsi_for_stmt (stmt); + gsi2 = gsi_for_stmt (stmt2); + gsi_move_before (&gsi2, &gsi1); +} + /* This function checks three consequtive operands in passed operands vector OPS starting from OPINDEX and swaps two operands if it is profitable for binary operation @@ -2369,6 +2388,8 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, print_gimple_stmt (dump_file, stmt, 0, 0); } + possibly_move_powi (stmt, oe1->op); + possibly_move_powi (stmt, oe2->op); } return; } @@ -2414,6 +2435,8 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, fprintf (dump_file, " into "); print_gimple_stmt (dump_file, stmt, 0, 0); } + + possibly_move_powi (stmt, oe->op); } /* Recurse on the LHS of the binary operator, which is guaranteed to be the non-leaf side. */ @@ -2587,6 +2610,9 @@ rewrite_expr_tree_parallel (gimple stmt, int width, fprintf (dump_file, " into "); print_gimple_stmt (dump_file, stmts[i], 0, 0); } + + possibly_move_powi (stmts[i], op1); + possibly_move_powi (stmts[i], op2); } remove_visited_stmt_chain (last_rhs1); @@ -3298,6 +3324,8 @@ attempt_builtin_powi (gimple stmt, VEC(operand_entry_t, heap) **ops, power)); gimple_call_set_lhs (pow_stmt, iter_result); gimple_set_location (pow_stmt, gimple_location (stmt)); + /* Temporarily place the call; we will move it to the + correct place during rewrite_expr. */ gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3402,10 +3430,8 @@ attempt_builtin_powi (gimple stmt, VEC(operand_entry_t, heap) **ops, gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT); } - /* Append the result of this iteration to the ops vector. - Give it a rank higher than all other ranks in the ops vector - so that all uses of it will be forced to come after it. */ - add_to_ops_vec_max_rank (ops, iter_result); + /* Append the result of this iteration to the ops vector. */ + add_to_ops_vec (ops, iter_result); /* Decrement the occurrence count of each element in the product by the count found above, and remove this many copies of each