SOURCES: gcc-pr17640.patch (NEW) - empty loop removal.

pluto pluto at pld-linux.org
Fri Jul 1 23:02:36 CEST 2005


Author: pluto                        Date: Fri Jul  1 21:02:36 2005 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- empty loop removal.

---- Files affected:
SOURCES:
   gcc-pr17640.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/gcc-pr17640.patch
diff -u /dev/null SOURCES/gcc-pr17640.patch:1.1
--- /dev/null	Fri Jul  1 23:02:36 2005
+++ SOURCES/gcc-pr17640.patch	Fri Jul  1 23:02:31 2005
@@ -0,0 +1,289 @@
+Date: Thu, 30 Jun 2005 23:41:10 +0200
+From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
+Subject: [patch] Empty loop removal
+
+Hello,
+
+this patch implements removal of finite empty loops.  Unlike the
+previous version of the patch that worked by transfering information
+about finiteness of the loop to DCE, this version removes the loops
+directly.  This makes it safer and less likely to cause bugs, although
+possibly a bit weaker; nevertheless, on the practical cases there should
+be no difference.
+
+Bootstrapped & regtested on i686 and ia64.
+
+Zdenek
+
+	* tree-flow.h (remove_empty_loops, single_dom_exit): Declare.
+	* tree-optimize.c (init_tree_optimization_passes): Add pass_empty_loop.
+	* tree-pass.h (pass_empty_loop): Declare.
+	* tree-ssa-loop-ivcanon.c (empty_loop_p, remove_empty_loop,
+	try_remove_empty_loop, remove_empty_loops): New functions.
+	* tree-ssa-loop-ivopts.c (single_dom_exit): Export.
+	* tree-ssa-loop.c (tree_ssa_empty_loop, pass_empty_loop): New.
+
+	* gcc.dg/tree-ssa/loop-10.c: New test.
+
+*** gcc/gcc/tree-flow.h	25 Jun 2005 02:01:21 -0000	2.121
+--- gcc/gcc/tree-flow.h	30 Jun 2005 15:39:16 -0000
+*************** void tree_ssa_lim (struct loops *);
+*** 650,655 ****
+--- 650,656 ----
+  void tree_ssa_unswitch_loops (struct loops *);
+  void canonicalize_induction_variables (struct loops *);
+  void tree_unroll_loops_completely (struct loops *, bool);
++ void remove_empty_loops (struct loops *);
+  void tree_ssa_iv_optimize (struct loops *);
+  
+  bool number_of_iterations_exit (struct loop *, edge,
+*************** struct loop *tree_ssa_loop_version (stru
+*** 681,686 ****
+--- 682,688 ----
+  				    basic_block *);
+  tree expand_simple_operations (tree);
+  void substitute_in_loop_info (struct loop *, tree, tree);
++ edge single_dom_exit (struct loop *);
+  
+  /* In tree-ssa-loop-im.c  */
+  /* The possibilities of statement movement.  */
+*** gcc/gcc/tree-optimize.c	30 Jun 2005 00:47:49 -0000	2.116
+--- gcc/gcc/tree-optimize.c	30 Jun 2005 15:39:17 -0000
+*************** init_tree_optimization_passes (void)
+*** 564,569 ****
+--- 564,570 ----
+    NEXT_PASS (pass_lim);
+    NEXT_PASS (pass_unswitch);
+    NEXT_PASS (pass_scev_cprop);
++   NEXT_PASS (pass_empty_loop);
+    NEXT_PASS (pass_record_bounds);
+    NEXT_PASS (pass_linear_transform);
+    NEXT_PASS (pass_iv_canon);
+*** gcc/gcc/tree-pass.h	28 Jun 2005 02:20:29 -0000	2.46
+--- gcc/gcc/tree-pass.h	30 Jun 2005 15:39:17 -0000
+*************** extern struct tree_opt_pass pass_lim;
+*** 175,180 ****
+--- 175,181 ----
+  extern struct tree_opt_pass pass_unswitch;
+  extern struct tree_opt_pass pass_iv_canon;
+  extern struct tree_opt_pass pass_scev_cprop;
++ extern struct tree_opt_pass pass_empty_loop;
+  extern struct tree_opt_pass pass_record_bounds;
+  extern struct tree_opt_pass pass_if_conversion;
+  extern struct tree_opt_pass pass_vectorize;
+*** gcc/gcc/tree-ssa-loop-ivcanon.c	26 Jun 2005 21:21:32 -0000	2.16
+--- gcc/gcc/tree-ssa-loop-ivcanon.c	30 Jun 2005 15:39:17 -0000
+*************** tree_unroll_loops_completely (struct loo
+*** 371,373 ****
+--- 371,523 ----
+    if (changed)
+      cleanup_tree_cfg_loop ();
+  }
++ 
++ /* Checks whether LOOP is empty.  */
++ 
++ static bool
++ empty_loop_p (struct loop *loop)
++ {
++   edge exit;
++   struct tree_niter_desc niter;
++   tree phi, def;
++   basic_block *body;
++   block_stmt_iterator bsi;
++   unsigned i;
++   tree stmt;
++ 
++   /* If the loop has multiple exits, it is too hard for us to handle.
++      Similarly, if the exit is not dominating, we cannot determine
++      whether the loop is not infinite.  */
++   exit = single_dom_exit (loop);
++   if (!exit)
++     return false;
++ 
++   /* The loop must be finite.  */
++   if (!number_of_iterations_exit (loop, exit, &niter))
++     return false;
++ 
++   /* Values of all loop exit phi nodes must be invariants.  */
++   for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
++     {
++       if (!is_gimple_reg (PHI_RESULT (phi)))
++ 	continue;
++ 
++       def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
++ 
++       if (!expr_invariant_in_loop_p (loop, def))
++ 	return false;
++     }
++ 
++   /* And there should be no memory modifying or from other reasons
++      unremovable statements.  */
++   body = get_loop_body (loop);
++   for (i = 0; i < loop->num_nodes; i++)
++     {
++       /* Irreducible region might be infinite.  */
++       if (body[i]->flags & BB_IRREDUCIBLE_LOOP)
++ 	{
++ 	  free (body);
++ 	  return false;
++ 	}
++ 	
++       for (bsi = bsi_start (body[i]); !bsi_end_p (bsi); bsi_next (&bsi))
++ 	{
++ 	  stmt = bsi_stmt (bsi);
++ 	  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS)
++ 	      || stmt_ann (stmt)->has_volatile_ops)
++ 	    {
++ 	      free (body);
++ 	      return false;
++ 	    }
++ 
++ 	  /* Also, asm statements and calls may have side effects and we
++ 	     cannot change the number of times they are executed.  */
++ 	  switch (TREE_CODE (stmt))
++ 	    {
++ 	    case RETURN_EXPR:
++ 	    case MODIFY_EXPR:
++ 	      stmt = get_call_expr_in (stmt);
++ 	      if (!stmt)
++ 		break;
++ 
++ 	    case CALL_EXPR:
++ 	      if (TREE_SIDE_EFFECTS (stmt))
++ 		{
++ 		  free (body);
++ 		  return false;
++ 		}
++ 	      break;
++ 
++ 	    case ASM_EXPR:
++ 	      free (body);
++ 	      return false;
++ 
++ 	    default:
++ 	      break;
++ 	    }
++ 	}
++       }
++   free (body);
++ 
++   return true;
++ }
++ 
++ /* Remove LOOP by making it exit in the first iteration.  */
++ 
++ static void
++ remove_empty_loop (struct loop *loop)
++ {
++   edge exit = single_dom_exit (loop);
++   tree cond_stmt = last_stmt (exit->src);
++   tree do_exit;
++ 
++   if (exit->flags & EDGE_TRUE_VALUE)
++     do_exit = boolean_true_node;
++   else
++     do_exit = boolean_false_node;
++ 
++   COND_EXPR_COND (cond_stmt) = do_exit;
++   update_stmt (cond_stmt);
++ }
++ 
++ /* Removes LOOP if it is empty.  */
++ 
++ static bool
++ try_remove_empty_loop (struct loop *loop)
++ {
++   bool changed = false, all = true;
++   struct loop *sub;
++ 
++   /* First, all subloops must be removed.  */
++   for (sub = loop->inner; sub; sub = sub->next)
++     {
++       if (try_remove_empty_loop (sub))
++ 	changed = true;
++       else
++ 	all = false;
++     }
++ 
++   if (!all || !empty_loop_p (loop))
++     return changed;
++ 
++   remove_empty_loop (loop);
++   return true;
++ }
++ 
++ /* Remove the empty LOOPS.  */
++ 
++ void
++ remove_empty_loops (struct loops *loops)
++ {
++   bool changed = false;
++   struct loop *loop;
++ 
++   for (loop = loops->tree_root->inner; loop; loop = loop->next)
++     changed |= try_remove_empty_loop (loop);
++ 
++   if (changed)
++     {
++       scev_reset ();
++       cleanup_tree_cfg_loop ();
++     }
++ }
+*** gcc/gcc/tree-ssa-loop-ivopts.c	26 Jun 2005 21:21:32 -0000	2.82
+--- gcc/gcc/tree-ssa-loop-ivopts.c	30 Jun 2005 15:39:18 -0000
+*************** loop_data (struct loop *loop)
+*** 358,364 ****
+  
+  /* The single loop exit if it dominates the latch, NULL otherwise.  */
+  
+! static edge
+  single_dom_exit (struct loop *loop)
+  {
+    edge exit = loop->single_exit;
+--- 358,364 ----
+  
+  /* The single loop exit if it dominates the latch, NULL otherwise.  */
+  
+! edge
+  single_dom_exit (struct loop *loop)
+  {
+    edge exit = loop->single_exit;
+*** gcc/gcc/tree-ssa-loop.c	25 Jun 2005 02:01:42 -0000	2.31
+--- gcc/gcc/tree-ssa-loop.c	30 Jun 2005 15:39:18 -0000
+*************** struct tree_opt_pass pass_scev_cprop =
+*** 311,316 ****
+--- 311,344 ----
+    0					/* letter */
+  };
+  
++ /* Remove empty loops.  */
++ 
++ static void
++ tree_ssa_empty_loop (void)
++ {
++   if (!current_loops)
++     return;
++ 
++   remove_empty_loops (current_loops);
++ }
++ 
++ struct tree_opt_pass pass_empty_loop =
++ {
++   "empty",				/* name */
++   NULL,					/* gate */
++   tree_ssa_empty_loop,		       	/* execute */
++   NULL,					/* sub */
++   NULL,					/* next */
++   0,					/* static_pass_number */
++   TV_COMPLETE_UNROLL,	  		/* tv_id */
++   PROP_cfg | PROP_ssa,			/* properties_required */
++   0,					/* properties_provided */
++   0,					/* properties_destroyed */
++   0,					/* todo_flags_start */
++   TODO_dump_func | TODO_verify_loops,	/* todo_flags_finish */
++   0					/* letter */
++ };
++ 
+  /* Record bounds on numbers of iterations of loops.  */
+  
+  static void
================================================================



More information about the pld-cvs-commit mailing list