On Tue, 17 Apr 2012, William J. Schmidt wrote:

> The emergency patch for PR52976 manipulated the operand rank system to
> force inserted __builtin_powi calls to occur before uses of the call
> results.  However, this is generally the wrong approach, as it forces
> other computations to move unnecessarily, and extends the lifetimes of
> other operands.
> 
> This patch fixes the problem in the proper way, by letting the rank
> system determine where the __builtin_powi call belongs, and moving the
> call to that location during the expression rewrite.
> 
> Bootstrapped with no new regressions on powerpc64-linux.  SPEC cpu2000
> and cpu2006 also build cleanly.  Ok for trunk?

Ok.

Thanks,
Richard.

> Thanks,
> Bill
> 
> 
> gcc:
> 
> 2012-04-17  Bill Schmidt  <wschm...@linux.vnet.ibm.com>
> 
>       * 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-17  Bill Schmidt  <wschm...@linux.vnet.ibm.com>
> 
>       gfortran.dg/reassoc_11.f: New test.
> 
> 
> 
> Index: gcc/testsuite/gfortran.dg/reassoc_11.f
> ===================================================================
> --- gcc/testsuite/gfortran.dg/reassoc_11.f    (revision 0)
> +++ gcc/testsuite/gfortran.dg/reassoc_11.f    (revision 0)
> @@ -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
> Index: gcc/tree-ssa-reassoc.c
> ===================================================================
> --- gcc/tree-ssa-reassoc.c    (revision 186495)
> +++ gcc/tree-ssa-reassoc.c    (working copy)
> @@ -544,28 +544,6 @@ add_repeat_to_ops_vec (VEC(operand_entry_t, heap)
>    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.  */
>  
> @@ -2162,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
> @@ -2267,6 +2388,8 @@ rewrite_expr_tree (gimple stmt, unsigned int opind
>             print_gimple_stmt (dump_file, stmt, 0, 0);
>           }
>  
> +       possibly_move_powi (stmt, oe1->op);
> +       possibly_move_powi (stmt, oe2->op);
>       }
>        return;
>      }
> @@ -2312,6 +2435,8 @@ rewrite_expr_tree (gimple stmt, unsigned int opind
>         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.  */
> @@ -2485,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);
> @@ -3196,6 +3324,8 @@ attempt_builtin_powi (gimple stmt, VEC(operand_ent
>                                                          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))
> @@ -3300,10 +3430,8 @@ attempt_builtin_powi (gimple stmt, VEC(operand_ent
>         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
> 
> 
> 

-- 
Richard Guenther <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer

Reply via email to