This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR43186


This fixes PR43186, a case where we end up with gazillions of
nested loops which are worthwhile to completely unroll.  The
issue is that we do a bad job cleaning up after the individual
unrolls and thus while our estimates on what gets optimized
away are correct we spend a lot of useless time copying to-be
optimized away statements.  The fix is to try a little harder
to fold COND_EXPRs in cfgcleanup.  On the way I removed the
odd gimple_fold routine which is only called from
cleanup_control_expr_graph and only with conds and switches.

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

Richard.

2010-02-26  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/43186
	* gimple.h (gimple_fold): Remove.
	* gimple.c (gimple_fold): Remove.  Inline into single user ...
	* tree-cfgcleanup.c (cleanup_control_expr_graph): ... here.
	Try harder for conditions.

	* gcc.c-torture/compile/pr43186.c: New testcase.

Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h	(revision 157087)
--- gcc/gimple.h	(working copy)
*************** bool gimple_assign_ssa_name_copy_p (gimp
*** 841,847 ****
  bool gimple_assign_single_p (gimple);
  bool gimple_assign_unary_nop_p (gimple);
  void gimple_set_bb (gimple, struct basic_block_def *);
- tree gimple_fold (const_gimple);
  void gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *, tree);
  void gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *, enum tree_code,
  				     tree, tree);
--- 841,846 ----
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c	(revision 157087)
--- gcc/gimple.c	(working copy)
*************** gimple_set_bb (gimple stmt, basic_block
*** 1835,1888 ****
  }
  
  
- /* Fold the expression computed by STMT.  If the expression can be
-    folded, return the folded result, otherwise return NULL.  STMT is
-    not modified.  */
- 
- tree
- gimple_fold (const_gimple stmt)
- {
-   location_t loc = gimple_location (stmt);
-   switch (gimple_code (stmt))
-     {
-     case GIMPLE_COND:
-       return fold_binary_loc (loc, gimple_cond_code (stmt),
- 			  boolean_type_node,
- 			  gimple_cond_lhs (stmt),
- 			  gimple_cond_rhs (stmt));
- 
-     case GIMPLE_ASSIGN:
-       switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
- 	{
- 	case GIMPLE_UNARY_RHS:
- 	  return fold_unary_loc (loc, gimple_assign_rhs_code (stmt),
- 			     TREE_TYPE (gimple_assign_lhs (stmt)),
- 			     gimple_assign_rhs1 (stmt));
- 	case GIMPLE_BINARY_RHS:
- 	  return fold_binary_loc (loc, gimple_assign_rhs_code (stmt),
- 			      TREE_TYPE (gimple_assign_lhs (stmt)),
- 			      gimple_assign_rhs1 (stmt),
- 			      gimple_assign_rhs2 (stmt));
- 	case GIMPLE_SINGLE_RHS:
- 	  return fold (gimple_assign_rhs1 (stmt));
- 	default:;
- 	}
-       break;
- 
-     case GIMPLE_SWITCH:
-       return gimple_switch_index (stmt);
- 
-     case GIMPLE_CALL:
-       return NULL_TREE;
- 
-     default:
-       break;
-     }
- 
-   gcc_unreachable ();
- }
- 
- 
  /* Modify the RHS of the assignment pointed-to by GSI using the
     operands in the expression tree EXPR.
  
--- 1835,1840 ----
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c	(revision 157087)
--- gcc/tree-cfgcleanup.c	(working copy)
*************** cleanup_control_expr_graph (basic_block
*** 90,98 ****
        edge e;
        edge_iterator ei;
        bool warned;
  
        fold_defer_overflow_warnings ();
!       val = gimple_fold (stmt);
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)
  	{
--- 90,136 ----
        edge e;
        edge_iterator ei;
        bool warned;
+       location_t loc;
  
        fold_defer_overflow_warnings ();
!       loc = gimple_location (stmt);
!       switch (gimple_code (stmt))
! 	{
! 	case GIMPLE_COND:
! 	  {
! 	    tree lhs = gimple_cond_lhs (stmt);
! 	    tree rhs = gimple_cond_rhs (stmt);
! 	    /* For conditions try harder and lookup single-argument
! 	       PHI nodes.  Only do so from the same basic-block though
! 	       as other basic-blocks may be dead already.  */
! 	    if (TREE_CODE (lhs) == SSA_NAME)
! 	      {
! 		gimple def_stmt = SSA_NAME_DEF_STMT (lhs);
! 		if (gimple_code (def_stmt) == GIMPLE_PHI
! 		    && gimple_phi_num_args (def_stmt) == 1
! 		    && gimple_bb (def_stmt) == gimple_bb (stmt))
! 		  lhs = PHI_ARG_DEF (def_stmt, 0);
! 	      }
! 	    if (TREE_CODE (rhs) == SSA_NAME)
! 	      {
! 		gimple def_stmt = SSA_NAME_DEF_STMT (rhs);
! 		if (gimple_code (def_stmt) == GIMPLE_PHI
! 		    && gimple_phi_num_args (def_stmt) == 1
! 		    && gimple_bb (def_stmt) == gimple_bb (stmt))
! 		  rhs = PHI_ARG_DEF (def_stmt, 0);
! 	      }
! 	    val = fold_binary_loc (loc, gimple_cond_code (stmt),
! 				   boolean_type_node, lhs, rhs);
! 	    break;
! 	  }
! 
! 	case GIMPLE_SWITCH:
! 	  val = gimple_switch_index (stmt);
! 	  break;
! 
! 	default:
! 	  val = NULL_TREE;
! 	}
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)
  	{
Index: gcc/testsuite/gcc.c-torture/compile/pr43186.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr43186.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr43186.c	(revision 0)
***************
*** 0 ****
--- 1,15 ----
+ int n;
+ 
+ void foo (int i)
+ {
+   int a, b;
+ 
+   if (!i)
+     for (a = 1; a < 3; a++)
+       if (a)
+ 	for (b = 1; b < 3; b++)
+ 	  foo (b);
+ 
+   n++;
+ }
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]