diff options
-rw-r--r-- | gcc/ChangeLog | 56 | ||||
-rw-r--r-- | gcc/cfgloop.c | 242 | ||||
-rw-r--r-- | gcc/cfgloop.h | 40 | ||||
-rw-r--r-- | gcc/cfgloopanal.c | 29 | ||||
-rw-r--r-- | gcc/cfgloopmanip.c | 2 | ||||
-rw-r--r-- | gcc/ifcvt.c | 40 | ||||
-rw-r--r-- | gcc/lambda-code.c | 1 | ||||
-rw-r--r-- | gcc/loop-init.c | 2 | ||||
-rw-r--r-- | gcc/loop-unroll.c | 3 | ||||
-rw-r--r-- | gcc/passes.c | 2 | ||||
-rw-r--r-- | gcc/predict.c | 15 | ||||
-rw-r--r-- | gcc/tree-if-conv.c | 38 | ||||
-rw-r--r-- | gcc/tree-loop-linear.c | 3 | ||||
-rw-r--r-- | gcc/tree-vect-analyze.c | 26 | ||||
-rw-r--r-- | gcc/tree-vect-transform.c | 16 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 48 |
16 files changed, 171 insertions, 392 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fb3aa1b956b..c5f2f228323 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,59 @@ +2005-03-01 Zdenek Dvorak <dvorakz@suse.cz> + + * cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find, + flow_loop_pre_header_scan, flow_loop_pre_header_find, + flow_loop_scan): Removed. + (flow_loop_dump): Do not dump removed fields. + (flow_loop_free): Do not free removed fields. + (flow_loops_find): Flags argument removed. Do not call flow_loop_scan. + (loop_exit_edge_p): New function. + * cfgloop.h (struct loop): Removed fields pre_header, pre_header_edges, + num_pre_header_edges, entry_edges, num_entries, exit_edges, + num_exits, exits_doms. + (LOOP_TREE, LOOP_PRE_HEADER, LOOP_ENTRY_EDGES, LOOP_EXIT_EDGES, + LOOP_EDGES, LOOP_ALL): Removed. + (flow_loop_scan): Declaration removed. + (loop_exit_edge_p, mark_loop_exit_edges): Declare. + * cfgloopmanip.c (create_loop_notes): Do not pass flags to + flow_loops_find. + * ifcvt.c (mark_loop_exit_edges): Moved to cfgloopanal.c. + (if_convert): Call flow_loops_find and flow_loops_free + when calling mark_loop_exit_edges. + * cfgloopanal.c (mark_loop_exit_edges): Moved from + ifcvt.c. Removed the flow_loops_find, flow_loops_free and + free_dominance_info calls. + * loop-init.c (flow_loops_find): Ditto. + * passes.c (rest_of_handle_branch_prob): Ditto. + * lambda-code.c (perfect_nestify): Do not call flow_loops_find. + * loop-unroll.c (analyze_insns_in_loop): Do not use + EDGE_LOOP_EXIT. + * predict.c (predict_loops): Do not call flow_loop_scan. + Use get_loop_exit_edges. + (tree_estimate_probability): Do not pass flags to flow_loops_find. + * tree-if-conv.c (bb_with_exit_edge_p): Take loop as argument. + Do not use EDGE_LOOP_EXIT. + (tree_if_convert_cond_expr, if_convertible_modify_expr_p): Pass loop + to bb_with_exit_edge_p. + (if_convertible_loop_p): Do not call flow_loop_scan. Use + loop->single_exit. Do not use EDGE_LOOP_EXIT. Pass loop + to bb_with_exit_edge_p. + (combine_blocks): Pass loop to bb_with_exit_edge_p. Do not use + EDGE_LOOP_EXIT. + * tree-loop-linear.c (linear_transform_loops): Do not call + flow_loop_scan. Use loop->single_exit. + * tree-vect-analyze.c (vect_analyze_operations): Use loop->single_exit. + (vect_analyze_loop_form): Do not call flow_loop_scan. + * tree-vect-transform.c (vect_update_ivs_after_vectorizer): Use + loop->single_exit. + (vect_do_peeling_for_loop_bound): Use loop_preheader_edge and + loop->single_exit. + * tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop, + slpeel_make_loop_iterate_ntimes, slpeel_can_duplicate_loop_p, + slpeel_tree_duplicate_loop_to_edge_cfg, + slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge): + Use loop_preheader_edge and loop->single_exit. Do not call + flow_loop_scan. + 2005-03-01 Nick Clifton <nickc@redhat.com> * config/arm/arm.c (thumb_find_work_register): Check all of the diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 40a6de489cc..96175a8dbe1 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -41,11 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define LATCH_EDGE(E) (*(int *) (E)->aux) static void flow_loops_cfg_dump (const struct loops *, FILE *); -static void flow_loop_entry_edges_find (struct loop *); -static void flow_loop_exit_edges_find (struct loop *); static int flow_loop_nodes_find (basic_block, struct loop *); -static void flow_loop_pre_header_scan (struct loop *); -static basic_block flow_loop_pre_header_find (basic_block); static int flow_loop_level_compute (struct loop *); static void flow_loops_level_compute (struct loops *); static void establish_preds (struct loop *); @@ -135,27 +131,18 @@ flow_loop_dump (const struct loop *loop, FILE *file, fprintf (file, ";;\n;; Loop %d:%s\n", loop->num, loop->invalid ? " invalid" : ""); - fprintf (file, ";; header %d, latch %d, pre-header %d\n", - loop->header->index, loop->latch->index, - loop->pre_header ? loop->pre_header->index : -1); + fprintf (file, ";; header %d, latch %d\n", + loop->header->index, loop->latch->index); fprintf (file, ";; depth %d, level %d, outer %ld\n", loop->depth, loop->level, (long) (loop->outer ? loop->outer->num : -1)); - if (loop->pre_header_edges) - flow_edge_list_print (";; pre-header edges", loop->pre_header_edges, - loop->num_pre_header_edges, file); - - flow_edge_list_print (";; entry edges", loop->entry_edges, - loop->num_entries, file); fprintf (file, ";; nodes:"); bbs = get_loop_body (loop); for (i = 0; i < loop->num_nodes; i++) fprintf (file, " %d", bbs[i]->index); free (bbs); fprintf (file, "\n"); - flow_edge_list_print (";; exit edges", loop->exit_edges, - loop->num_exits, file); if (loop_dump_aux) loop_dump_aux (loop, file, verbose); @@ -194,12 +181,6 @@ flow_loops_dump (const struct loops *loops, FILE *file, void (*loop_dump_aux) (c void flow_loop_free (struct loop *loop) { - if (loop->pre_header_edges) - free (loop->pre_header_edges); - if (loop->entry_edges) - free (loop->entry_edges); - if (loop->exit_edges) - free (loop->exit_edges); if (loop->pred) free (loop->pred); free (loop); @@ -238,95 +219,6 @@ flow_loops_free (struct loops *loops) } } -/* Find the entry edges into the LOOP. */ - -static void -flow_loop_entry_edges_find (struct loop *loop) -{ - edge e; - edge_iterator ei; - int num_entries; - - num_entries = 0; - FOR_EACH_EDGE (e, ei, loop->header->preds) - { - if (flow_loop_outside_edge_p (loop, e)) - num_entries++; - } - - gcc_assert (num_entries); - - loop->entry_edges = xmalloc (num_entries * sizeof (edge *)); - - num_entries = 0; - FOR_EACH_EDGE (e, ei, loop->header->preds) - { - if (flow_loop_outside_edge_p (loop, e)) - loop->entry_edges[num_entries++] = e; - } - - loop->num_entries = num_entries; -} - -/* Find the exit edges from the LOOP. */ - -static void -flow_loop_exit_edges_find (struct loop *loop) -{ - edge e; - basic_block node, *bbs; - unsigned num_exits, i; - - loop->exit_edges = NULL; - loop->num_exits = 0; - - /* Check all nodes within the loop to see if there are any - successors not in the loop. Note that a node may have multiple - exiting edges. */ - num_exits = 0; - bbs = get_loop_body (loop); - for (i = 0; i < loop->num_nodes; i++) - { - edge_iterator ei; - node = bbs[i]; - FOR_EACH_EDGE (e, ei, node->succs) - { - basic_block dest = e->dest; - - if (!flow_bb_inside_loop_p (loop, dest)) - num_exits++; - } - } - - if (! num_exits) - { - free (bbs); - return; - } - - loop->exit_edges = xmalloc (num_exits * sizeof (edge *)); - - /* Store all exiting edges into an array. */ - num_exits = 0; - for (i = 0; i < loop->num_nodes; i++) - { - edge_iterator ei; - node = bbs[i]; - FOR_EACH_EDGE (e, ei, node->succs) - { - basic_block dest = e->dest; - - if (!flow_bb_inside_loop_p (loop, dest)) - { - e->flags |= EDGE_LOOP_EXIT; - loop->exit_edges[num_exits++] = e; - } - } - } - free (bbs); - loop->num_exits = num_exits; -} - /* Find the nodes contained within the LOOP with header HEADER. Return the number of nodes within the loop. */ @@ -434,77 +326,6 @@ mark_single_exit_loops (struct loops *loops) loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS; } -/* Find the root node of the loop pre-header extended basic block and - the edges along the trace from the root node to the loop header. */ - -static void -flow_loop_pre_header_scan (struct loop *loop) -{ - int num; - basic_block ebb; - edge e; - - loop->num_pre_header_edges = 0; - if (loop->num_entries != 1) - return; - - ebb = loop->entry_edges[0]->src; - if (ebb == ENTRY_BLOCK_PTR) - return; - - /* Count number of edges along trace from loop header to - root of pre-header extended basic block. Usually this is - only one or two edges. */ - for (num = 1; - EDGE_PRED (ebb, 0)->src != ENTRY_BLOCK_PTR && EDGE_COUNT (ebb->preds) == 1; - num++) - ebb = EDGE_PRED (ebb, 0)->src; - - loop->pre_header_edges = xmalloc (num * sizeof (edge)); - loop->num_pre_header_edges = num; - - /* Store edges in order that they are followed. The source of the first edge - is the root node of the pre-header extended basic block and the - destination of the last last edge is the loop header. */ - for (e = loop->entry_edges[0]; num; e = EDGE_PRED (e->src, 0)) - loop->pre_header_edges[--num] = e; -} - -/* Return the block for the pre-header of the loop with header - HEADER. Return NULL if there is no pre-header. */ - -static basic_block -flow_loop_pre_header_find (basic_block header) -{ - basic_block pre_header; - edge e; - edge_iterator ei; - - /* If block p is a predecessor of the header and is the only block - that the header does not dominate, then it is the pre-header. */ - pre_header = NULL; - FOR_EACH_EDGE (e, ei, header->preds) - { - basic_block node = e->src; - - if (node != ENTRY_BLOCK_PTR - && ! dominated_by_p (CDI_DOMINATORS, node, header)) - { - if (pre_header == NULL) - pre_header = node; - else - { - /* There are multiple edges into the header from outside - the loop so there is no pre-header block. */ - pre_header = NULL; - break; - } - } - } - - return pre_header; -} - static void establish_preds (struct loop *loop) { @@ -602,39 +423,6 @@ flow_loops_level_compute (struct loops *loops) flow_loop_level_compute (loops->tree_root); } -/* Scan a single natural loop specified by LOOP collecting information - about it specified by FLAGS. */ - -int -flow_loop_scan (struct loop *loop, int flags) -{ - if (flags & LOOP_ENTRY_EDGES) - { - /* Find edges which enter the loop header. - Note that the entry edges should only - enter the header of a natural loop. */ - flow_loop_entry_edges_find (loop); - } - - if (flags & LOOP_EXIT_EDGES) - { - /* Find edges which exit the loop. */ - flow_loop_exit_edges_find (loop); - } - - if (flags & LOOP_PRE_HEADER) - { - /* Look to see if the loop has a pre-header node. */ - loop->pre_header = flow_loop_pre_header_find (loop->header); - - /* Find the blocks within the extended basic block of - the loop pre-header. */ - flow_loop_pre_header_scan (loop); - } - - return 1; -} - /* A callback to update latch and header info for basic block JUMP created by redirecting an edge. */ @@ -800,14 +588,12 @@ initialize_loops_parallel_p (struct loops *loops) } /* Find all the natural loops in the function and save in LOOPS structure and - recalculate loop_depth information in basic block structures. FLAGS - controls which loop information is collected. Return the number of natural - loops found. */ + recalculate loop_depth information in basic block structures. + Return the number of natural loops found. */ int -flow_loops_find (struct loops *loops, int flags) +flow_loops_find (struct loops *loops) { - int i; int b; int num_loops; edge e; @@ -817,11 +603,6 @@ flow_loops_find (struct loops *loops, int flags) basic_block header; basic_block bb; - /* This function cannot be repeatedly called with different - flags to build up the loop information. The loop tree - must always be built if this function is called. */ - gcc_assert (flags & LOOP_TREE); - memset (loops, 0, sizeof *loops); /* We are going to recount the maximum loop depth, @@ -963,10 +744,6 @@ flow_loops_find (struct loops *loops, int flags) loop. */ flow_loops_level_compute (loops); - /* Scan the loops. */ - for (i = 1; i < num_loops; i++) - flow_loop_scan (loops->parray[i], flags); - loops->num = num_loops; initialize_loops_parallel_p (loops); } @@ -1523,3 +1300,12 @@ loop_preheader_edge (const struct loop *loop) return e; } + +/* Returns true if E is an exit of LOOP. */ + +bool +loop_exit_edge_p (const struct loop *loop, edge e) +{ + return (flow_bb_inside_loop_p (loop, e->src) + && !flow_bb_inside_loop_p (loop, e->dest)); +} diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 1562736faae..224d6cf18fb 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -69,9 +69,6 @@ struct loop /* Basic block of loop latch. */ basic_block latch; - /* Basic block of loop preheader or NULL if it does not exist. */ - basic_block pre_header; - /* For loop unrolling/peeling decision. */ struct lpt_decision lpt_decision; @@ -81,14 +78,6 @@ struct loop /* Average number of executed insns per iteration. */ unsigned av_ninsns; - /* Array of edges along the preheader extended basic block trace. - The source of the first edge is the root node of preheader - extended basic block, if it exists. */ - edge *pre_header_edges; - - /* Number of edges along the pre_header extended basic block trace. */ - int num_pre_header_edges; - /* The first block in the loop. This is not necessarily the same as the loop header. */ basic_block first; @@ -100,21 +89,6 @@ struct loop /* Number of blocks contained within the loop. */ unsigned num_nodes; - /* Array of edges that enter the loop. */ - edge *entry_edges; - - /* Number of edges that enter the loop. */ - int num_entries; - - /* Array of edges that exit the loop. */ - edge *exit_edges; - - /* Number of edges that exit the loop. */ - int num_exits; - - /* Bitmap of blocks that dominate all exits of the loop. */ - sbitmap exits_doms; - /* The loop nesting depth. */ int depth; @@ -254,23 +228,13 @@ struct loops extern struct loops *current_loops; -/* Flags for loop discovery. */ - -#define LOOP_TREE 1 /* Build loop hierarchy tree. */ -#define LOOP_PRE_HEADER 2 /* Analyze loop preheader. */ -#define LOOP_ENTRY_EDGES 4 /* Find entry edges. */ -#define LOOP_EXIT_EDGES 8 /* Find exit edges. */ -#define LOOP_EDGES (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES) -#define LOOP_ALL 15 /* All of the above */ - /* Loop recognition. */ -extern int flow_loops_find (struct loops *, int flags); +extern int flow_loops_find (struct loops *); extern void flow_loops_free (struct loops *); extern void flow_loops_dump (const struct loops *, FILE *, void (*)(const struct loop *, FILE *, int), int); extern void flow_loop_dump (const struct loop *, FILE *, void (*)(const struct loop *, FILE *, int), int); -extern int flow_loop_scan (struct loop *, int); extern void flow_loop_free (struct loop *); void mark_irreducible_loops (struct loops *); void mark_single_exit_loops (struct loops *); @@ -288,6 +252,8 @@ extern unsigned tree_num_loop_insns (struct loop *); extern int num_loop_insns (struct loop *); extern int average_num_loop_insns (struct loop *); extern unsigned get_loop_level (const struct loop *); +extern bool loop_exit_edge_p (const struct loop *, edge); +extern void mark_loop_exit_edges (struct loops *); /* Loops & cfg manipulation. */ extern basic_block *get_loop_body (const struct loop *); diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 6c625d6a974..f40a48f8202 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -565,3 +565,32 @@ global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses) return cost; } +/* Sets EDGE_LOOP_EXIT flag for all exits of LOOPS. */ + +void +mark_loop_exit_edges (struct loops *loops) +{ + basic_block bb; + edge e; + + if (loops->num <= 1) + return; + + FOR_EACH_BB (bb) + { + edge_iterator ei; + + /* Do not mark exits from the fake outermost loop. */ + if (!bb->loop_father->outer) + continue; + + FOR_EACH_EDGE (e, ei, bb->succs) + { + if (loop_exit_edge_p (bb->loop_father, e)) + e->flags |= EDGE_LOOP_EXIT; + else + e->flags &= ~EDGE_LOOP_EXIT; + } + } +} + diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index c07571014af..022624f574f 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1296,7 +1296,7 @@ create_loop_notes (void) NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG); #endif - flow_loops_find (&loops, LOOP_TREE); + flow_loops_find (&loops); free_dominance_info (CDI_DOMINATORS); if (loops.num > 1) { diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 39fced43b24..eb597d13f1f 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -110,38 +110,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block, basic_block, int); static void noce_emit_move_insn (rtx, rtx); static rtx block_has_only_trap (basic_block); -static void mark_loop_exit_edges (void); -/* Sets EDGE_LOOP_EXIT flag for all loop exits. */ -static void -mark_loop_exit_edges (void) -{ - struct loops loops; - basic_block bb; - edge e; - - flow_loops_find (&loops, LOOP_TREE); - free_dominance_info (CDI_DOMINATORS); - - if (loops.num > 1) - { - FOR_EACH_BB (bb) - { - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->succs) - { - if (find_common_loop (bb->loop_father, e->dest->loop_father) - != bb->loop_father) - e->flags |= EDGE_LOOP_EXIT; - else - e->flags &= ~EDGE_LOOP_EXIT; - } - } - } - - flow_loops_free (&loops); -} - /* Count the number of non-jump active insns in BB. */ static int @@ -3356,7 +3325,14 @@ if_convert (int x_life_data_ok) if ((! targetm.cannot_modify_jumps_p ()) && (!flag_reorder_blocks_and_partition || !no_new_pseudos || !targetm.have_named_sections)) - mark_loop_exit_edges (); + { + struct loops loops; + + flow_loops_find (&loops); + mark_loop_exit_edges (&loops); + flow_loops_free (&loops); + free_dominance_info (CDI_DOMINATORS); + } /* Compute postdominators if we think we'll use them. */ if (HAVE_conditional_execution || life_data_ok) diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c index 037be930a43..909c28dd371 100644 --- a/gcc/lambda-code.c +++ b/gcc/lambda-code.c @@ -2430,7 +2430,6 @@ perfect_nestify (struct loops *loops, } } free (bbs); - flow_loops_find (loops, LOOP_ALL); return perfect_nest_p (loop); } diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 5aa0db11a9c..b6a827ca2c6 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -56,7 +56,7 @@ loop_optimizer_init (FILE *dumpfile) /* Find the loops. */ - if (flow_loops_find (loops, LOOP_TREE) <= 1) + if (flow_loops_find (loops) <= 1) { /* No loops. */ flow_loops_free (loops); diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 4c7f6e2efce..c4f49d5629f 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -1669,8 +1669,7 @@ analyze_insns_in_loop (struct loop *loop) opt_info->loop_preheader = loop_preheader_edge (loop)->src; if (n_edges == 1 - && !(edges[0]->flags & EDGE_COMPLEX) - && (edges[0]->flags & EDGE_LOOP_EXIT)) + && !(edges[0]->flags & EDGE_COMPLEX)) { opt_info->loop_exit = loop_split_edge_with (edges[0], NULL_RTX); can_apply = true; diff --git a/gcc/passes.c b/gcc/passes.c index 956885ab717..65c183df383 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -781,7 +781,7 @@ rest_of_handle_branch_prob (void) /* Discover and record the loop depth at the head of each basic block. The loop infrastructure does the real job for us. */ - flow_loops_find (&loops, LOOP_TREE); + flow_loops_find (&loops); if (dump_file) flow_loops_dump (&loops, dump_file, NULL, 0); diff --git a/gcc/predict.c b/gcc/predict.c index 9ecf1e3269d..bf594acfc92 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -583,13 +583,13 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) { basic_block bb, *bbs; unsigned j; - int exits; + unsigned n_exits; struct loop *loop = loops_info->parray[i]; struct niter_desc desc; unsigned HOST_WIDE_INT niter; + edge *exits; - flow_loop_scan (loop, LOOP_EXIT_EDGES); - exits = loop->num_exits; + exits = get_loop_exit_edges (loop, &n_exits); if (rtlsimpleloops) { @@ -615,11 +615,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) } else { - edge *exits; - unsigned j, n_exits; struct tree_niter_desc niter_desc; - exits = get_loop_exit_edges (loop, &n_exits); for (j = 0; j < n_exits; j++) { tree niter = NULL; @@ -647,8 +644,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) } } - free (exits); } + free (exits); bbs = get_loop_body (loop); @@ -690,7 +687,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops) (e, PRED_LOOP_EXIT, (REG_BR_PROB_BASE - predictor_info [(int) PRED_LOOP_EXIT].hitrate) - / exits); + / n_exits); } /* Free basic blocks from get_loop_body. */ @@ -1293,7 +1290,7 @@ tree_estimate_probability (void) basic_block bb; struct loops loops_info; - flow_loops_find (&loops_info, LOOP_TREE); + flow_loops_find (&loops_info); if (dump_file && (dump_flags & TDF_DETAILS)) flow_loops_dump (&loops_info, dump_file, NULL, 0); diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 52bcfba69fb..bb832d24616 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -126,7 +126,7 @@ static void combine_blocks (struct loop *); static tree ifc_temp_var (tree, tree); static bool pred_blocks_visited_p (basic_block, bitmap *); static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop); -static bool bb_with_exit_edge_p (basic_block); +static bool bb_with_exit_edge_p (struct loop *, basic_block); /* List of basic blocks in if-conversion-suitable order. */ static basic_block *ifc_bbs; @@ -312,7 +312,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond, /* Now this conditional statement is redundant. Remove it. But, do not remove exit condition! Update exit condition using new condition. */ - if (!bb_with_exit_edge_p (bb_for_stmt (stmt))) + if (!bb_with_exit_edge_p (loop, bb_for_stmt (stmt))) { bsi_remove (bsi); cond = NULL_TREE; @@ -405,7 +405,7 @@ if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr) if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME && bb != loop->header - && !bb_with_exit_edge_p (bb)) + && !bb_with_exit_edge_p (loop, bb)) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -534,8 +534,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) return false; } - flow_loop_scan (loop, LOOP_ALL); - /* If only one block, no need for if-conversion. */ if (loop->num_nodes <= 2) { @@ -545,7 +543,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) } /* More than one loop exit is too much to handle. */ - if (loop->num_exits > 1) + if (!loop->single_exit) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "multiple exits\n"); @@ -557,8 +555,10 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) /* If one of the loop header's edge is exit edge then do not apply if-conversion. */ FOR_EACH_EDGE (e, ei, loop->header->succs) - if ( e->flags & EDGE_LOOP_EXIT) - return false; + { + if (loop_exit_edge_p (loop, e)) + return false; + } compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL); @@ -593,7 +593,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) if (!if_convertible_phi_p (loop, bb, phi)) return false; - if (bb_with_exit_edge_p (bb)) + if (bb_with_exit_edge_p (loop, bb)) exit_bb_seen = true; } @@ -874,7 +874,7 @@ combine_blocks (struct loop *loop) bb = ifc_bbs[i]; - if (!exit_bb && bb_with_exit_edge_p (bb)) + if (!exit_bb && bb_with_exit_edge_p (loop, bb)) exit_bb = bb; if (bb == exit_bb) @@ -890,11 +890,13 @@ combine_blocks (struct loop *loop) { /* Redirect non-exit edge to loop->latch. */ FOR_EACH_EDGE (e, ei, bb->succs) - if (!(e->flags & EDGE_LOOP_EXIT)) - { - redirect_edge_and_branch (e, loop->latch); - set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb); - } + { + if (!loop_exit_edge_p (loop, e)) + { + redirect_edge_and_branch (e, loop->latch); + set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb); + } + } } continue; } @@ -1056,17 +1058,17 @@ get_loop_body_in_if_conv_order (const struct loop *loop) return blocks; } -/* Return true if one of the basic block BB edge is loop exit. */ +/* Return true if one of the basic block BB edge is exit of LOOP. */ static bool -bb_with_exit_edge_p (basic_block bb) +bb_with_exit_edge_p (struct loop *loop, basic_block bb) { edge e; edge_iterator ei; bool exit_edge_found = false; FOR_EACH_EDGE (e, ei, bb->succs) - if (e->flags & EDGE_LOOP_EXIT) + if (loop_exit_edge_p (loop, e)) { exit_edge_found = true; break; diff --git a/gcc/tree-loop-linear.c b/gcc/tree-loop-linear.c index b8c6201ff88..03333046129 100644 --- a/gcc/tree-loop-linear.c +++ b/gcc/tree-loop-linear.c @@ -277,9 +277,8 @@ linear_transform_loops (struct loops *loops) depth = 1; for (temp = loop_nest->inner; temp; temp = temp->inner) { - flow_loop_scan (temp, LOOP_ALL); /* If we have a sibling loop or multiple exit edges, jump ship. */ - if (temp->next || temp->num_exits != 1) + if (temp->next || !temp->single_exit) { problem = true; break; diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index fd26c90687e..4736f1b4cfa 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -462,7 +462,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo) "not vectorized: can't create epilog loop 1."); return false; } - if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0])) + if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit)) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, LOOP_LOC (loop_vinfo))) @@ -2265,7 +2265,6 @@ vect_analyze_loop_form (struct loop *loop) loop_vec_info loop_vinfo; tree loop_cond; tree number_of_iterations = NULL; - bool rescan = false; LOC loop_loc; loop_loc = find_loop_location (loop); @@ -2282,8 +2281,7 @@ vect_analyze_loop_form (struct loop *loop) if (!loop->single_exit || loop->num_nodes != 2 - || EDGE_COUNT (loop->header->preds) != 2 - || loop->num_entries != 1) + || EDGE_COUNT (loop->header->preds) != 2) { if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc)) { @@ -2293,8 +2291,6 @@ vect_analyze_loop_form (struct loop *loop) fprintf (vect_dump, "not vectorized: too many BBs in loop."); else if (EDGE_COUNT (loop->header->preds) != 2) fprintf (vect_dump, "not vectorized: too many incoming edges."); - else if (loop->num_entries != 1) - fprintf (vect_dump, "not vectorized: too many entries."); } return NULL; @@ -2311,16 +2307,6 @@ vect_analyze_loop_form (struct loop *loop) return NULL; } - /* Make sure we have a preheader basic block. */ - if (!loop->pre_header || EDGE_COUNT (loop->pre_header->succs) != 1) - { - edge e = loop_preheader_edge (loop); - loop_split_edge_with (e, NULL); - if (vect_print_dump_info (REPORT_DETAILS, loop_loc)) - fprintf (vect_dump, "split preheader edge."); - rescan = true; - } - /* Make sure there exists a single-predecessor exit bb: */ if (EDGE_COUNT (loop->single_exit->dest->preds) != 1) { @@ -2330,7 +2316,6 @@ vect_analyze_loop_form (struct loop *loop) loop_split_edge_with (e, NULL); if (vect_print_dump_info (REPORT_DETAILS, loop_loc)) fprintf (vect_dump, "split exit edge."); - rescan = true; } else { @@ -2339,13 +2324,6 @@ vect_analyze_loop_form (struct loop *loop) return NULL; } } - - if (rescan) - { - flow_loop_scan (loop, LOOP_ALL); - /* Flow loop scan does not update loop->single_exit field. */ - loop->single_exit = loop->exit_edges[0]; - } if (empty_block_p (loop->header)) { diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 5f71256e14e..1935a738f71 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -1315,7 +1315,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters, edge update_e) { struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - basic_block exit_bb = loop->exit_edges[0]->dest; + basic_block exit_bb = loop->single_exit->dest; tree phi, phi1; basic_block update_bb = update_e->dest; @@ -1398,6 +1398,7 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *new_loop; edge update_e; + basic_block preheader; #ifdef ENABLE_CHECKING int loop_num; #endif @@ -1413,14 +1414,10 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, vect_generate_tmps_on_preheader (loop_vinfo, &ni_name, &ratio_mult_vf_name, ratio); - /* Update loop info. */ - loop->pre_header = loop_preheader_edge (loop)->src; - loop->pre_header_edges[0] = loop_preheader_edge (loop); - #ifdef ENABLE_CHECKING loop_num = loop->num; #endif - new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->exit_edges[0], + new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit, ratio_mult_vf_name, ni_name, false); #ifdef ENABLE_CHECKING gcc_assert (new_loop); @@ -1434,10 +1431,11 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio, is a bb after NEW_LOOP, where these IVs are not used. Find the edge that is on the path where the LOOP IVs are used and need to be updated. */ - if (EDGE_PRED (new_loop->pre_header, 0)->src == loop->exit_edges[0]->dest) - update_e = EDGE_PRED (new_loop->pre_header, 0); + 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 (new_loop->pre_header, 1); + update_e = EDGE_PRED (preheader, 1); /* Update IVs of original loop as if they were advanced by ratio_mult_vf_name steps. */ diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 8c447428780..7f8d84ae21f 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -373,7 +373,7 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop, 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->exit_edges[0]; + 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); @@ -518,8 +518,9 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge, if (entry_phis) { loop_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, - EDGE_SUCC (loop->latch, 0)); - guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, loop->entry_edges[0]); + loop_latch_edge (loop)); + guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, + loop_preheader_edge (loop)); } else /* exit phis */ { @@ -544,7 +545,7 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge, loop_arg = orig_def; } } - add_phi_arg (new_phi, loop_arg, loop->exit_edges[0]); + add_phi_arg (new_phi, loop_arg, loop->single_exit); add_phi_arg (new_phi, guard_arg, guard_edge); /* 3. Update phi in successor block. */ @@ -567,7 +568,7 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters) { tree indx_before_incr, indx_after_incr, cond_stmt, cond; tree orig_cond; - edge exit_edge = loop->exit_edges[0]; + edge exit_edge = loop->single_exit; block_stmt_iterator loop_cond_bsi; block_stmt_iterator incr_bsi; bool insert_after; @@ -636,7 +637,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, basic_block exit_dest; tree phi, phi_arg; - at_exit = (e == loop->exit_edges[0]); + at_exit = (e == loop->single_exit); if (!at_exit && e != loop_preheader_edge (loop)) return NULL; @@ -657,20 +658,21 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, return NULL; } - exit_dest = loop->exit_edges[0]->dest; + exit_dest = loop->single_exit->dest; was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS, exit_dest) == loop->header ? true : false); new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes); - copy_bbs (bbs, loop->num_nodes, new_bbs, NULL, 0, NULL, NULL); + copy_bbs (bbs, loop->num_nodes, new_bbs, + &loop->single_exit, 1, &new_loop->single_exit, NULL); /* 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->exit_edges[0]); + phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->single_exit); if (phi_arg) { edge new_loop_exit_edge; @@ -720,8 +722,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops, set_immediate_dominator (CDI_DOMINATORS, new_loop->header, preheader); } - flow_loop_scan (new_loop, LOOP_ALL); - flow_loop_scan (loop, LOOP_ALL); free (new_bbs); free (bbs); @@ -772,7 +772,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb, bool slpeel_can_duplicate_loop_p (struct loop *loop, edge e) { - edge exit_e = loop->exit_edges [0]; + 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); @@ -786,8 +786,7 @@ slpeel_can_duplicate_loop_p (struct loop *loop, edge e) || !loop->outer || loop->num_nodes != 2 || !empty_block_p (loop->latch) - || loop->num_exits != 1 - || loop->num_entries != 1 + || !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)) @@ -801,8 +800,8 @@ void slpeel_verify_cfg_after_peeling (struct loop *first_loop, struct loop *second_loop) { - basic_block loop1_exit_bb = first_loop->exit_edges[0]->dest; - basic_block loop2_entry_bb = second_loop->pre_header; + 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; /* A guard that controls whether the second_loop is to be executed or skipped @@ -812,7 +811,6 @@ slpeel_verify_cfg_after_peeling (struct loop *first_loop, */ gcc_assert (EDGE_COUNT (loop1_exit_bb->succs) == 2); - /* 1. Verify that one of the successors of first_loopt->exit is the preheader of second_loop. */ @@ -880,7 +878,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, basic_block bb_before_second_loop, bb_after_second_loop; basic_block bb_before_first_loop; basic_block bb_between_loops; - edge exit_e = loop->exit_edges [0]; + edge exit_e = loop->single_exit; LOC loop_loc; if (!slpeel_can_duplicate_loop_p (loop, e)) @@ -961,10 +959,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, bb_before_first_loop = split_edge (loop_preheader_edge (first_loop)); add_bb_to_loop (bb_before_first_loop, first_loop->outer); - bb_before_second_loop = split_edge (first_loop->exit_edges[0]); + bb_before_second_loop = split_edge (first_loop->single_exit); add_bb_to_loop (bb_before_second_loop, first_loop->outer); - flow_loop_scan (first_loop, LOOP_ALL); - flow_loop_scan (second_loop, LOOP_ALL); pre_condition = build2 (LE_EXPR, boolean_type_node, first_niters, integer_zero_node); @@ -1000,12 +996,10 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, orig_exit_bb: */ - bb_between_loops = split_edge (first_loop->exit_edges[0]); + bb_between_loops = split_edge (first_loop->single_exit); add_bb_to_loop (bb_between_loops, first_loop->outer); - bb_after_second_loop = split_edge (second_loop->exit_edges[0]); + bb_after_second_loop = split_edge (second_loop->single_exit); add_bb_to_loop (bb_after_second_loop, second_loop->outer); - flow_loop_scan (first_loop, LOOP_ALL); - flow_loop_scan (second_loop, LOOP_ALL); pre_condition = build2 (EQ_EXPR, boolean_type_node, first_niters, niters); skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition, @@ -1014,8 +1008,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, second_loop == new_loop); /* Flow loop scan does not update loop->single_exit field. */ - first_loop->single_exit = first_loop->exit_edges[0]; - second_loop->single_exit = second_loop->exit_edges[0]; + first_loop->single_exit = first_loop->single_exit; + second_loop->single_exit = second_loop->single_exit; /* 4. Make first-loop iterate FIRST_NITERS times, if requested. */ |