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]

Re: Allow CD-DCE to remove (finite) empty loops


Hi,
it turned out that I was bit too fast with removing the empty loop pass and
forgot to check testsuite failures, did only the bootstrap stats.  Some testsuite
updating is needed since we no longer print info on removed empty loops that is
included in this patch and there was two kind of real missed optimizations with
cd-dce relative to empty loop.

First one, seen on pr32044, was caused by fact that we keep silly PHI nodes
like ssa_name=PHI(0,0) that makes cd-dce to mark control dependency for both
incomming edges. Such degenerate PHI nodes are really just copy statements.
There was code to special case them in virtual PHI handling, so I broke it out
to degenerate_phi_p (that match fact that all operands are the same) and use it
in control dependence propagation and in forward_edge_to_pdom to simply pick
the single argument instead of looking for control dependent BB.

Other problem was cuased by fact that initializing loop optimizer with preheaders
only causes code proving finiteness to miss some loops, in particular ones present
in loop-15.c and loop-24.c.  Those are loops of for
 for (a=start;a!=end;a+=4)
where we need fact that loops has only one exit.

I updated the flags to be same as in loop optimizer (and all the flags are
needed) and did same update in ipa-cp.

I am re-doing full testing (x86_64-linux) after small last minute
cleanups and will commit it later today if there are no complains.

Honza

	* gcc.dg/tree-ssa/loop-24.c: Update dump file matching; enable -O2.
	* gcc.dg/tree-ssa/loop-25.c: Likewise.
	* gcc.dg/tree-ssa/loop-26.c: Likewise.
	* gcc.dg/tree-ssa/pr32044.c: Likewise.
	* gcc.dg/tree-ssa/loop-29.c: Likewise.
	* gcc.dg/tree-ssa/loop-10.c: Likewise.

	* ipa-pure-const.c (analyze): Update loop optimizer init.
	* tree-ssa-loop-iv-canon.c (empty_loop_p, remove_empty_loop,
	try_remove_empty_loop, remove_empty_loops): Remove.
	* tree-ssa-loop.c (tree_ssa_empty_loop, pass_empty_loop): Remove.
	* tree-ssa-dce.c (find_obviously_necessary_stmts): Use finiteness info
	to mark regular loops as neccesary.
	(degenerate_phi_p): New function.
	(propagate_necessity, remove_dead_phis): Use it.
	(forward_edge_to_pdom): Likewise.
	(eliminate_unnecessary_stmts): Take care to remove uses of results of
	virtual PHI nodes that became unreachable.
	(perform_tree_ssa_dce): Initialize/deinitialize loop optimizer.
	* tree-flow.h (remove_empty_loops): Remove.
	* passes.c (init_optimization_passes): Remove.
Index: testsuite/gcc.dg/tree-ssa/loop-24.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/loop-24.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/loop-24.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O -fstrict-overflow -fdump-tree-empty" } */
  
  void foo(int a, int b)
  { for(;a!=b;a+=4); }
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fstrict-overflow -fdump-tree-optimized" } */
  
  void foo(int a, int b)
  { for(;a!=b;a+=4); }
*************** void foo3(int*a, int* b)
*** 13,17 ****
  void foo4(int*a, int*b)
  { for(;a!=b;a++); }
  
! /* { dg-final { scan-tree-dump-times "Removing empty loop" 4 "empty" } } */
! /* { dg-final { cleanup-tree-dump "empty" } } */
--- 13,17 ----
  void foo4(int*a, int*b)
  { for(;a!=b;a++); }
  
! /* { dg-final { scan-tree-dump-not "if" "optimized" } } */
! /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-25.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/loop-25.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/loop-25.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-profile" } */
  
  int foo(void);
  void bla(void);
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O1 -fdump-tree-profile" } */
  
  int foo(void);
  void bla(void);
Index: testsuite/gcc.dg/tree-ssa/loop-26.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/loop-26.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/loop-26.c	(working copy)
***************
*** 2,8 ****
     determine number of iterations of the following loops unconditionally.  */
  
  /* { dg-do compile } */
! /* { dg-options "-O -fstrict-overflow -fdump-tree-empty" } */
  
  unsigned foo(unsigned int n)
  {
--- 2,8 ----
     determine number of iterations of the following loops unconditionally.  */
  
  /* { dg-do compile } */
! /* { dg-options "-O2 -fstrict-overflow -fdump-tree-optimized-blocks" } */
  
  unsigned foo(unsigned int n)
  {
*************** int foo0(int i0, int i1)
*** 25,29 ****
    return j;
  }
  
! /* { dg-final { scan-tree-dump-times "Removing empty loop" 2 "empty" } } */
! /* { dg-final { cleanup-tree-dump "empty" } } */
--- 25,29 ----
    return j;
  }
  
! /* { dg-final { scan-tree-dump-times "if" 2 "optimized" } } */
! /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/pr32044.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/pr32044.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/pr32044.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-empty -fdump-tree-optimized" } */
  
  int foo (int n)
  {
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-optimized" } */
  
  int foo (int n)
  {
*************** int baz (int n)
*** 43,55 ****
    return i;
  }
  
! /* The loops computing division/modulo by 64 should be eliminated.  */
! /* { dg-final { scan-tree-dump-times "Removing empty loop" 2 "empty" } } */
  
  /* There should be no division/modulo in the final dump (division and modulo
     by 64 are done using bit operations).  */
  /* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */
  /* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */
  
- /* { dg-final { cleanup-tree-dump "empty" } } */
  /* { dg-final { cleanup-tree-dump "optimized" } } */
--- 43,54 ----
    return i;
  }
  
! /* The loops computing division/modulo by 64 should be eliminated */
! /* { dg-final { scan-tree-dump-times "if" 6 "optimized" } } */
  
  /* There should be no division/modulo in the final dump (division and modulo
     by 64 are done using bit operations).  */
  /* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */
  /* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */
  
  /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-29.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/loop-29.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/loop-29.c	(working copy)
***************
*** 1,7 ****
  /* PR 31885 */
  
  /* { dg-do compile } */
! /* { dg-options "-O1 -fdump-tree-empty" } */
  
  struct s {
      int *blah;
--- 1,7 ----
  /* PR 31885 */
  
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-optimized" } */
  
  struct s {
      int *blah;
*************** foo (struct s *p)
*** 17,21 ****
      p++;
  }
  
! /* { dg-final { scan-tree-dump-times "Removing empty loop" 1 "empty" } } */
! /* { dg-final { cleanup-tree-dump "empty" } } */
--- 17,21 ----
      p++;
  }
  
! /* { dg-final { scan-tree-dump-not "if" "optimized" } } */
! /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-ssa/loop-10.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/loop-10.c	(revision 149199)
--- testsuite/gcc.dg/tree-ssa/loop-10.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O1 -fdump-tree-optimized" } */
  /* { dg-require-effective-target int32plus } */
  
  int bar (void);
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-optimized" } */
  /* { dg-require-effective-target int32plus } */
  
  int bar (void);
Index: ipa-pure-const.c
===================================================================
*** ipa-pure-const.c	(revision 149199)
--- ipa-pure-const.c	(working copy)
*************** end:
*** 535,541 ****
  	 effect.  */
        if (mark_dfs_back_edges ())
          {
! 	  loop_optimizer_init (LOOPS_HAVE_PREHEADERS);
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    flow_loops_dump (dump_file, NULL, 0);
  	  if (mark_irreducible_loops ())
--- 535,545 ----
  	 effect.  */
        if (mark_dfs_back_edges ())
          {
! 	  /* Preheaders are needed for SCEV to work.
! 	     Simple lateches and recorded exits improve chances that loop will
! 	     proved to be finite in testcases such as in loop-15.c and loop-24.c  */
! 	  loop_optimizer_init (LOOPS_NORMAL
! 			       | LOOPS_HAVE_RECORDED_EXITS);
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    flow_loops_dump (dump_file, NULL, 0);
  	  if (mark_irreducible_loops ())
Index: tree-ssa-loop-ivcanon.c
===================================================================
*** tree-ssa-loop-ivcanon.c	(revision 149199)
--- tree-ssa-loop-ivcanon.c	(working copy)
*************** tree_unroll_loops_completely (bool may_i
*** 558,744 ****
  
    return 0;
  }
- 
- /* Checks whether LOOP is empty.  */
- 
- static bool
- empty_loop_p (struct loop *loop)
- {
-   edge exit;
-   basic_block *body;
-   gimple_stmt_iterator gsi;
-   unsigned i;
- 
-   /* 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 (!finite_loop_p (loop))
-     return false;
- 
-   /* Values of all loop exit phi nodes must be invariants.  */
-   for (gsi = gsi_start(phi_nodes (exit->dest)); !gsi_end_p (gsi); gsi_next (&gsi))
-     {
-       gimple phi = gsi_stmt (gsi);
-       tree def;
- 
-       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 (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
- 	{
- 	  gimple stmt = gsi_stmt (gsi);
- 
- 	  if (gimple_vdef (stmt)
- 	      || gimple_has_volatile_ops (stmt))
- 	    {
- 	      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 (gimple_code (stmt))
- 	    {
- 	    case GIMPLE_CALL:
- 	      if (gimple_has_side_effects (stmt))
- 		{
- 		  free (body);
- 		  return false;
- 		}
- 	      break;
- 
- 	    case GIMPLE_ASM:
- 	      /* We cannot remove volatile assembler.  */
- 	      if (gimple_asm_volatile_p (stmt))
- 		{
- 		  free (body);
- 		  return false;
- 		}
- 	      break;
- 
- 	    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), non_exit;
-   gimple cond_stmt = last_stmt (exit->src);
-   basic_block *body;
-   unsigned n_before, freq_in, freq_h;
-   gcov_type exit_count = exit->count;
- 
-   if (dump_file)
-     fprintf (dump_file, "Removing empty loop %d\n", loop->num);
- 
-   non_exit = EDGE_SUCC (exit->src, 0);
-   if (non_exit == exit)
-     non_exit = EDGE_SUCC (exit->src, 1);
- 
-   if (exit->flags & EDGE_TRUE_VALUE)
-     gimple_cond_make_true (cond_stmt);
-   else
-     gimple_cond_make_false (cond_stmt);
-   update_stmt (cond_stmt);
- 
-   /* Let us set the probabilities of the edges coming from the exit block.  */
-   exit->probability = REG_BR_PROB_BASE;
-   non_exit->probability = 0;
-   non_exit->count = 0;
- 
-   /* Update frequencies and counts.  Everything before
-      the exit needs to be scaled FREQ_IN/FREQ_H times,
-      where FREQ_IN is the frequency of the entry edge
-      and FREQ_H is the frequency of the loop header.
-      Everything after the exit has zero frequency.  */
-   freq_h = loop->header->frequency;
-   freq_in = EDGE_FREQUENCY (loop_preheader_edge (loop));
-   if (freq_h != 0)
-     {
-       body = get_loop_body_in_dom_order (loop);
-       for (n_before = 1; n_before <= loop->num_nodes; n_before++)
- 	if (body[n_before - 1] == exit->src)
- 	  break;
-       scale_bbs_frequencies_int (body, n_before, freq_in, freq_h);
-       scale_bbs_frequencies_int (body + n_before, loop->num_nodes - n_before,
- 				 0, 1);
-       free (body);
-     }
- 
-   /* Number of executions of exit is not changed, thus we need to restore
-      the original value.  */
-   exit->count = exit_count;
- }
- 
- /* Removes LOOP if it is empty.  Returns true if LOOP is removed.  CHANGED
-    is set to true if LOOP or any of its subloops is removed.  */
- 
- static bool
- try_remove_empty_loop (struct loop *loop, bool *changed)
- {
-   bool nonempty_subloop = false;
-   struct loop *sub;
- 
-   /* First, all subloops must be removed.  */
-   for (sub = loop->inner; sub; sub = sub->next)
-     nonempty_subloop |= !try_remove_empty_loop (sub, changed);
- 
-   if (nonempty_subloop || !empty_loop_p (loop))
-     return false;
- 
-   remove_empty_loop (loop);
-   *changed = true;
-   return true;
- }
- 
- /* Remove the empty loops.  */
- 
- unsigned int
- remove_empty_loops (void)
- {
-   bool changed = false;
-   struct loop *loop;
- 
-   for (loop = current_loops->tree_root->inner; loop; loop = loop->next)
-     try_remove_empty_loop (loop, &changed);
- 
-   if (changed)
-     {
-       scev_reset ();
-       return TODO_cleanup_cfg;
-     }
-   return 0;
- }
- 
--- 558,560 ----
Index: tree-ssa-loop.c
===================================================================
*** tree-ssa-loop.c	(revision 149199)
--- tree-ssa-loop.c	(working copy)
*************** struct gimple_opt_pass pass_scev_cprop =
*** 433,469 ****
   }
  };
  
- /* Remove empty loops.  */
- 
- static unsigned int
- tree_ssa_empty_loop (void)
- {
-   if (number_of_loops () <= 1)
-     return 0;
- 
-   return remove_empty_loops ();
- }
- 
- struct gimple_opt_pass pass_empty_loop =
- {
-  {
-   GIMPLE_PASS,
-   "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_ggc_collect			/* todo_flags_finish */
-  }
- };
- 
  /* Record bounds on numbers of iterations of loops.  */
  
  static unsigned int
--- 433,438 ----
Index: tree-ssa-dce.c
===================================================================
*** tree-ssa-dce.c	(revision 149199)
--- tree-ssa-dce.c	(working copy)
*************** find_obviously_necessary_stmts (struct e
*** 434,450 ****
  	}
      }
  
    if (el)
      {
!       /* Prevent the loops from being removed.  We must keep the infinite loops,
! 	 and we currently do not have a means to recognize the finite ones.  */
!       FOR_EACH_BB (bb)
! 	{
! 	  edge_iterator ei;
! 	  FOR_EACH_EDGE (e, ei, bb->succs)
! 	    if (e->flags & EDGE_DFS_BACK)
! 	      mark_control_dependent_edges_necessary (e->dest, el);
! 	}
      }
  }
  
--- 434,475 ----
  	}
      }
  
+   /* Pure and const functions are finite and thus have no infinite loops in
+      them.  */
+   if ((TREE_READONLY (current_function_decl)
+        || DECL_PURE_P (current_function_decl))
+       && !DECL_LOOPING_CONST_OR_PURE_P (current_function_decl))
+     return;
+ 
+   /* Prevent the empty possibly infinite loops from being removed.  */
    if (el)
      {
!       loop_iterator li;
!       struct loop *loop;
!       scev_initialize ();
!       if (mark_irreducible_loops ())
! 	FOR_EACH_BB (bb)
! 	  {
! 	    edge_iterator ei;
! 	    FOR_EACH_EDGE (e, ei, bb->succs)
! 	      if ((e->flags & EDGE_DFS_BACK)
! 		  && (e->flags & EDGE_IRREDUCIBLE_LOOP))
! 		{
! 	          if (dump_file)
! 	            fprintf (dump_file, "Marking back edge of irreducible loop %i->%i\n",
! 		    	     e->src->index, e->dest->index);
! 		  mark_control_dependent_edges_necessary (e->dest, el);
! 		}
! 	  }
! 
!       FOR_EACH_LOOP (li, loop, 0)
! 	if (!finite_loop_p (loop))
! 	  {
! 	    if (dump_file)
! 	      fprintf (dump_file, "can not prove finiteness of loop %i\n", loop->num);
! 	    mark_control_dependent_edges_necessary (loop->latch, el);
! 	  }
!       scev_finalize ();
      }
  }
  
*************** mark_all_reaching_defs_necessary (gimple
*** 570,575 ****
--- 595,613 ----
  		      mark_all_reaching_defs_necessary_1, NULL, &visited);
  }
  
+ /* Return true for PHI nodes with one or identical arguments
+    can be removed.  */
+ static bool
+ degenerate_phi_p (gimple phi)
+ {
+   unsigned int i;
+   tree op = gimple_phi_arg_def (phi, 0);
+   for (i = 1; i < gimple_phi_num_args (phi); i++)
+     if (gimple_phi_arg_def (phi, i) != op)
+       return false;
+   return true;
+ }
+ 
  /* Propagate necessity using the operands of necessary statements.
     Process the uses on each statement in the worklist, and add all
     feeding statements which contribute to the calculation of this
*************** propagate_necessity (struct edge_list *e
*** 632,638 ****
  		mark_operand_necessary (arg);
  	    }
  
! 	  if (aggressive)
  	    {
  	      for (k = 0; k < gimple_phi_num_args (stmt); k++)
  		{
--- 670,676 ----
  		mark_operand_necessary (arg);
  	    }
  
! 	  if (aggressive && !degenerate_phi_p (stmt))
  	    {
  	      for (k = 0; k < gimple_phi_num_args (stmt); k++)
  		{
*************** remove_dead_phis (basic_block bb)
*** 822,844 ****
           very simple dead PHI removal here.  */
        if (!is_gimple_reg (gimple_phi_result (phi)))
  	{
- 	  unsigned i;
- 	  tree vuse;
- 
  	  /* Virtual PHI nodes with one or identical arguments
  	     can be removed.  */
! 	  vuse = gimple_phi_arg_def (phi, 0);
! 	  for (i = 1; i < gimple_phi_num_args (phi); ++i)
! 	    {
! 	      if (gimple_phi_arg_def (phi, i) != vuse)
! 		{
! 		  vuse = NULL_TREE;
! 		  break;
! 		}
! 	    }
! 	  if (vuse != NULL_TREE)
  	    {
  	      tree vdef = gimple_phi_result (phi);
  	      use_operand_p use_p;
  	      imm_use_iterator iter;
  	      gimple use_stmt;
--- 860,872 ----
           very simple dead PHI removal here.  */
        if (!is_gimple_reg (gimple_phi_result (phi)))
  	{
  	  /* Virtual PHI nodes with one or identical arguments
  	     can be removed.  */
! 	  if (degenerate_phi_p (phi))
  	    {
  	      tree vdef = gimple_phi_result (phi);
+ 	      tree vuse = gimple_phi_arg_def (phi, 0);
+ 
  	      use_operand_p use_p;
  	      imm_use_iterator iter;
  	      gimple use_stmt;
*************** static edge
*** 899,905 ****
  forward_edge_to_pdom (edge e, basic_block post_dom_bb)
  {
    gimple_stmt_iterator gsi;
!   edge e2;
    edge_iterator ei;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
--- 927,933 ----
  forward_edge_to_pdom (edge e, basic_block post_dom_bb)
  {
    gimple_stmt_iterator gsi;
!   edge e2 = NULL;
    edge_iterator ei;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
*************** forward_edge_to_pdom (edge e, basic_bloc
*** 924,929 ****
--- 952,958 ----
        for (gsi = gsi_start_phis (post_dom_bb); !gsi_end_p (gsi);)
  	{
  	  gimple phi = gsi_stmt (gsi);
+ 	  tree op;
  
  	  /* Dead PHI do not imply control dependency.  */
            if (!gimple_plf (phi, STMT_NECESSARY)
*************** forward_edge_to_pdom (edge e, basic_bloc
*** 947,954 ****
  	      remove_phi_node (&gsi, true);
  	      continue;
  	    }
!           gcc_assert (e2);
! 	  add_phi_arg (phi, gimple_phi_arg_def (phi, e2->dest_idx), e);
  	  gsi_next (&gsi);
  	}
      }
--- 976,987 ----
  	      remove_phi_node (&gsi, true);
  	      continue;
  	    }
! 	  if (!e2)
! 	    op = gimple_phi_arg_def (phi, e->dest_idx == 0 ? 1 : 0);
! 	  else
! 	    op = gimple_phi_arg_def (phi, e2->dest_idx);
! 	  add_phi_arg (phi, op, e);
! 	  gcc_assert (e2 || degenerate_phi_p (phi));
  	  gsi_next (&gsi);
  	}
      }
*************** eliminate_unnecessary_stmts (void)
*** 1094,1100 ****
  	    }
  	}
      }
! 
    FOR_EACH_BB (bb)
      {
        /* Remove dead PHI nodes.  */
--- 1127,1168 ----
  	    }
  	}
      }
!   /* Since we don't track liveness of virtual PHI nodes, it is possible that we
!      rendered some PHI nodes unreachable while they are still in use.
!      Mark them for renaming.  */
!   if (cfg_altered)
!     {
!       basic_block next_bb;
!       find_unreachable_blocks ();
!       for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; bb = next_bb)
! 	{
! 	  next_bb = bb->next_bb;
! 	  if (!(bb->flags & BB_REACHABLE))
! 	    {
! 	      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
! 		if (!is_gimple_reg (gimple_phi_result (gsi_stmt (gsi))))
! 		  {
! 		    bool found = false;
! 		    imm_use_iterator iter;
! 
! 		    FOR_EACH_IMM_USE_STMT (stmt, iter, gimple_phi_result (gsi_stmt (gsi)))
! 		      {
! 			if (!(gimple_bb (stmt)->flags & BB_REACHABLE))
! 			  continue;
! 			if (gimple_code (stmt) == GIMPLE_PHI
! 			    || gimple_plf (stmt, STMT_NECESSARY))
! 			  {
! 			    found = true;
! 			    BREAK_FROM_IMM_USE_STMT (iter);
! 			  }
! 		      }
! 		    if (found)
! 		      mark_virtual_phi_result_for_renaming (gsi_stmt (gsi));
! 		  }
! 	      delete_basic_block (bb);
! 	    }
! 	}
!     }
    FOR_EACH_BB (bb)
      {
        /* Remove dead PHI nodes.  */
*************** perform_tree_ssa_dce (bool aggressive)
*** 1197,1202 ****
--- 1265,1277 ----
    struct edge_list *el = NULL;
    bool something_changed = 0;
  
+   /* Preheaders are needed for SCEV to work.
+      Simple lateches and recorded exits improve chances that loop will
+      proved to be finite in testcases such as in loop-15.c and loop-24.c  */
+   if (aggressive)
+     loop_optimizer_init (LOOPS_NORMAL
+ 			 | LOOPS_HAVE_RECORDED_EXITS);
+ 
    tree_dce_init (aggressive);
  
    if (aggressive)
*************** perform_tree_ssa_dce (bool aggressive)
*** 1216,1221 ****
--- 1291,1299 ----
  
    find_obviously_necessary_stmts (el);
  
+   if (aggressive)
+     loop_optimizer_finalize ();
+ 
    longest_chain = 0;
    total_chain = 0;
    chain_ovfl = false;
Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 149199)
--- tree-flow.h	(working copy)
*************** unsigned int tree_ssa_unswitch_loops (vo
*** 745,751 ****
  unsigned int canonicalize_induction_variables (void);
  unsigned int tree_unroll_loops_completely (bool, bool);
  unsigned int tree_ssa_prefetch_arrays (void);
- unsigned int remove_empty_loops (void);
  void tree_ssa_iv_optimize (void);
  unsigned tree_predictive_commoning (void);
  tree canonicalize_loop_ivs (struct loop *, htab_t, tree *);
--- 745,750 ----
Index: passes.c
===================================================================
*** passes.c	(revision 149199)
--- passes.c	(working copy)
*************** init_optimization_passes (void)
*** 651,657 ****
  	  NEXT_PASS (pass_lim);
  	  NEXT_PASS (pass_tree_unswitch);
  	  NEXT_PASS (pass_scev_cprop);
- 	  NEXT_PASS (pass_empty_loop);
  	  NEXT_PASS (pass_record_bounds);
  	  NEXT_PASS (pass_check_data_deps);
  	  NEXT_PASS (pass_loop_distribution);
--- 651,656 ----


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