) > 0) { bb = single_succ (bb); /* This empty block could only lead outside the region. */ gcc_assert (! in_current_region_p (bb)); } /* And now check whether we should skip over inner loop. */ if (inner_loop_header_p (bb)) { struct loop *this_loop; struct loop *pred_loop = NULL; int i; edge e; for (this_loop = bb->loop_father; this_loop && this_loop != current_loop_nest; this_loop = loop_outer (this_loop)) pred_loop = this_loop; this_loop = pred_loop; gcc_assert (this_loop != NULL); exits = get_loop_exit_edges_unique_dests (this_loop); /* Traverse all loop headers. */ for (i = 0; exits.iterate (i, &e); i++) if (in_current_region_p (e->dest) || inner_loop_header_p (e->dest)) { vec next_exits = get_all_loop_exits (e->dest); if (next_exits.exists ()) { int j; edge ne; /* Add all loop exits for the current edge into the resulting vector. */ for (j = 0; next_exits.iterate (j, &ne); j++) exits.safe_push (ne); /* Remove the original edge. */ exits.ordered_remove (i); /* Decrease the loop counter so we won't skip anything. */ i--; continue; } } } return exits; } /* Flags to pass to compute_succs_info and FOR_EACH_SUCC. Any successor will fall into exactly one category. */ /* Include normal successors. */ #define SUCCS_NORMAL (1) /* Include back-edge successors. */ #define SUCCS_BACK (2) /* Include successors that are outside of the current region. */ #define SUCCS_OUT (4) /* When pipelining of the outer loops is enabled, skip innermost loops to their exits. */ #define SUCCS_SKIP_TO_LOOP_EXITS (8) /* Include all successors. */ #define SUCCS_ALL (SUCCS_NORMAL | SUCCS_BACK | SUCCS_OUT) /* We need to return a succ_iterator to avoid 'unitialized' warning during bootstrap. */ static inline succ_iterator _succ_iter_start (insn_t *succp, insn_t insn, int flags) { succ_iterator i; basic_block bb = BLOCK_FOR_INSN (insn); gcc_assert (INSN_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn)); i.flags = flags; /* Avoid 'uninitialized' warning. */ *succp = NULL; i.e1 = NULL; i.e2 = NULL; i.bb = bb; i.current_flags = 0; i.current_exit = -1; i.loop_exits.create (0); if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun) && BB_END (bb) != insn) { i.bb_end = false; /* Avoid 'uninitialized' warning. */ i.ei.index = 0; i.ei.container = 0; } else { i.ei = ei_start (bb->succs); i.bb_end = true; } return i; } static inline bool _succ_iter_cond (succ_iterator *ip, insn_t *succp, insn_t insn, bool check (edge, succ_iterator *)) { if (!ip->bb_end) { /* When we're in a middle of a basic block, return the next insn immediately, but only when SUCCS_NORMAL is set. */ if (*succp != NULL || (ip->flags & SUCCS_NORMAL) == 0) return false; *succp = NEXT_INSN (insn); ip->current_flags = SUCCS_NORMAL; return true; } else { while (1) { edge e_tmp = NULL; /* First, try loop exits, if we have them. */ if (ip->loop_exits.exists ()) { do { ip->loop_exits.iterate (ip->current_exit, &e_tmp); ip->current_exit++; } while (e_tmp && !check (e_tmp, ip)); if (!e_tmp) ip->loop_exits.release (); } /* If we have found a successor, then great. */ if (e_tmp) { ip->e1 = e_tmp; break; } /* If not, then try the next edge. */ while (ei_cond (ip->ei, &(ip->e1))) { basic_block bb = ip->e1->dest; /* Consider bb as a possible loop header. */ if ((ip->flags & SUCCS_SKIP_TO_LOOP_EXITS) && flag_sel_sched_pipelining_outer_loops && (!in_current_region_p (bb) || BLOCK_TO_BB (ip->bb->index) < BLOCK_TO_BB (bb->index))) { /* Get all loop exits recursively. */ ip->loop_exits = get_all_loop_exits (bb); if (ip->loop_exits.exists ()) { ip->current_exit = 0; /* Move the iterator now, because we won't do succ_iter_next until loop exits will end. */ ei_next (&(ip->ei)); break; } } /* bb is not a loop header, check as usual. */ if (check (ip->e1, ip)) break; ei_next (&(ip->ei)); } /* If loop_exits are non null, we have found an inner loop; do one more iteration to fetch an edge from these exits. */ if (ip->loop_exits.exists ()) continue; /* Otherwise, we've found an edge in a usual way. Break now. */ break; } if (ip->e1) { basic_block bb = ip->e2->dest; if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == after_recovery) *succp = exit_insn; else { *succp = sel_bb_head (bb); gcc_assert (ip->flags != SUCCS_NORMAL || *succp == NEXT_INSN (bb_note (bb))); gcc_assert (BLOCK_FOR_INSN (*succp) == bb); } return true; } else return false; } } static inline void _succ_iter_next (succ_iterator *ip) { gcc_assert (!ip->e2 || ip->e1); if (ip->bb_end && ip->e1 && !ip->loop_exits.exists ()) ei_next (&(ip->ei)); } /* Returns true when E1 is an eligible successor edge, possibly skipping empty blocks. When E2P is not null, the resulting edge is written there. FLAGS are used to specify whether back edges and out-of-region edges should be considered. */ static inline bool _eligible_successor_edge_p (edge e1, succ_iterator *ip) { edge e2 = e1; basic_block bb; int flags = ip->flags; bool src_outside_rgn = !in_current_region_p (e1->src); gcc_assert (flags != 0); if (src_outside_rgn) { /* Any successor of the block that is outside current region is ineligible, except when we're skipping to loop exits. */ gcc_assert (flags & (SUCCS_OUT | SUCCS_SKIP_TO_LOOP_EXITS)); if (flags & SUCCS_OUT) return false; } bb = e2->dest; /* Skip empty blocks, but be careful not to leave the region. */ while (1) { if (!sel_bb_empty_p (bb)) { edge ne; basic_block nbb; if (!sel_bb_empty_or_nop_p (bb)) break; ne = EDGE_SUCC (bb, 0); nbb = ne->dest; if (!in_current_region_p (nbb) && !(flags & SUCCS_OUT)) break; e2 = ne; bb = nbb; continue; } if (!in_current_region_p (bb) && !(flags & SUCCS_OUT)) return false; if (EDGE_COUNT (bb->succs) == 0) return false; e2 = EDGE_SUCC (bb, 0); bb = e2->dest; } /* Save the second edge for later checks. */ ip->e2 = e2; if (in_current_region_p (bb)) { /* BLOCK_TO_BB sets topological order of the region here. It is important to use real predecessor here, which is ip->bb, as we may well have e1->src outside current region, when skipping to loop exits. */ bool succeeds_in_top_order = (BLOCK_TO_BB (ip->bb->index) < BLOCK_TO_BB (bb->index)); /* This is true for the all cases except the last one. */ ip->current_flags = SUCCS_NORMAL; /* We are advancing forward in the region, as usual. */ if (succeeds_in_top_order) { /* We are skipping to loop exits here. */ gcc_assert (!src_outside_rgn || flag_sel_sched_pipelining_outer_loops); return !!(flags & SUCCS_NORMAL); } /* This is a back edge. During pipelining we ignore back edges, but only when it leads to the same loop. It can lead to the header of the outer loop, which will also be the preheader of the current loop. */ if (pipelining_p && e1->src->loop_father == bb->loop_father) return !!(flags & SUCCS_NORMAL); /* A back edge should be requested explicitly. */ ip->current_flags = SUCCS_BACK; return !!(flags & SUCCS_BACK); } ip->current_flags = SUCCS_OUT; return !!(flags & SUCCS_OUT); } #define FOR_EACH_SUCC_1(SUCC, ITER, INSN, FLAGS) \ for ((ITER) = _succ_iter_start (&(SUCC), (INSN), (FLAGS)); \ _succ_iter_cond (&(ITER), &(SUCC), (INSN), _eligible_successor_edge_p); \ _succ_iter_next (&(ITER))) #define FOR_EACH_SUCC(SUCC, ITER, INSN) \ FOR_EACH_SUCC_1 (SUCC, ITER, INSN, SUCCS_NORMAL) /* Return the current edge along which a successor was built. */ #define SUCC_ITER_EDGE(ITER) ((ITER)->e1) /* Return the next block of BB not running into inconsistencies. */ static inline basic_block bb_next_bb (basic_block bb) { switch (EDGE_COUNT (bb->succs)) { case 0: return bb->next_bb; case 1: return single_succ (bb); case 2: return FALLTHRU_EDGE (bb)->dest; default: return bb->next_bb; } gcc_unreachable (); }