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] Access single_exit through accessor functions


Hello,

during some of the loop optimizations, we keep the information whether
loop has only a single exit edge.  This information is a bit difficult
to update (requiring separate handling in each transformation). I
believe now it would be better to keep the set of all exits from the
loop (this set should be fairly easy to update from cfghooks functions,
requiring no special handling anywhere); from this, it is easy to
determine whether the loop has only one exit.  Furthermore, knowing the
list of exits directly, without need to scan body of the loop, is
important in several loop optimization and analysis algorithms.
(I of course need to consider the costs of updating the lists of exit
edges, and possibly limit it to the optimizers that really need it).

This patch is the first step in this direction -- it makes us use
accessor functions to get the single exit edge, instead of reading it
from the loop structure directly.

Bootstrapped & regtested on i686. I will wait for a day to give people
chance to comment on the patch, and commit it then.

Zdenek

	* tree-loop-linear.c (linear_transform_loops): Use single_exit accessor
	functions.
	* tree-ssa-loop-niter.c (loop_only_exit_p): Ditto.
	* cfgloopmanip.c (update_single_exits_after_duplication,
	update_single_exit_for_duplicated_loop, loop_version): Ditto.
	* tree-scalar-evolution.c (get_loop_exit_condition,
	get_exit_conditions_rec, loop_closed_phi_def,
	number_of_iterations_in_loop, scev_const_prop): Ditto.
	* tree-ssa-loop-ivopts.c (single_dom_exit): Ditto.
	* modulo-sched.c (generate_prolog_epilog, loop_canon_p, sms_schedule):
	Ditto.
	* tree-ssa-loop-ivcanon.c (canonicalize_loop_induction_variables):
	Ditto.
	* tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
	slpeel_update_phi_nodes_for_guard1, slpeel_update_phi_nodes_for_guard2,
	slpeel_make_loop_iterate_ntimes,
	slpeel_tree_duplicate_loop_to_edge_cfg, slpeel_can_duplicate_loop_p,
	slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
	Ditto.
	* tree-if-conv.c (if_convertible_loop_p): Ditto.
	* tree-vect-analyze.c (vect_analyze_operations, vect_stmt_relevant_p,
	vect_analyze_loop_form): Ditto.
	* lambda-code.c (lambda_loopnest_to_gcc_loopnest, exit_phi_for_loop_p,
	can_convert_to_perfect_nest, perfect_nestify): Ditto.
	* tree-vect-transform.c (vect_create_epilog_for_reduction,
	vect_update_ivs_after_vectorizer, vect_do_peeling_for_loop_bound,
	vect_transform_loop): Ditto.
	* cfgloop.c (mark_single_exit_loops, verify_loop_structure): Ditto.
	(single_exit, set_single_exit): New functions.
	* cfgloop.h (struct loop): Rename single_exit field to single_exit_.
	(single_exit, set_single_exit): Declare.
	* doc/loop.texi: Undocument single_exit field.  Document single_exit
	accessor function.

Index: tree-loop-linear.c
===================================================================
*** tree-loop-linear.c	(revision 119038)
--- tree-loop-linear.c	(working copy)
*************** linear_transform_loops (struct loops *lo
*** 270,276 ****
                  ...
                 }
             } */
!       if (!loop_nest || !loop_nest->inner || !loop_nest->single_exit)
  	continue;
        VEC_truncate (tree, oldivs, 0);
        VEC_truncate (tree, invariants, 0);
--- 270,276 ----
                  ...
                 }
             } */
!       if (!loop_nest || !loop_nest->inner || !single_exit (loop_nest))
  	continue;
        VEC_truncate (tree, oldivs, 0);
        VEC_truncate (tree, invariants, 0);
*************** linear_transform_loops (struct loops *lo
*** 278,284 ****
        for (temp = loop_nest->inner; temp; temp = temp->inner)
  	{
  	  /* If we have a sibling loop or multiple exit edges, jump ship.  */
! 	  if (temp->next || !temp->single_exit)
  	    {
  	      problem = true;
  	      break;
--- 278,284 ----
        for (temp = loop_nest->inner; temp; temp = temp->inner)
  	{
  	  /* If we have a sibling loop or multiple exit edges, jump ship.  */
! 	  if (temp->next || !single_exit (temp))
  	    {
  	      problem = true;
  	      break;
Index: doc/loop.texi
===================================================================
*** doc/loop.texi	(revision 119038)
--- doc/loop.texi	(working copy)
*************** flag is not set for blocks and edges tha
*** 104,111 ****
  are in such an irreducible region (but it is set for the entry and exit
  edges of such a loop, if they lead to/from this region).
  @item @code{LOOPS_HAVE_MARKED_SINGLE_EXITS}: If a loop has exactly one
! exit edge, this edge is stored in @code{single_exit} field of the loop
! structure.  @code{NULL} is stored there otherwise.
  @end itemize
  
  These properties may also be computed/enforced later, using functions
--- 104,111 ----
  are in such an irreducible region (but it is set for the entry and exit
  edges of such a loop, if they lead to/from this region).
  @item @code{LOOPS_HAVE_MARKED_SINGLE_EXITS}: If a loop has exactly one
! exit edge, this edge is recorded in the loop structure.  @code{single_exit}
! function can be used to retrieve this edge.
  @end itemize
  
  These properties may also be computed/enforced later, using functions
*************** the basic blocks of the sub-loops).
*** 140,148 ****
  number of super-loops of the loop.
  @item @code{outer}, @code{inner}, @code{next}: The super-loop, the first
  sub-loop, and the sibling of the loop in the loops tree.
- @item @code{single_exit}: The exit edge of the loop, if the loop has
- exactly one exit and the loops were analyzed with
- LOOPS_HAVE_MARKED_SINGLE_EXITS.
  @end itemize
  
  There are other fields in the loop structures, many of them used only by
--- 140,145 ----
*************** with @code{EDGE_LOOP_EXIT} flag.
*** 176,181 ****
--- 173,181 ----
  @code{get_loop_body_in_bfs_order}: Enumerates the basic blocks in the
  loop in depth-first search order in reversed CFG, ordered by dominance
  relation, and breath-first search order, respectively.
+ @item @code{single_exit}: Returns the single exit edge of the loop, or
+ @code{NULL} if the loop has more than one exit.  You can only use this
+ function if LOOPS_HAVE_MARKED_SINGLE_EXITS property is used.
  @item @code{get_loop_exit_edges}: Enumerates the exit edges of a loop.
  @item @code{just_once_each_iteration_p}: Returns true if the basic block
  is executed exactly once during each iteration of a loop (that is, it
Index: tree-ssa-loop-niter.c
===================================================================
*** tree-ssa-loop-niter.c	(revision 119039)
--- tree-ssa-loop-niter.c	(working copy)
*************** loop_only_exit_p (struct loop *loop, edg
*** 1006,1012 ****
    unsigned i;
    tree call;
  
!   if (exit != loop->single_exit)
      return false;
  
    body = get_loop_body (loop);
--- 1006,1012 ----
    unsigned i;
    tree call;
  
!   if (exit != single_exit (loop))
      return false;
  
    body = get_loop_body (loop);
Index: cfgloopmanip.c
===================================================================
*** cfgloopmanip.c	(revision 119038)
--- cfgloopmanip.c	(working copy)
*************** update_single_exits_after_duplication (b
*** 770,780 ****
  
    for (; loop->outer; loop = loop->outer)
      {
!       if (!loop->single_exit)
  	continue;
  
!       if (loop->single_exit->src->flags & BB_DUPLICATED)
! 	loop->single_exit = NULL;
      }
  
    for (i = 0; i < nbbs; i++)
--- 770,780 ----
  
    for (; loop->outer; loop = loop->outer)
      {
!       if (!single_exit (loop))
  	continue;
  
!       if (single_exit (loop)->src->flags & BB_DUPLICATED)
! 	set_single_exit (loop, NULL);
      }
  
    for (i = 0; i < nbbs; i++)
*************** update_single_exit_for_duplicated_loop (
*** 788,794 ****
  {
    struct loop *copy = loop->copy;
    basic_block src, dest;
!   edge exit = loop->single_exit;
  
    if (!exit)
      return;
--- 788,794 ----
  {
    struct loop *copy = loop->copy;
    basic_block src, dest;
!   edge exit = single_exit (loop);
  
    if (!exit)
      return;
*************** update_single_exit_for_duplicated_loop (
*** 800,806 ****
  
    exit = find_edge (src, dest);
    gcc_assert (exit != NULL);
!   copy->single_exit = exit;
  }
  
  /* Updates single exit information for copies of ORIG_LOOPS and their subloops.
--- 800,806 ----
  
    exit = find_edge (src, dest);
    gcc_assert (exit != NULL);
!   set_single_exit (copy, exit);
  }
  
  /* Updates single exit information for copies of ORIG_LOOPS and their subloops.
*************** loop_version (struct loops *loops, struc
*** 1340,1348 ****
  		   cond_bb, true_edge, false_edge,
  		   false /* Do not redirect all edges.  */);
  
!   exit = loop->single_exit;
    if (exit)
!     nloop->single_exit = find_edge (get_bb_copy (exit->src), exit->dest);
  
    /* loopify redirected latch_edge. Update its PENDING_STMTS.  */
    lv_flush_pending_stmts (latch_edge);
--- 1340,1348 ----
  		   cond_bb, true_edge, false_edge,
  		   false /* Do not redirect all edges.  */);
  
!   exit = single_exit (loop);
    if (exit)
!     set_single_exit (nloop, find_edge (get_bb_copy (exit->src), exit->dest));
  
    /* loopify redirected latch_edge. Update its PENDING_STMTS.  */
    lv_flush_pending_stmts (latch_edge);
Index: tree-scalar-evolution.c
===================================================================
*** tree-scalar-evolution.c	(revision 119038)
--- tree-scalar-evolution.c	(working copy)
*************** tree 
*** 966,973 ****
  get_loop_exit_condition (struct loop *loop)
  {
    tree res = NULL_TREE;
!   edge exit_edge = loop->single_exit;
! 
    
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "(get_loop_exit_condition \n  ");
--- 966,972 ----
  get_loop_exit_condition (struct loop *loop)
  {
    tree res = NULL_TREE;
!   edge exit_edge = single_exit (loop);
    
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "(get_loop_exit_condition \n  ");
*************** get_exit_conditions_rec (struct loop *lo
*** 1003,1009 ****
    get_exit_conditions_rec (loop->inner, exit_conditions);
    get_exit_conditions_rec (loop->next, exit_conditions);
    
!   if (loop->single_exit)
      {
        tree loop_condition = get_loop_exit_condition (loop);
        
--- 1002,1008 ----
    get_exit_conditions_rec (loop->inner, exit_conditions);
    get_exit_conditions_rec (loop->next, exit_conditions);
    
!   if (single_exit (loop))
      {
        tree loop_condition = get_loop_exit_condition (loop);
        
*************** loop_closed_phi_def (tree var)
*** 2107,2113 ****
      return NULL_TREE;
  
    loop = loop_containing_stmt (SSA_NAME_DEF_STMT (var));
!   exit = loop->single_exit;
    if (!exit)
      return NULL_TREE;
  
--- 2106,2112 ----
      return NULL_TREE;
  
    loop = loop_containing_stmt (SSA_NAME_DEF_STMT (var));
!   exit = single_exit (loop);
    if (!exit)
      return NULL_TREE;
  
*************** number_of_iterations_in_loop (struct loo
*** 2485,2491 ****
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "(number_of_iterations_in_loop\n");
    
!   exit = loop->single_exit;
    if (!exit)
      goto end;
  
--- 2484,2490 ----
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "(number_of_iterations_in_loop\n");
    
!   exit = single_exit (loop);
    if (!exit)
      goto end;
  
*************** scev_const_prop (void)
*** 2961,2967 ****
  
        /* If we do not know exact number of iterations of the loop, we cannot
  	 replace the final value.  */
!       exit = loop->single_exit;
        if (!exit)
  	continue;
  
--- 2960,2966 ----
  
        /* If we do not know exact number of iterations of the loop, we cannot
  	 replace the final value.  */
!       exit = single_exit (loop);
        if (!exit)
  	continue;
  
Index: tree-ssa-loop-ivopts.c
===================================================================
*** tree-ssa-loop-ivopts.c	(revision 119038)
--- tree-ssa-loop-ivopts.c	(working copy)
*************** iv_cand (struct ivopts_data *data, unsig
*** 349,355 ****
  edge
  single_dom_exit (struct loop *loop)
  {
!   edge exit = loop->single_exit;
  
    if (!exit)
      return NULL;
--- 349,355 ----
  edge
  single_dom_exit (struct loop *loop)
  {
!   edge exit = single_exit (loop);
  
    if (!exit)
      return NULL;
Index: modulo-sched.c
===================================================================
*** modulo-sched.c	(revision 119038)
--- modulo-sched.c	(working copy)
*************** generate_prolog_epilog (partial_schedule
*** 755,762 ****
      duplicate_insns_of_cycles (ps, i + 1, last_stage, 0);
  
    /* Put the epilogue on the exit edge.  */
!   gcc_assert (loop->single_exit);
!   e = loop->single_exit;
    split_edge_and_insert (e, get_insns());
    end_sequence ();
  }
--- 755,762 ----
      duplicate_insns_of_cycles (ps, i + 1, last_stage, 0);
  
    /* Put the epilogue on the exit edge.  */
!   gcc_assert (single_exit (loop));
!   e = single_exit (loop);
    split_edge_and_insert (e, get_insns());
    end_sequence ();
  }
*************** loop_canon_p (struct loop *loop)
*** 814,820 ****
    if (loop->inner || ! loop->outer)
      return false;
  
!   if (!loop->single_exit)
      {
        if (dump_file)
  	{
--- 814,820 ----
    if (loop->inner || ! loop->outer)
      return false;
  
!   if (!single_exit (loop))
      {
        if (dump_file)
  	{
*************** sms_schedule (void)
*** 943,956 ****
  
        get_ebb_head_tail (bb, bb, &head, &tail);
        latch_edge = loop_latch_edge (loop);
!       gcc_assert (loop->single_exit);
!       if (loop->single_exit->count)
! 	trip_count = latch_edge->count / loop->single_exit->count;
  
        /* Perfrom SMS only on loops that their average count is above threshold.  */
  
        if ( latch_edge->count
!           && (latch_edge->count < loop->single_exit->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
  	{
  	  if (dump_file)
  	    {
--- 943,956 ----
  
        get_ebb_head_tail (bb, bb, &head, &tail);
        latch_edge = loop_latch_edge (loop);
!       gcc_assert (single_exit (loop));
!       if (single_exit (loop)->count)
! 	trip_count = latch_edge->count / single_exit (loop)->count;
  
        /* Perfrom SMS only on loops that their average count is above threshold.  */
  
        if ( latch_edge->count
!           && (latch_edge->count < single_exit (loop)->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
  	{
  	  if (dump_file)
  	    {
*************** sms_schedule (void)
*** 1037,1045 ****
        get_ebb_head_tail (loop->header, loop->header, &head, &tail);
  
        latch_edge = loop_latch_edge (loop);
!       gcc_assert (loop->single_exit);
!       if (loop->single_exit->count)
! 	trip_count = latch_edge->count / loop->single_exit->count;
  
        if (dump_file)
  	{
--- 1037,1045 ----
        get_ebb_head_tail (loop->header, loop->header, &head, &tail);
  
        latch_edge = loop_latch_edge (loop);
!       gcc_assert (single_exit (loop));
!       if (single_exit (loop)->count)
! 	trip_count = latch_edge->count / single_exit (loop)->count;
  
        if (dump_file)
  	{
Index: tree-ssa-loop-ivcanon.c
===================================================================
*** tree-ssa-loop-ivcanon.c	(revision 119038)
--- tree-ssa-loop-ivcanon.c	(working copy)
*************** canonicalize_loop_induction_variables (s
*** 283,289 ****
    niter = number_of_iterations_in_loop (loop);
    if (TREE_CODE (niter) == INTEGER_CST)
      {
!       exit = loop->single_exit;
        if (!just_once_each_iteration_p (loop, exit->src))
  	return false;
  
--- 283,289 ----
    niter = number_of_iterations_in_loop (loop);
    if (TREE_CODE (niter) == INTEGER_CST)
      {
!       exit = single_exit (loop);
        if (!just_once_each_iteration_p (loop, exit->src))
  	return false;
  
*************** canonicalize_loop_induction_variables (s
*** 297,303 ****
      {
        /* If the loop has more than one exit, try checking all of them
  	 for # of iterations determinable through scev.  */
!       if (!loop->single_exit)
  	niter = find_loop_niter (loop, &exit);
  
        /* Finally if everything else fails, try brute force evaluation.  */
--- 297,303 ----
      {
        /* If the loop has more than one exit, try checking all of them
  	 for # of iterations determinable through scev.  */
!       if (!single_exit (loop))
  	niter = find_loop_niter (loop, &exit);
  
        /* Finally if everything else fails, try brute force evaluation.  */
Index: tree-vectorizer.c
===================================================================
*** tree-vectorizer.c	(revision 119038)
--- tree-vectorizer.c	(working copy)
*************** slpeel_update_phis_for_duplicate_loop (s
*** 279,285 ****
    tree def;
    edge orig_loop_latch = loop_latch_edge (orig_loop);
    edge orig_entry_e = loop_preheader_edge (orig_loop);
!   edge new_loop_exit_e = new_loop->single_exit;
    edge new_loop_entry_e = loop_preheader_edge (new_loop);
    edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e);
  
--- 279,285 ----
    tree def;
    edge orig_loop_latch = loop_latch_edge (orig_loop);
    edge orig_entry_e = loop_preheader_edge (orig_loop);
!   edge new_loop_exit_e = single_exit (new_loop);
    edge new_loop_entry_e = loop_preheader_edge (new_loop);
    edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e);
  
*************** slpeel_update_phi_nodes_for_guard1 (edge
*** 519,525 ****
    tree name;
  
    /* Create new bb between loop and new_merge_bb.  */
!   *new_exit_bb = split_edge (loop->single_exit);
  
    new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
  
--- 519,525 ----
    tree name;
  
    /* Create new bb between loop and new_merge_bb.  */
!   *new_exit_bb = split_edge (single_exit (loop));
  
    new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
  
*************** slpeel_update_phi_nodes_for_guard1 (edge
*** 564,570 ****
                                   *new_exit_bb);
  
        /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
!       add_phi_arg (new_phi, loop_arg, loop->single_exit);
  
        /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
        gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
--- 564,570 ----
                                   *new_exit_bb);
  
        /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
!       add_phi_arg (new_phi, loop_arg, single_exit (loop));
  
        /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
        gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
*************** slpeel_update_phi_nodes_for_guard2 (edge
*** 644,650 ****
    tree arg;
  
    /* Create new bb between loop and new_merge_bb.  */
!   *new_exit_bb = split_edge (loop->single_exit);
  
    new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
  
--- 644,650 ----
    tree arg;
  
    /* Create new bb between loop and new_merge_bb.  */
!   *new_exit_bb = split_edge (single_exit (loop));
  
    new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
  
*************** slpeel_update_phi_nodes_for_guard2 (edge
*** 709,715 ****
                                   *new_exit_bb);
  
        /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
!       add_phi_arg (new_phi, loop_arg, loop->single_exit);
  
        /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
        gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
--- 709,715 ----
                                   *new_exit_bb);
  
        /* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop.  */
!       add_phi_arg (new_phi, loop_arg, single_exit (loop));
  
        /* 2.3. Update phi in successor of NEW_EXIT_BB:  */
        gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
*************** slpeel_make_loop_iterate_ntimes (struct 
*** 766,777 ****
  {
    tree indx_before_incr, indx_after_incr, cond_stmt, cond;
    tree orig_cond;
!   edge exit_edge = loop->single_exit;
    block_stmt_iterator loop_cond_bsi;
    block_stmt_iterator incr_bsi;
    bool insert_after;
    tree begin_label = tree_block_label (loop->latch);
!   tree exit_label = tree_block_label (loop->single_exit->dest);
    tree init = build_int_cst (TREE_TYPE (niters), 0);
    tree step = build_int_cst (TREE_TYPE (niters), 1);
    tree then_label;
--- 766,777 ----
  {
    tree indx_before_incr, indx_after_incr, cond_stmt, cond;
    tree orig_cond;
!   edge exit_edge = single_exit (loop);
    block_stmt_iterator loop_cond_bsi;
    block_stmt_iterator incr_bsi;
    bool insert_after;
    tree begin_label = tree_block_label (loop->latch);
!   tree exit_label = tree_block_label (single_exit (loop)->dest);
    tree init = build_int_cst (TREE_TYPE (niters), 0);
    tree step = build_int_cst (TREE_TYPE (niters), 1);
    tree then_label;
*************** slpeel_tree_duplicate_loop_to_edge_cfg (
*** 832,839 ****
    bool was_imm_dom;
    basic_block exit_dest; 
    tree phi, phi_arg;
  
!   at_exit = (e == loop->single_exit); 
    if (!at_exit && e != loop_preheader_edge (loop))
      return NULL;
  
--- 832,840 ----
    bool was_imm_dom;
    basic_block exit_dest; 
    tree phi, phi_arg;
+   edge exit, new_exit;
  
!   at_exit = (e == single_exit (loop)); 
    if (!at_exit && e != loop_preheader_edge (loop))
      return NULL;
  
*************** slpeel_tree_duplicate_loop_to_edge_cfg (
*** 854,875 ****
        return NULL;
      }
  
!   exit_dest = loop->single_exit->dest;
    was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS, 
  					  exit_dest) == loop->header ? 
  		 true : false);
  
    new_bbs = XNEWVEC (basic_block, loop->num_nodes);
  
    copy_bbs (bbs, loop->num_nodes, new_bbs,
! 	    &loop->single_exit, 1, &new_loop->single_exit, NULL,
  	    e->src);
  
    /* Duplicating phi args at exit bbs as coming 
       also from exit of duplicated loop.  */
    for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi))
      {
!       phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->single_exit);
        if (phi_arg)
  	{
  	  edge new_loop_exit_edge;
--- 855,878 ----
        return NULL;
      }
  
!   exit_dest = single_exit (loop)->dest;
    was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS, 
  					  exit_dest) == loop->header ? 
  		 true : false);
  
    new_bbs = XNEWVEC (basic_block, loop->num_nodes);
  
+   exit = single_exit (loop);
    copy_bbs (bbs, loop->num_nodes, new_bbs,
! 	    &exit, 1, &new_exit, NULL,
  	    e->src);
+   set_single_exit (new_loop, new_exit);
  
    /* Duplicating phi args at exit bbs as coming 
       also from exit of duplicated loop.  */
    for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi))
      {
!       phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, single_exit (loop));
        if (phi_arg)
  	{
  	  edge new_loop_exit_edge;
*************** slpeel_add_loop_guard (basic_block guard
*** 969,975 ****
  bool
  slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
  {
!   edge exit_e = loop->single_exit;
    edge entry_e = loop_preheader_edge (loop);
    tree orig_cond = get_loop_exit_condition (loop);
    block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
--- 972,978 ----
  bool
  slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
  {
!   edge exit_e = single_exit (loop);
    edge entry_e = loop_preheader_edge (loop);
    tree orig_cond = get_loop_exit_condition (loop);
    block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
*************** slpeel_can_duplicate_loop_p (struct loop
*** 983,989 ****
        || !loop->outer
        || loop->num_nodes != 2
        || !empty_block_p (loop->latch)
!       || !loop->single_exit
        /* Verify that new loop exit condition can be trivially modified.  */
        || (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi))
        || (e != exit_e && e != entry_e))
--- 986,992 ----
        || !loop->outer
        || loop->num_nodes != 2
        || !empty_block_p (loop->latch)
!       || !single_exit (loop)
        /* Verify that new loop exit condition can be trivially modified.  */
        || (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi))
        || (e != exit_e && e != entry_e))
*************** void
*** 997,1003 ****
  slpeel_verify_cfg_after_peeling (struct loop *first_loop,
                                   struct loop *second_loop)
  {
!   basic_block loop1_exit_bb = first_loop->single_exit->dest;
    basic_block loop2_entry_bb = loop_preheader_edge (second_loop)->src;
    basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src;
  
--- 1000,1006 ----
  slpeel_verify_cfg_after_peeling (struct loop *first_loop,
                                   struct loop *second_loop)
  {
!   basic_block loop1_exit_bb = single_exit (first_loop)->dest;
    basic_block loop2_entry_bb = loop_preheader_edge (second_loop)->src;
    basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src;
  
*************** slpeel_tree_peel_loop_to_edge (struct lo
*** 1076,1082 ****
    basic_block bb_before_first_loop;
    basic_block bb_between_loops;
    basic_block new_exit_bb;
!   edge exit_e = loop->single_exit;
    LOC loop_loc;
    
    if (!slpeel_can_duplicate_loop_p (loop, e))
--- 1079,1085 ----
    basic_block bb_before_first_loop;
    basic_block bb_between_loops;
    basic_block new_exit_bb;
!   edge exit_e = single_exit (loop);
    LOC loop_loc;
    
    if (!slpeel_can_duplicate_loop_p (loop, e))
*************** slpeel_tree_peel_loop_to_edge (struct lo
*** 1155,1161 ****
     */
  
    bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
!   bb_before_second_loop = split_edge (first_loop->single_exit);
  
    pre_condition =
      fold_build2 (LE_EXPR, boolean_type_node, first_niters, 
--- 1158,1164 ----
     */
  
    bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
!   bb_before_second_loop = split_edge (single_exit (first_loop));
  
    pre_condition =
      fold_build2 (LE_EXPR, boolean_type_node, first_niters, 
*************** slpeel_tree_peel_loop_to_edge (struct lo
*** 1194,1200 ****
     */
  
    bb_between_loops = new_exit_bb;
!   bb_after_second_loop = split_edge (second_loop->single_exit);
  
    pre_condition = 
  	fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
--- 1197,1203 ----
     */
  
    bb_between_loops = new_exit_bb;
!   bb_after_second_loop = split_edge (single_exit (second_loop));
  
    pre_condition = 
  	fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
Index: tree-if-conv.c
===================================================================
*** tree-if-conv.c	(revision 119038)
--- tree-if-conv.c	(working copy)
*************** if_convertible_loop_p (struct loop *loop
*** 521,527 ****
      }
  
    /* More than one loop exit is too much to handle.  */
!   if (!loop->single_exit)
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
  	fprintf (dump_file, "multiple exits\n");
--- 521,527 ----
      }
  
    /* More than one loop exit is too much to handle.  */
!   if (!single_exit (loop))
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
  	fprintf (dump_file, "multiple exits\n");
Index: tree-vect-analyze.c
===================================================================
*** tree-vect-analyze.c	(revision 119038)
--- tree-vect-analyze.c	(working copy)
*************** vect_analyze_operations (loop_vec_info l
*** 384,390 ****
                       "not vectorized: can't create epilog loop 1.");
            return false;
          }
!       if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
          {
            if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
              fprintf (vect_dump,
--- 384,390 ----
                       "not vectorized: can't create epilog loop 1.");
            return false;
          }
!       if (!slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
          {
            if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
              fprintf (vect_dump,
*************** vect_stmt_relevant_p (tree stmt, loop_ve
*** 1522,1528 ****
  	      /* We expect all such uses to be in the loop exit phis
  		 (because of loop closed form)   */
  	      gcc_assert (TREE_CODE (USE_STMT (use_p)) == PHI_NODE);
! 	      gcc_assert (bb == loop->single_exit->dest);
  
                *live_p = true;
  	    }
--- 1522,1528 ----
  	      /* We expect all such uses to be in the loop exit phis
  		 (because of loop closed form)   */
  	      gcc_assert (TREE_CODE (USE_STMT (use_p)) == PHI_NODE);
! 	      gcc_assert (bb == single_exit (loop)->dest);
  
                *live_p = true;
  	    }
*************** vect_analyze_loop_form (struct loop *loo
*** 1873,1885 ****
        return NULL;
      }
    
!   if (!loop->single_exit 
        || loop->num_nodes != 2
        || EDGE_COUNT (loop->header->preds) != 2)
      {
        if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
          {
!           if (!loop->single_exit)
              fprintf (vect_dump, "not vectorized: multiple exits.");
            else if (loop->num_nodes != 2)
              fprintf (vect_dump, "not vectorized: too many BBs in loop.");
--- 1873,1885 ----
        return NULL;
      }
    
!   if (!single_exit (loop) 
        || loop->num_nodes != 2
        || EDGE_COUNT (loop->header->preds) != 2)
      {
        if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
          {
!           if (!single_exit (loop))
              fprintf (vect_dump, "not vectorized: multiple exits.");
            else if (loop->num_nodes != 2)
              fprintf (vect_dump, "not vectorized: too many BBs in loop.");
*************** vect_analyze_loop_form (struct loop *loo
*** 1903,1911 ****
      }
  
    /* Make sure there exists a single-predecessor exit bb:  */
!   if (!single_pred_p (loop->single_exit->dest))
      {
!       edge e = loop->single_exit;
        if (!(e->flags & EDGE_ABNORMAL))
  	{
  	  split_loop_exit_edge (e);
--- 1903,1911 ----
      }
  
    /* Make sure there exists a single-predecessor exit bb:  */
!   if (!single_pred_p (single_exit (loop)->dest))
      {
!       edge e = single_exit (loop);
        if (!(e->flags & EDGE_ABNORMAL))
  	{
  	  split_loop_exit_edge (e);
Index: lambda-code.c
===================================================================
*** lambda-code.c	(revision 119038)
--- lambda-code.c	(working copy)
*************** lambda_loopnest_to_gcc_loopnest (struct 
*** 1875,1881 ****
  					     type,
  					     new_ivs,
  					     invariants, MIN_EXPR, &stmts);
!       exit = temp->single_exit;
        exitcond = get_loop_exit_condition (temp);
        bb = bb_for_stmt (exitcond);
        bsi = bsi_start (bb);
--- 1875,1881 ----
  					     type,
  					     new_ivs,
  					     invariants, MIN_EXPR, &stmts);
!       exit = single_exit (temp);
        exitcond = get_loop_exit_condition (temp);
        bb = bb_for_stmt (exitcond);
        bsi = bsi_start (bb);
*************** exit_phi_for_loop_p (struct loop *loop, 
*** 2211,2217 ****
    
    if (TREE_CODE (stmt) != PHI_NODE
        || PHI_NUM_ARGS (stmt) != 1
!       || bb_for_stmt (stmt) != loop->single_exit->dest)
      return false;
    
    return true;
--- 2211,2217 ----
    
    if (TREE_CODE (stmt) != PHI_NODE
        || PHI_NUM_ARGS (stmt) != 1
!       || bb_for_stmt (stmt) != single_exit (loop)->dest)
      return false;
    
    return true;
*************** can_convert_to_perfect_nest (struct loop
*** 2387,2393 ****
    /* We also need to make sure the loop exit only has simple copy phis in it,
       otherwise we don't know how to transform it into a perfect nest right
       now.  */
!   exitdest = loop->single_exit->dest;
    
    for (phi = phi_nodes (exitdest); phi; phi = PHI_CHAIN (phi))
      if (PHI_NUM_ARGS (phi) != 1)
--- 2387,2393 ----
    /* We also need to make sure the loop exit only has simple copy phis in it,
       otherwise we don't know how to transform it into a perfect nest right
       now.  */
!   exitdest = single_exit (loop)->dest;
    
    for (phi = phi_nodes (exitdest); phi; phi = PHI_CHAIN (phi))
      if (PHI_NUM_ARGS (phi) != 1)
*************** perfect_nestify (struct loops *loops,
*** 2463,2470 ****
    htab_t replacements = NULL;
  
    /* Create the new loop.  */
!   olddest = loop->single_exit->dest;
!   preheaderbb = split_edge (loop->single_exit);
    headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
    
    /* Push the exit phi nodes that we are moving.  */
--- 2463,2470 ----
    htab_t replacements = NULL;
  
    /* Create the new loop.  */
!   olddest = single_exit (loop)->dest;
!   preheaderbb = split_edge (single_exit (loop));
    headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
    
    /* Push the exit phi nodes that we are moving.  */
*************** perfect_nestify (struct loops *loops,
*** 2517,2530 ****
    newloop = duplicate_loop (loops, loop, olddest->loop_father);  
    newloop->header = headerbb;
    newloop->latch = latchbb;
!   newloop->single_exit = e;
    add_bb_to_loop (latchbb, newloop);
    add_bb_to_loop (bodybb, newloop);
    add_bb_to_loop (headerbb, newloop);
    set_immediate_dominator (CDI_DOMINATORS, bodybb, headerbb);
    set_immediate_dominator (CDI_DOMINATORS, headerbb, preheaderbb);
    set_immediate_dominator (CDI_DOMINATORS, preheaderbb, 
! 			   loop->single_exit->src);
    set_immediate_dominator (CDI_DOMINATORS, latchbb, bodybb);
    set_immediate_dominator (CDI_DOMINATORS, olddest, bodybb);
    /* Create the new iv.  */
--- 2517,2530 ----
    newloop = duplicate_loop (loops, loop, olddest->loop_father);  
    newloop->header = headerbb;
    newloop->latch = latchbb;
!   set_single_exit (newloop, e);
    add_bb_to_loop (latchbb, newloop);
    add_bb_to_loop (bodybb, newloop);
    add_bb_to_loop (headerbb, newloop);
    set_immediate_dominator (CDI_DOMINATORS, bodybb, headerbb);
    set_immediate_dominator (CDI_DOMINATORS, headerbb, preheaderbb);
    set_immediate_dominator (CDI_DOMINATORS, preheaderbb, 
! 			   single_exit (loop)->src);
    set_immediate_dominator (CDI_DOMINATORS, latchbb, bodybb);
    set_immediate_dominator (CDI_DOMINATORS, olddest, bodybb);
    /* Create the new iv.  */
Index: tree-vect-transform.c
===================================================================
*** tree-vect-transform.c	(revision 119038)
--- tree-vect-transform.c	(working copy)
*************** vect_create_epilog_for_reduction (tree v
*** 995,1003 ****
    /* 2.1 Create new loop-exit-phi to preserve loop-closed form:
          v_out1 = phi <v_loop>  */
  
!   exit_bb = loop->single_exit->dest;
    new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
!   SET_PHI_ARG_DEF (new_phi, loop->single_exit->dest_idx, vect_def);
    exit_bsi = bsi_start (exit_bb);
  
    /* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3 
--- 995,1003 ----
    /* 2.1 Create new loop-exit-phi to preserve loop-closed form:
          v_out1 = phi <v_loop>  */
  
!   exit_bb = single_exit (loop)->dest;
    new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
!   SET_PHI_ARG_DEF (new_phi, single_exit (loop)->dest_idx, vect_def);
    exit_bsi = bsi_start (exit_bb);
  
    /* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3 
*************** vect_update_ivs_after_vectorizer (loop_v
*** 3325,3331 ****
  				  edge update_e)
  {
    struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   basic_block exit_bb = loop->single_exit->dest;
    tree phi, phi1;
    basic_block update_bb = update_e->dest;
  
--- 3325,3331 ----
  				  edge update_e)
  {
    struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
!   basic_block exit_bb = single_exit (loop)->dest;
    tree phi, phi1;
    basic_block update_bb = update_e->dest;
  
*************** vect_do_peeling_for_loop_bound (loop_vec
*** 3436,3442 ****
  				   &ratio_mult_vf_name, ratio);
  
    loop_num  = loop->num; 
!   new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
  					    ratio_mult_vf_name, ni_name, false);
    gcc_assert (new_loop);
    gcc_assert (loop_num == loop->num);
--- 3436,3442 ----
  				   &ratio_mult_vf_name, ratio);
  
    loop_num  = loop->num; 
!   new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, single_exit (loop),
  					    ratio_mult_vf_name, ni_name, false);
    gcc_assert (new_loop);
    gcc_assert (loop_num == loop->num);
*************** vect_do_peeling_for_loop_bound (loop_vec
*** 3451,3457 ****
       is on the path where the LOOP IVs are used and need to be updated.  */
  
    preheader = loop_preheader_edge (new_loop)->src;
!   if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
      update_e = EDGE_PRED (preheader, 0);
    else
      update_e = EDGE_PRED (preheader, 1);
--- 3451,3457 ----
       is on the path where the LOOP IVs are used and need to be updated.  */
  
    preheader = loop_preheader_edge (new_loop)->src;
!   if (EDGE_PRED (preheader, 0)->src == single_exit (loop)->dest)
      update_e = EDGE_PRED (preheader, 0);
    else
      update_e = EDGE_PRED (preheader, 1);
*************** vect_transform_loop (loop_vec_info loop_
*** 3842,3851 ****
  	 here by adding a new (empty) block on the exit-edge of the loop,
  	 with the proper loop-exit phis to maintain loop-closed-form.  **/
        
!       merge_bb = loop->single_exit->dest;
        gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
!       new_exit_bb = split_edge (loop->single_exit);
!       new_exit_e = loop->single_exit;
        e = EDGE_SUCC (new_exit_bb, 0);
  
        for (orig_phi = phi_nodes (merge_bb); orig_phi; 
--- 3842,3851 ----
  	 here by adding a new (empty) block on the exit-edge of the loop,
  	 with the proper loop-exit phis to maintain loop-closed-form.  **/
        
!       merge_bb = single_exit (loop)->dest;
        gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
!       new_exit_bb = split_edge (single_exit (loop));
!       new_exit_e = single_exit (loop);
        e = EDGE_SUCC (new_exit_bb, 0);
  
        for (orig_phi = phi_nodes (merge_bb); orig_phi; 
Index: cfgloop.c
===================================================================
*** cfgloop.c	(revision 119039)
--- cfgloop.c	(working copy)
*************** mark_single_exit_loops (struct loops *lo
*** 254,260 ****
      {
        loop = loops->parray[i];
        if (loop)
! 	loop->single_exit = NULL;
      }
  
    FOR_EACH_BB (bb)
--- 254,260 ----
      {
        loop = loops->parray[i];
        if (loop)
! 	set_single_exit (loop, NULL);
      }
  
    FOR_EACH_BB (bb)
*************** mark_single_exit_loops (struct loops *lo
*** 276,285 ****
  	    {
  	      /* If we have already seen an exit, mark this by the edge that
  		 surely does not occur as any exit.  */
! 	      if (loop->single_exit)
! 		loop->single_exit = single_succ_edge (ENTRY_BLOCK_PTR);
  	      else
! 		loop->single_exit = e;
  	    }
  	}
      }
--- 276,285 ----
  	    {
  	      /* If we have already seen an exit, mark this by the edge that
  		 surely does not occur as any exit.  */
! 	      if (single_exit (loop))
! 		set_single_exit (loop, single_succ_edge (ENTRY_BLOCK_PTR));
  	      else
! 		set_single_exit (loop, e);
  	    }
  	}
      }
*************** mark_single_exit_loops (struct loops *lo
*** 290,297 ****
        if (!loop)
  	continue;
  
!       if (loop->single_exit == single_succ_edge (ENTRY_BLOCK_PTR))
! 	loop->single_exit = NULL;
      }
  
    loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS;
--- 290,297 ----
        if (!loop)
  	continue;
  
!       if (single_exit (loop) == single_succ_edge (ENTRY_BLOCK_PTR))
! 	set_single_exit (loop, NULL);
      }
  
    loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS;
*************** verify_loop_structure (struct loops *loo
*** 1188,1199 ****
  		   loop = loop->outer)
  		{
  		  sizes[loop->num]++;
! 		  if (loop->single_exit
! 		      && loop->single_exit != e)
  		    {
  		      error ("wrong single exit %d->%d recorded for loop %d",
! 			     loop->single_exit->src->index,
! 			     loop->single_exit->dest->index,
  			     loop->num);
  		      error ("right exit is %d->%d",
  			     e->src->index, e->dest->index);
--- 1188,1199 ----
  		   loop = loop->outer)
  		{
  		  sizes[loop->num]++;
! 		  if (single_exit (loop)
! 		      && single_exit (loop) != e)
  		    {
  		      error ("wrong single exit %d->%d recorded for loop %d",
! 			     single_exit (loop)->src->index,
! 			     single_exit (loop)->dest->index,
  			     loop->num);
  		      error ("right exit is %d->%d",
  			     e->src->index, e->dest->index);
*************** verify_loop_structure (struct loops *loo
*** 1210,1228 ****
  	    continue;
  
  	  if (sizes[i] == 1
! 	      && !loop->single_exit)
  	    {
  	      error ("single exit not recorded for loop %d", loop->num);
  	      err = 1;
  	    }
  
  	  if (sizes[i] != 1
! 	      && loop->single_exit)
  	    {
  	      error ("loop %d should not have single exit (%d -> %d)",
  		     loop->num,
! 		     loop->single_exit->src->index,
! 		     loop->single_exit->dest->index);
  	      err = 1;
  	    }
  	}
--- 1210,1228 ----
  	    continue;
  
  	  if (sizes[i] == 1
! 	      && !single_exit (loop))
  	    {
  	      error ("single exit not recorded for loop %d", loop->num);
  	      err = 1;
  	    }
  
  	  if (sizes[i] != 1
! 	      && single_exit (loop))
  	    {
  	      error ("loop %d should not have single exit (%d -> %d)",
  		     loop->num,
! 		     single_exit (loop)->src->index,
! 		     single_exit (loop)->dest->index);
  	      err = 1;
  	    }
  	}
*************** loop_exit_edge_p (const struct loop *loo
*** 1262,1264 ****
--- 1262,1281 ----
    return (flow_bb_inside_loop_p (loop, e->src)
  	  && !flow_bb_inside_loop_p (loop, e->dest));
  }
+ 
+ /* Returns the single exit edge of LOOP, or NULL if LOOP has either no exit
+    or more than one exit.  */
+ 
+ edge
+ single_exit (const struct loop *loop)
+ {
+   return loop->single_exit_;
+ }
+ 
+ /* Records E as a single exit edge of LOOP.  */
+ 
+ void
+ set_single_exit (struct loop *loop, edge e)
+ {
+   loop->single_exit_ = e;
+ }
Index: cfgloop.h
===================================================================
*** cfgloop.h	(revision 119039)
--- cfgloop.h	(working copy)
*************** struct loop
*** 148,154 ****
  
    /* If not NULL, loop has just single exit edge stored here (edges to the
       EXIT_BLOCK_PTR do not count.  */
!   edge single_exit;
  
    /* True when the loop does not carry data dependences, and
       consequently the iterations can be executed in any order.  False
--- 148,154 ----
  
    /* If not NULL, loop has just single exit edge stored here (edges to the
       EXIT_BLOCK_PTR do not count.  */
!   edge single_exit_;
  
    /* True when the loop does not carry data dependences, and
       consequently the iterations can be executed in any order.  False
*************** extern basic_block *get_loop_body (const
*** 223,228 ****
--- 223,230 ----
  extern basic_block *get_loop_body_in_dom_order (const struct loop *);
  extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
  extern VEC (edge, heap) *get_loop_exit_edges (const struct loop *);
+ edge single_exit (const struct loop *);
+ void set_single_exit (struct loop *, edge);
  extern unsigned num_loop_branches (const struct loop *);
  
  extern edge loop_preheader_edge (const struct loop *);


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