assert (! in_current_region_p (bb));
    }

  /* And now check whether we should skip over inner loop.  */
  if (inner_loop_header_p (bb))
    {
      class loop *this_loop;
      class loop *pred_loop = NULL;
      int i;
      unsigned this_depth;
      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);
      this_depth = loop_depth (this_loop);

      /* Traverse all loop headers.  Be careful not to go back
	 to the outer loop's header (see PR 84206).  */
      for (i = 0; exits.iterate (i, &e); i++)
	if ((in_current_region_p (e->dest)
	     || (inner_loop_header_p (e->dest)))
	    && loop_depth (e->dest->loop_father) >= this_depth)
	  {
	    auto_vec<edge> 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.  */
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;
}

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;
    }
}

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.  */
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.  */
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;
    }
}

