[PATCH] Fix PR48290

Richard Guenther rguenther@suse.de
Fri Apr 15 14:16:00 GMT 2011


This fixes the remaining part of PR48290, copyprop not properly
propagating constant copies across PHI nodes.  On the way this
patch needs to fix some present issues with the code inhibiting
various kinds of propagation (but not removing those two that
look completely bogus).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2011-04-15  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/48290
	* tree-ssa-copy.c (copy_prop_visit_phi_node): Propagate constants.
	Properly decide inhibiting propagation based on the valueized
	operand.  Do loop-closed SSA form preserving here ...
	(init_copy_prop): ... not here.

Index: gcc/tree-ssa-copy.c
===================================================================
*** gcc/tree-ssa-copy.c	(revision 172485)
--- gcc/tree-ssa-copy.c	(working copy)
*************** copy_prop_visit_phi_node (gimple phi)
*** 567,572 ****
--- 567,573 ----
    for (i = 0; i < gimple_phi_num_args (phi); i++)
      {
        prop_value_t *arg_val;
+       tree arg_value;
        tree arg = gimple_phi_arg_def (phi, i);
        edge e = gimple_phi_arg_edge (phi, i);
  
*************** copy_prop_visit_phi_node (gimple phi)
*** 575,598 ****
        if (!(e->flags & EDGE_EXECUTABLE))
  	continue;
  
!       /* Constants in the argument list never generate a useful copy.
! 	 Similarly, names that flow through abnormal edges cannot be
! 	 used to derive copies.  */
!       if (TREE_CODE (arg) != SSA_NAME || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
! 	{
! 	  phi_val.value = lhs;
! 	  break;
! 	}
! 
!       /* Avoid copy propagation from an inner into an outer loop.
! 	 Otherwise, this may move loop variant variables outside of
! 	 their loops and prevent coalescing opportunities.  If the
! 	 value was loop invariant, it will be hoisted by LICM and
! 	 exposed for copy propagation.  Not a problem for virtual
! 	 operands though.
! 	 ???  The value will be always loop invariant.  */
!       if (is_gimple_reg (lhs)
! 	  && loop_depth_of_name (arg) > loop_depth_of_name (lhs))
  	{
  	  phi_val.value = lhs;
  	  break;
--- 576,584 ----
        if (!(e->flags & EDGE_EXECUTABLE))
  	continue;
  
!       /* Names that flow through abnormal edges cannot be used to
! 	 derive copies.  */
!       if (TREE_CODE (arg) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg))
  	{
  	  phi_val.value = lhs;
  	  break;
*************** copy_prop_visit_phi_node (gimple phi)
*** 605,630 ****
  	  fprintf (dump_file, "\n");
  	}
  
!       arg_val = get_copy_of_val (arg);
  
!       /* If we didn't visit the definition of arg yet treat it as
!          UNDEFINED.  This also handles PHI arguments that are the
! 	 same as lhs.  We'll come here again.  */
!       if (!arg_val->value)
! 	continue;
  
        /* If the LHS didn't have a value yet, make it a copy of the
  	 first argument we find.   */
        if (phi_val.value == NULL_TREE)
  	{
! 	  phi_val.value = arg_val->value;
  	  continue;
  	}
  
        /* If PHI_VAL and ARG don't have a common copy-of chain, then
  	 this PHI node cannot be a copy operation.  */
!       if (phi_val.value != arg_val->value
! 	  && !operand_equal_p (phi_val.value, arg_val->value, 0))
  	{
  	  phi_val.value = lhs;
  	  break;
--- 591,641 ----
  	  fprintf (dump_file, "\n");
  	}
  
!       if (TREE_CODE (arg) == SSA_NAME)
! 	{
! 	  arg_val = get_copy_of_val (arg);
! 
! 	  /* If we didn't visit the definition of arg yet treat it as
! 	     UNDEFINED.  This also handles PHI arguments that are the
! 	     same as lhs.  We'll come here again.  */
! 	  if (!arg_val->value)
! 	    continue;
  
! 	  arg_value = arg_val->value;
! 	}
!       else
! 	arg_value = valueize_val (arg);
! 
!       /* Avoid copy propagation from an inner into an outer loop.
! 	 Otherwise, this may move loop variant variables outside of
! 	 their loops and prevent coalescing opportunities.  If the
! 	 value was loop invariant, it will be hoisted by LICM and
! 	 exposed for copy propagation.
! 	 ???  The value will be always loop invariant.
! 	 In loop-closed SSA form do not copy-propagate through
! 	 PHI nodes in blocks with a loop exit edge predecessor.  */
!       if (current_loops
! 	  && TREE_CODE (arg_value) == SSA_NAME
! 	  && (loop_depth_of_name (arg_value) > loop_depth_of_name (lhs)
! 	      || (loops_state_satisfies_p (LOOP_CLOSED_SSA)
! 		  && loop_exit_edge_p (e->src->loop_father, e))))
! 	{
! 	  phi_val.value = lhs;
! 	  break;
! 	}
  
        /* If the LHS didn't have a value yet, make it a copy of the
  	 first argument we find.   */
        if (phi_val.value == NULL_TREE)
  	{
! 	  phi_val.value = arg_value;
  	  continue;
  	}
  
        /* If PHI_VAL and ARG don't have a common copy-of chain, then
  	 this PHI node cannot be a copy operation.  */
!       if (phi_val.value != arg_value
! 	  && !operand_equal_p (phi_val.value, arg_value, 0))
  	{
  	  phi_val.value = lhs;
  	  break;
*************** init_copy_prop (void)
*** 669,675 ****
      {
        gimple_stmt_iterator si;
        int depth = bb->loop_depth;
-       bool loop_exit_p = false;
  
        for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
  	{
--- 680,685 ----
*************** init_copy_prop (void)
*** 706,731 ****
  	      set_copy_of_val (def, def);
  	}
  
-       /* In loop-closed SSA form do not copy-propagate through
- 	 PHI nodes in blocks with a loop exit edge predecessor.  */
-       if (current_loops
- 	  && loops_state_satisfies_p (LOOP_CLOSED_SSA))
- 	{
- 	  edge_iterator ei;
- 	  edge e;
- 	  FOR_EACH_EDGE (e, ei, bb->preds)
- 	    if (loop_exit_edge_p (e->src->loop_father, e))
- 	      loop_exit_p = true;
- 	}
- 
        for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
  	{
            gimple phi = gsi_stmt (si);
            tree def;
  
  	  def = gimple_phi_result (phi);
! 	  if (!is_gimple_reg (def)
! 	      || loop_exit_p)
              prop_set_simulate_again (phi, false);
  	  else
              prop_set_simulate_again (phi, true);
--- 716,728 ----
  	      set_copy_of_val (def, def);
  	}
  
        for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
  	{
            gimple phi = gsi_stmt (si);
            tree def;
  
  	  def = gimple_phi_result (phi);
! 	  if (!is_gimple_reg (def))
              prop_set_simulate_again (phi, false);
  	  else
              prop_set_simulate_again (phi, true);



More information about the Gcc-patches mailing list