/* Loop manipulation code for GNU compiler.
   Copyright (C) 2002-2021 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "cfganal.h"
#include "cfgloop.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "tree-ssa-loop-manip.h"
#include "dumpfile.h"

static void copy_loops_to (class loop **, int,
			   class loop *);
static void loop_redirect_edge (edge, basic_block);
static void remove_bbs (basic_block *, int);
static bool rpe_enum_p (const_basic_block, const void *);
static int find_path (edge, basic_block **);
static void fix_loop_placements (class loop *, bool *);
static bool fix_bb_placement (basic_block);
static void fix_bb_placements (basic_block, bool *, bitmap);

/* Checks whether basic block BB is dominated by DATA.  */
static bool
rpe_enum_p (const_basic_block bb, const void *data)
{
  return dominated_by_p (CDI_DOMINATORS, bb, (const_basic_block) data);
}

/* Remove basic blocks BBS.  NBBS is the number of the basic blocks.  */

static void
remove_bbs (basic_block *bbs, int nbbs)
{
  int i;

  for (i = 0; i < nbbs; i++)
    delete_basic_block (bbs[i]);
}

/* Find path -- i.e. the basic blocks dominated by edge E and put them
   into array BBS, that will be allocated large enough to contain them.
   E->dest must have exactly one predecessor for this to work (it is
   easy to achieve and we do not put it here because we do not want to
   alter anything by this function).  The number of basic blocks in the
   path is returned.  */
static int
find_path (edge e, basic_block **bbs)
{
  gcc_assert (EDGE_COUNT (e->dest->preds) <= 1);

  /* Find bbs in the path.  */
  *bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
  return dfs_enumerate_from (e->dest, 0, rpe_enum_p, *bbs,
			     n_basic_blocks_for_fn (cfun), e->dest);
}

/* Fix placement of basic block BB inside loop hierarchy --
   Let L be a loop to that BB belongs.  Then every successor of BB must either
     1) belong to some superloop of loop L, or
     2) be a header of loop K such that K->outer is superloop of L
   Returns true if we had to move BB into other loop to enforce this condition,
   false if the placement of BB was already correct (provided that placements
   of its successors are correct).  */
static bool
fix_bb_placement (basic_block bb)
{
  edge e;
  edge_iterator ei;
  class loop *loop = current_loops->tree_root, *act;

  FOR_EACH_EDGE (e, ei, bb->succs)
    {
      if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
	continue;

      act = e->dest->loop_father;
      if (act->header == e->dest)
	act = loop_outer (act);

      if (flow_loop_nested_p (loop, act))
	loop = act;
    }

  if (loop == bb->loop_father)
    return false;

  remove_bb_from_loops (bb);
  add_bb_to_loop (bb, loop);

  return true;
}

/* Fix placement of LOOP inside loop tree, i.e. find the innermost superloop
   of LOOP to that leads at least one exit edge of LOOP, and set it
   as the immediate superloop of LOOP.  Return true if the immediate superloop
   of LOOP changed.

   IRRED_INVALIDATED is set to true if a change in the loop structures might
   invalidate the information about irreducible regions.  */

static bool
fix_loop_placement (class loop *loop, bool *irred_invalidated)
{
  unsigned i;
  edge e;
  auto_vec<edge> exits = get_loop_exit_edges (loop);
  class loop *father = current_loops->tree_root, *act;
  bool ret = false;

  FOR_EACH_VEC_ELT (exits, i, e)
    {
      act = find_common_loop (loop, e->dest->loop_father);
      if (flow_loop_nested_p (father, act))
	father = act;
    }

  if (father != loop_outer (loop))
    {
      for (act = loop_outer (loop); act != father; act = loop_outer (act))
	act->num_nodes -= loop->num_nodes;
      flow_loop_tree_node_remove (loop);
      flow_loop_tree_node_add (father, loop);

      /* The exit edges of LOOP no longer exits its original immediate
	 superloops; remove them from the appropriate exit lists.  */
      FOR_EACH_VEC_ELT (exits, i, e)
	{
	  /* We may need to recompute irreducible loops.  */
	  if (e->flags & EDGE_IRREDUCIBLE_LOOP)
	    *irred_invalidated = true;
	  rescan_loop_exit (e, false, false);
	}

      ret = true;
    }

  return ret;
}

/* Fix placements of basic blocks inside loop hierarchy stored in loops; i.e.
   enforce condition stated in description of fix_bb_placement. We
   start from basic block FROM that had some of its successors removed, so that
   his placement no longer has to be correct, and iteratively fix placement of
   its predecessors that may change if placement of FROM changed.  Also fix
   placement of subloops of FROM->loop_father, that might also be altered due
   to this change; the condition for them is similar, except that instead of
   successors we consider edges coming out of the loops.

   If the changes may invalidate the information about irreducible regions,
   IRRED_INVALIDATED is set to true.  

   If LOOP_CLOSED_SSA_INVLIDATED is non-zero then all basic blocks with
   changed loop_father are collected there. */

static void
fix_bb_placements (basic_block from,
		   bool *irred_invalidated,
		   bitmap loop_closed_ssa_invalidated)
{
  basic_block *queue, *qtop, *qbeg, *qend;
  class loop *base_loop, *target_loop;
  edge e;

  /* We pass through blocks back-reachable from FROM, testing whether some
     of their successors moved to outer loop.  It may be necessary to
     iterate several times, but it is finite, as we stop unless we move
     the basic block up the loop structure.  The whole story is a bit
     more complicated due to presence of subloops, those are moved using
     fix_loop_placement.  */

  base_loop = from->loop_father;
  /* If we are already in the outermost loop, the basic blocks cannot be moved
     outside of it.  If FROM is the header of the base loop, it cannot be moved
     outside of it, either.  In both cases, we can end now.  */
  if (base_loop == current_loops->tree_root
      || from == base_loop->header)
    return;

  auto_sbitmap in_queue (last_basic_block_for_fn (cfun));
  bitmap_clear (in_queue);
  bitmap_set_bit (in_queue, from->index);
  /* Prevent us from going out of the base_loop.  */
  bitmap_set_bit (in_queue, base_loop->header->index);

  queue = XNEWVEC (basic_block, base_loop->num_nodes + 1);
  qtop = queue + base_loop->num_nodes + 1;
  qbeg = queue;
  qend = queue + 1;
  *qbeg = from;

  while (qbeg != qend)
    {
      edge_iterator ei;
      from = *qbeg;
      qbeg++;
      if (qbeg == qtop)
	qbeg = queue;
      bitmap_clear_bit (in_queue, from->index);

      if (from->loop_father->header == from)
	{
	  /* Subloop header, maybe move the loop upward.  */
	  if (!fix_loop_placement (from->loop_father, irred_invalidated))
	    continue;
	  target_loop = loop_outer (from->loop_father);
	  if (loop_closed_ssa_invalidated)
	    {
	      basic_block *bbs = get_loop_body (from->loop_father);
	      for (unsigned i = 0; i < from->loop_father->num_nodes; ++i)
		bitmap_set_bit (loop_closed_ssa_invalidated, bbs[i]->index);
	      free (bbs);
	    }
	}
      else
	{
	  /* Ordinary basic block.  */
	  if (!fix_bb_placement (from))
	    continue;
	  target_loop = from->loop_father;
	  if (loop_closed_ssa_invalidated)
	    bitmap_set_bit (loop_closed_ssa_invalidated, from->index);
	}

      FOR_EACH_EDGE (e, ei, from->succs)
	{
	  if (e->flags & EDGE_IRREDUCIBLE_LOOP)
	    *irred_invalidated = true;
	}

      /* Something has changed, insert predecessors into queue.  */
      FOR_EACH_EDGE (e, ei, from->preds)
	{
	  basic_block pred = e->src;
	  class loop *nca;

	  if (e->flags & EDGE_IRREDUCIBLE_LOOP)
	    *irred_invalidated = true;

	  if (bitmap_bit_p (in_queue, pred->index))
	    continue;

	  /* If it is subloop, then it either was not moved, or
	     the path up the loop tree from base_loop do not contain
	     it.  */
	  nca = find_common_loop (pred->loop_father, base_loop);
	  if (pred->loop_father != base_loop
	      && (nca == base_loop
		  || nca != pred->loop_father))
	    pred = pred->loop_father->header;
	  else if (!flow_loop_nested_p (target_loop, pred->loop_father))
	    {
	      /* If PRED is already higher in the loop hierarchy than the
		 TARGET_LOOP to that we moved FROM, the change of the position
		 of FROM does not affect the position of PRED, so there is no
		 point in processing it.  */
	      continue;
	    }

	  if (bitmap_bit_p (in_queue, pred->index))
	    continue;

	  /* Schedule the basic block.  */
	  *qend = pred;
	  qend++;
	  if (qend == qtop)
	    qend = queue;
	  bitmap_set_bit (in_queue, pred->index);
	}
    }
  free (queue);
}

/* Removes path beginning at edge E, i.e. remove basic blocks dominated by E
   and update loop structures and dominators.  Return true if we were able
   to remove the path, false otherwise (and nothing is affected then).  */
bool
remove_path (edge e, bool *irred_invalidated,
	     bitmap loop_closed_ssa_invalidated)
{
  edge ae;
  basic_block *rem_bbs, *bord_bbs, from, bb;
  vec<basic_block> dom_bbs;
  int i, nrem, n_bord_bbs;
  bool local_irred_invalidated = false;
  edge_iterator ei;
  class loop *l, *f;

  if (! irred_invalidated)
    irred_invalidated = &local_irred_invalidated;

  if (!can_remove_branch_p (e))
    return false;

  /* Keep track of whether we need to update information about irreducible
     regions.  This is the case if the removed area is a part of the
     irreducible region, or if the set of basic blocks that belong to a loop
     that is inside an irreducible region is changed, or if such a loop is
     removed.  */
  if (e->flags & EDGE_IRREDUCIBLE_LOOP)
    *irred_invalidated = true;

  /* We need to check whether basic blocks are dominated by the edge
     e, but we only have basic block dominators.  This is easy to
     fix -- when e->dest has exactly one predecessor, this corresponds
     to blocks dominated by e->dest, if not, split the edge.  */
  if (!single_pred_p (e->dest))
    e = single_pred_edge (split_edge (e));

  /* It may happen that by removing path we remove one or more loops
     we belong to.  In this case first unloop the loops, then proceed
     normally.   We may assume that e->dest is not a header of any loop,
     as it now has exactly one predecessor.  */
  for (l = e->src->loop_father; loop_outer (l); l = f)
    {
      f = loop_outer (l);
      if (dominated_by_p (CDI_DOMINATORS, l->latch, e->dest))
        unloop (l, irred_invalidated, loop_closed_ssa_invalidated);
    }

  /* Identify the path.  */
  nrem = find_path (e, &rem_bbs);

  n_bord_bbs = 0;
  bord_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
  auto_sbitmap seen (last_basic_block_for_fn (cfun));
  bitmap_clear (seen);

  /* Find "border" hexes -- i.e. those with predecessor in removed path.  */
  for (i = 0; i < nrem; i++)
    bitmap_set_bit (seen, rem_bbs[i]->index);
  if (!*irred_invalidated)
    FOR_EACH_EDGE (ae, ei, e->src->succs)
      if (ae != e && ae->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
	  && !bitmap_bit_p (seen, ae->dest->index)
	  && ae->flags & EDGE_IRREDUCIBLE_LOOP)
	{
	  *irred_invalidated = true;
	  break;
	}

  for (i = 0; i < nrem; i++)
    {
      FOR_EACH_EDGE (ae, ei, rem_bbs[i]->succs)
	if (ae->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
	    && !bitmap_bit_p (seen, ae->dest->index))
	  {
	    bitmap_set_bit (seen, ae->dest->index);
	    bord_bbs[n_bord_bbs++] = ae->dest;

	    if (ae->flags & EDGE_IRREDUCIBLE_LOOP)
	      *irred_invalidated = true;
	  }
    }

  /* Remove the path.  */
  from = e->src;
  remove_branch (e);
  dom_bbs.create (0);

  /* Cancel loops contained in the path.  */
  for (i = 0; i < nrem; i++)
    if (rem_bbs[i]->loop_father->header == rem_bbs[i])
      cancel_loop_tree (rem_bbs[i]->loop_father);

  remove_bbs (rem_bbs, nrem);
  free (rem_bbs);

  /* Find blocks whose dominators may be affected.  */
  bitmap_clear (seen);
  for (i = 0; i < n_bord_bbs; i++)
    {
      basic_block ldom;

      bb = get_immediate_dominator (CDI_DOMINATORS, bord_bbs[i]);
      if (bitmap_bit_p (seen, bb->index))
	continue;
      bitmap_set_bit (seen, bb->index);

      for (ldom = first_dom_son (CDI_DOMINATORS, bb);
	   ldom;
	   ldom = next_dom_son (CDI_DOMINATORS, ldom))
	if (!dominated_by_p (CDI_DOMINATORS, from, ldom))
	  dom_bbs.safe_push (ldom);
    }

  /* Recount dominators.  */
  iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, true);
  dom_bbs.release ();
  free (bord_bbs);

  /* Fix placements of basic blocks inside loops and the placement of
     loops in the loop tree.  */
  fix_bb_placements (from, irred_invalidated, loop_closed_ssa_invalidated);
  fix_loop_placements (from->loop_father, irred_invalidated);

  if (local_irred_invalidated
      && loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
    mark_irreducible_loops ();

  return true;
}

/* Creates place for a new LOOP in loops structure of FN.  */

void
place_new_loop (struct function *fn, class loop *loop)
{
  loop->num = number_of_loops (fn);
  vec_safe_push (loops_for_fn (fn)->larray, loop);
}

/* Given LOOP structure with filled header and latch, find the body of the
   corresponding loop and add it to loops tree.  Insert the LOOP as a son of
   outer.  */

void
add_loop (class loop *loop, class loop *outer)
{
  basic_block *bbs;
  int i, n;
  class loop *subloop;
  edge e;
  edge_iterator ei;

  /* Add it to loop structure.  */
  place_new_loop (cfun, loop);
  flow_loop_tree_node_add (outer, loop);

  /* Find its nodes.  */
  bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
  n = get_loop_body_with_size (loop, bbs, n_basic_blocks_for_fn (cfun));

  for (i = 0; i < n; i++)
    {
      if (bbs[i]->loop_father == outer)
	{
	  remove_bb_from_loops (bbs[i]);
	  add_bb_to_loop (bbs[i], loop);
	  continue;
	}

      loop->num_nodes++;

      /* If we find a direct subloop of OUTER, move it to LOOP.  */
      subloop = bbs[i]->loop_father;
      if (loop_outer (subloop) == outer
	  && subloop->header == bbs[i])
	{
	  flow_loop_tree_node_remove (subloop);
	  flow_loop_tree_node_add (loop, subloop);
	}
    }

  /* Update the information about loop exit edges.  */
  for (i = 0; i < n; i++)
    {
      FOR_EACH_EDGE (e, ei, bbs[i]->succs)
	{
	  rescan_loop_exit (e, false, false);
	}
    }

  free (bbs);
}

/* Scale profile of loop by P.  */

void
scale_loop_frequencies (class loop *loop, profile_probability p)
{
  basic_block *bbs;

  bbs = get_loop_body (loop);
  scale_bbs_frequencies (bbs, loop->num_nodes, p);
  free (bbs);
}

/* Scale profile in LOOP by P.
   If ITERATION_BOUND is non-zero, scale even further if loop is predicted
   to iterate too many times.
   Before caling this function, preheader block profile should be already
   scaled to final count.  This is necessary because loop iterations are
   determined by comparing header edge count to latch ege count and thus
   they need to be scaled synchronously.  */

void
scale_loop_profile (class loop *loop, profile_probability p,
		    gcov_type iteration_bound)
{
  edge e, preheader_e;
  edge_iterator ei;

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file, ";; Scaling loop %i with scale ",
	       loop->num);
      p.dump (dump_file);
      fprintf (dump_file, " bounding iterations to %i\n",
	       (int)iteration_bound);
    }

  /* Scale the probabilities.  */
  scale_loop_frequencies (loop, p);

  if (iteration_bound == 0)
    return;

  gcov_type iterations = expected_loop_iterations_unbounded (loop, NULL, true);

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file, ";; guessed iterations after scaling %i\n",
	       (int)iterations);
    }

  /* See if loop is predicted to iterate too many times.  */
  if (iterations <= iteration_bound)
    return;

  preheader_e = loop_preheader_edge (loop);

  /* We could handle also loops without preheaders, but bounding is
     currently used only by optimizers that have preheaders constructed.  */
  gcc_checking_assert (preheader_e);
  profile_count count_in = preheader_e->count ();

  if (count_in > profile_count::zero ()
      && loop->header->count.initialized_p ())
    {
      profile_count count_delta = profile_count::zero ();

      e = single_exit (loop);
      if (e)
	{
	  edge other_e;
	  FOR_EACH_EDGE (other_e, ei, e->src->succs)
	    if (!(other_e->flags & (EDGE_ABNORMAL | EDGE_FAKE))
		&& e != other_e)
	      break;

	  /* Probability of exit must be 1/iterations.  */
	  count_delta = e->count ();
	  e->probability = profile_probability::always ()
				    .apply_scale (1, iteration_bound);
	  other_e->probability = e->probability.invert ();

	  /* In code below we only handle the following two updates.  */
	  if (other_e->dest != loop->header
	      && other_e->dest != loop->latch
	      && (dump_file && (dump_flags & TDF_DETAILS)))
	    {
	      fprintf (dump_file, ";; giving up on update of paths from "
		       "exit condition to latch\n");
	    }
	}
      else
        if (dump_file && (dump_flags & TDF_DETAILS))
	  fprintf (dump_file, ";; Loop has multiple exit edges; "
	      		      "giving up on exit condition update\n");

      /* Roughly speaking we want to reduce the loop body profile by the
	 difference of loop iterations.  We however can do better if
	 we look at the actual profile, if it is available.  */
      p = profile_probability::always ();

      count_in = count_in.apply_scale (iteration_bound, 1);
      p = count_in.probability_in (loop->header->count);
      if (!(p > profile_probability::never ()))
	p = profile_probability::very_unlikely ();

      if (p == profile_probability::always ()
	  || !p.initialized_p ())
	return;

      /* If latch exists, change its count, since we changed
	 probability of exit.  Theoretically we should update everything from
	 source of exit edge to latch, but for vectorizer this is enough.  */
      if (loop->latch && loop->latch != e->src)
	loop->latch->count += count_delta;

      /* Scale the probabilities.  */
      scale_loop_frequencies (loop, p);

      /* Change latch's count back.  */
      if (loop->latch && loop->latch != e->src)
	loop->latch->count -= count_delta;

      if (dump_file && (dump_flags & TDF_DETAILS))
	fprintf (dump_file, ";; guessed iterations are now %i\n",
		 (int)expected_loop_iterations_unbounded (loop, NULL, true));
    }
}

/* Recompute dominance information for basic blocks outside LOOP.  */

static void
update_dominators_in_loop (class loop *loop)
{
  vec<basic_block> dom_bbs = vNULL;
  basic_block *body;
  unsigned i;

  auto_sbitmap seen (last_basic_block_for_fn (cfun));
  bitmap_clear (seen);
  body = get_loop_body (loop);

  for (i = 0; i < loop->num_nodes; i++)
    bitmap_set_bit (seen, body[i]->index);

  for (i = 0; i < loop->num_nodes; i++)
    {
      basic_block ldom;

      for (ldom = first_dom_son (CDI_DOMINATORS, body[i]);
	   ldom;
	   ldom = next_dom_son (CDI_DOMINATORS, ldom))
	if (!bitmap_bit_p (seen, ldom->index))
	  {
	    bitmap_set_bit (seen, ldom->index);
	    dom_bbs.safe_push (ldom);
	  }
    }

  iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false);
  free (body);
  dom_bbs.release ();
}

/* Creates an if region as shown above. CONDITION is used to create
   the test for the if.

   |
   |     -------------                 -------------
   |     |  pred_bb  |                 |  pred_bb  |
   |     -------------                 -------------
   |           |                             |
   |           |                             | ENTRY_EDGE
   |           | ENTRY_EDGE                  V
   |           |             ====>     -------------
   |           |                       |  cond_bb  |
   |           |                       | CONDITION |
   |           |                       -------------
   |           V                        /         \
   |     -------------         e_false /           \ e_true
   |     |  succ_bb  |                V             V
   |     -------------         -----------       -----------
   |                           | false_bb |      | true_bb |
   |                           -----------       -----------
   |                                   \           /
   |                                    \         /
   |                                     V       V
   |                                   -------------
   |                                   |  join_bb  |
   |                                   -------------
   |                                         | exit_edge (result)
   |                                         V
   |                                    -----------
   |                                    | succ_bb |
   |                                    -----------
   |
 */

edge
create_empty_if_region_on_edge (edge entry_edge, tree condition)
{

  basic_block cond_bb, true_bb, false_bb, join_bb;
  edge e_true, e_false, exit_edge;
  gcond *cond_stmt;
  tree simple_cond;
  gimple_stmt_iterator gsi;

  cond_bb = split_edge (entry_edge);

  /* Insert condition in cond_bb.  */
  gsi = gsi_last_bb (cond_bb);
  simple_cond =
    force_gimple_operand_gsi (&gsi, condition, true, NULL,
			      false, GSI_NEW_STMT);
  cond_stmt = gimple_build_cond_from_tree (simple_cond, NULL_TREE, NULL_TREE);
  gsi = gsi_last_bb (cond_bb);
  gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);

  join_bb = split_edge (single_succ_edge (cond_bb));

  e_true = single_succ_edge (cond_bb);
  true_bb = split_edge (e_true);

  e_false = make_edge (cond_bb, join_bb, 0);
  false_bb = split_edge (e_false);

  e_true->flags &= ~EDGE_FALLTHRU;
  e_true->flags |= EDGE_TRUE_VALUE;
  e_false->flags &= ~EDGE_FALLTHRU;
  e_false->flags |= EDGE_FALSE_VALUE;

  set_immediate_dominator (CDI_DOMINATORS, cond_bb, entry_edge->src);
  set_immediate_dominator (CDI_DOMINATORS, true_bb, cond_bb);
  set_immediate_dominator (CDI_DOMINATORS, false_bb, cond_bb);
  set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);

  exit_edge = single_succ_edge (join_bb);

  if (single_pred_p (exit_edge->dest))
    set_immediate_dominator (CDI_DOMINATORS, exit_edge->dest, join_bb);

  return exit_edge;
}

/* create_empty_loop_on_edge
   |
   |    - pred_bb -                   ------ pred_bb ------
   |   |           |                 | iv0 = initial_value |
   |    -----|-----                   ---------|-----------
   |         |                       ______    | entry_edge
   |         | entry_edge           /      |   |
   |         |             ====>   |      -V---V- loop_header -------------
   |         V                     |     | iv_before = phi (iv0, iv_after) |
   |    - succ_bb -                |      ---|-----------------------------
   |   |           |               |         |
   |    -----------                |      ---V--- loop_body ---------------
   |                               |     | iv_after = iv_before + stride   |
   |                               |     | if (iv_before < upper_bound)    |
   |                               |      ---|--------------\--------------
   |                               |         |               \ exit_e
   |                               |         V                \
   |                               |       - loop_latch -      V- succ_bb -
   |                               |      |              |     |           |
   |                               |       /-------------       -----------
   |                                \ ___ /

   Creates an empty loop as shown above, the IV_BEFORE is the SSA_NAME
   that is used before the increment of IV. IV_BEFORE should be used for
   adding code to the body that uses the IV.  OUTER is the outer loop in
   which the new loop should be inserted.

   Both INITIAL_VALUE and UPPER_BOUND expressions are gimplified and
   inserted on the loop entry edge.  This implies that this function
   should be used only when the UPPER_BOUND expression is a loop
   invariant.  */

class loop *
create_empty_loop_on_edge (edge entry_edge,
			   tree initial_value,
			   tree stride, tree upper_bound,
			   tree iv,
			   tree *iv_before,
			   tree *iv_after,
			   class loop *outer)
{
  basic_block loop_header, loop_latch, succ_bb, pred_bb;
  class loop *loop;
  gimple_stmt_iterator gsi;
  gimple_seq stmts;
  gcond *cond_expr;
  tree exit_test;
  edge exit_e;

  gcc_assert (entry_edge && initial_value && stride && upper_bound && iv);

  /* Create header, latch and wire up the loop.  */
  pred_bb = entry_edge->src;
  loop_header = split_edge (entry_edge);
  loop_latch = split_edge (single_succ_edge (loop_header));
  succ_bb = single_succ (loop_latch);
  make_edge (loop_header, succ_bb, 0);
  redirect_edge_succ_nodup (single_succ_edge (loop_latch), loop_header);

  /* Set immediate dominator information.  */
  set_immediate_dominator (CDI_DOMINATORS, loop_header, pred_bb);
  set_immediate_dominator (CDI_DOMINATORS, loop_latch, loop_header);
  set_immediate_dominator (CDI_DOMINATORS, succ_bb, loop_header);

  /* Initialize a loop structure and put it in a loop hierarchy.  */
  loop = alloc_loop ();
  loop->header = loop_header;
  loop->latch = loop_latch;
  add_loop (loop, outer);

  /* TODO: Fix counts.  */
  scale_loop_frequencies (loop, profile_probability::even ());

  /* Update dominators.  */
  update_dominators_in_loop (loop);

  /* Modify edge flags.  */
  exit_e = single_exit (loop);
  exit_e->flags = EDGE_LOOP_EXIT | EDGE_FALSE_VALUE;
  single_pred_edge (loop_latch)->flags = EDGE_TRUE_VALUE;

  /* Construct IV code in loop.  */
  initial_value = force_gimple_operand (initial_value, &stmts, true, iv);
  if (stmts)
    {
      gsi_insert_seq_on_edge (loop_preheader_edge (loop), stmts);
      gsi_commit_edge_inserts ();
    }

  upper_bound = force_gimple_operand (upper_bound, &stmts, true, NULL);
  if (stmts)
    {
      gsi_insert_seq_on_edge (loop_preheader_edge (loop), stmts);
      gsi_commit_edge_inserts ();
    }

  gsi = gsi_last_bb (loop_header);
  create_iv (initial_value, stride, iv, loop, &gsi, false,
	     iv_before, iv_after);

  /* Insert loop exit condition.  */
  cond_expr = gimple_build_cond
    (LT_EXPR, *iv_before, upper_bound, NULL_TREE, NULL_TREE);

  exit_test = gimple_cond_lhs (cond_expr);
  exit_test = force_gimple_operand_gsi (&gsi, exit_test, true, NULL,
					false, GSI_NEW_STMT);
  gimple_cond_set_lhs (cond_expr, exit_test);
  gsi = gsi_last_bb (exit_e->src);
  gsi_insert_after (&gsi, cond_expr, GSI_NEW_STMT);

  split_block_after_labels (loop_header);

  return loop;
}

/* Make area between HEADER_EDGE and LATCH_EDGE a loop by connecting
   latch to header and update loop tree and dominators
   accordingly. Everything between them plus LATCH_EDGE destination must
   be dominated by HEADER_EDGE destination, and back-reachable from
   LATCH_EDGE source.  HEADER_EDGE is redirected to basic block SWITCH_BB,
   FALSE_EDGE of SWITCH_BB to original destination of HEADER_EDGE and
   TRUE_EDGE of SWITCH_BB to original destination of LATCH_EDGE.
   Returns the newly created loop.  Frequencies and counts in the new loop
   are scaled by FALSE_SCALE and in the old one by TRUE_SCALE.  */

class loop *
loopify (edge latch_edge, edge header_edge,
	 basic_block switch_bb, edge true_edge, edge false_edge,
	 bool redirect_all_edges, profile_probability true_scale,
	 profile_probability false_scale)
{
  basic_block succ_bb = latch_edge->dest;
  basic_block pred_bb = header_edge->src;
  class loop *loop = alloc_loop ();
  class loop *outer = loop_outer (succ_bb->loop_father);
  profile_count cnt;

  loop->header = header_edge->dest;
  loop->latch = latch_edge->src;

  cnt = header_edge->count ();

  /* Redirect edges.  */
  loop_redirect_edge (latch_edge, loop->header);
  loop_redirect_edge (true_edge, succ_bb);

  /* During loop versioning, one of the switch_bb edge is already properly
     set. Do not redirect it again unless redirect_all_edges is true.  */
  if (redirect_all_edges)
    {
      loop_redirect_edge (header_edge, switch_bb);
      loop_redirect_edge (false_edge, loop->header);

      /* Update dominators.  */
      set_immediate_dominator (CDI_DOMINATORS, switch_bb, pred_bb);
      set_immediate_dominator (CDI_DOMINATORS, loop->header, switch_bb);
    }

  set_immediate_dominator (CDI_DOMINATORS, succ_bb, switch_bb);

  /* Compute new loop.  */
  add_loop (loop, outer);

  /* Add switch_bb to appropriate loop.  */
  if (switch_bb->loop_father)
    remove_bb_from_loops (switch_bb);
  add_bb_to_loop (switch_bb, outer);

  /* Fix counts.  */
  if (redirect_all_edges)
    {
      switch_bb->count = cnt;
    }
  scale_loop_frequencies (loop, false_scale);
  scale_loop_frequencies (succ_bb->loop_father, true_scale);
  update_dominators_in_loop (loop);

  return loop;
}

/* Remove the latch edge of a LOOP and update loops to indicate that
   the LOOP was removed.  After this function, original loop latch will
   have no successor, which caller is expected to fix somehow.

   If this may cause the information about irreducible regions to become
   invalid, IRRED_INVALIDATED is set to true.  

   LOOP_CLOSED_SSA_INVALIDATED, if non-NULL, is a bitmap where we store
   basic blocks that had non-trivial update on their loop_father.*/

void
unloop (class loop *loop, bool *irred_invalidated,
	bitmap loop_closed_ssa_invalidated)
{
  basic_block *body;
  class loop *ploop;
  unsigned i, n;
  basic_block latch = loop->latch;
  bool dummy = false;

  if (loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP)
    *irred_invalidated = true;

  /* This is relatively straightforward.  The dominators are unchanged, as
     loop header dominates loop latch, so the only thing we have to care of
     is the placement of loops and basic blocks inside the loop tree.  We
     move them all to the loop->outer, and then let fix_bb_placements do
     its work.  */

  body = get_loop_body (loop);
  n = loop->num_nodes;
  for (i = 0; i < n; i++)
    if (body[i]->loop_father == loop)
      {
	remove_bb_from_loops (body[i]);
	add_bb_to_loop (body[i], loop_outer (loop));
      }
  free (body);

  while (loop->inner)
    {
      ploop = loop->inner;
      flow_loop_tree_node_remove (ploop);
      flow_loop_tree_node_add (loop_outer (loop), ploop);
    }

  /* Remove the loop and free its data.  */
  delete_loop (loop);

  remove_edge (single_succ_edge (latch));

  /* We do not pass IRRED_INVALIDATED to fix_bb_placements here, as even if
     there is an irreducible region inside the cancelled loop, the flags will
     be still correct.  */
  fix_bb_placements (latch, &dummy, loop_closed_ssa_invalidated);
}

/* Fix placement of superloops of LOOP inside loop tree, i.e. ensure that
   condition stated in description of fix_loop_placement holds for them.
   It is used in case when we removed some edges coming out of LOOP, which
   may cause the right placement of LOOP inside loop tree to change.

   IRRED_INVALIDATED is set to true if a change in the loop structures might
   invalidate the information about irreducible regions.  */

static void
fix_loop_placements (class loop *loop, bool *irred_invalidated)
{
  class loop *outer;

  while (loop_outer (loop))
    {
      outer = loop_outer (loop);
      if (!fix_loop_placement (loop, irred_invalidated))
	break;

      /* Changing the placement of a loop in the loop tree may alter the
	 validity of condition 2) of the description of fix_bb_placement
	 for its preheader, because the successor is the header and belongs
	 to the loop.  So call fix_bb_placements to fix up the placement
	 of the preheader and (possibly) of its predecessors.  */
      fix_bb_placements (loop_preheader_edge (loop)->src,
			 irred_invalidated, NULL);
      loop = outer;
    }
}

/* Duplicate loop bounds and other information we store about
   the loop into its duplicate.  */

void
copy_loop_info (class loop *loop, class loop *target)
{
  gcc_checking_assert (!target->any_upper_bound && !target->any_estimate);
  target->any_upper_bound = loop->any_upper_bound;
  target->nb_iterations_upper_bound = loop->nb_iterations_upper_bound;
  target->any_likely_upper_bound = loop->any_likely_upper_bound;
  target->nb_iterations_likely_upper_bound
    = loop->nb_iterations_likely_upper_bound;
  target->any_estimate = loop->any_estimate;
  target->nb_iterations_estimate = loop->nb_iterations_estimate;
  target->estimate_state = loop->estimate_state;
  target->safelen = loop->safelen;
  target->simdlen = loop->simdlen;
  target->constraints = loop->constraints;
  target->can_be_parallel = loop->can_be_parallel;
  target->warned_aggressive_loop_optimizations
    |= loop->warned_aggressive_loop_optimizations;
  target->dont_vectorize = loop->dont_vectorize;
  target->force_vectorize = loop->force_vectorize;
  target->in_oacc_kernels_region = loop->in_oacc_kernels_region;
  target->finite_p = loop->finite_p;
  target->unroll = loop->unroll;
  target->owned_clique = loop->owned_clique;
}

/* Copies copy of LOOP as subloop of TARGET loop, placing newly
   created loop into loops structure.  If AFTER is non-null
   the new loop is added at AFTER->next, otherwise in front of TARGETs
   sibling list.  */
class loop *
duplicate_loop (class loop *loop, class loop *target, class loop *after)
{
  class loop *cloop;
  cloop = alloc_loop ();
  place_new_loop (cfun, cloop);
 
  copy_loop_info (loop, cloop);

  /* Mark the new loop as copy of LOOP.  */
  set_loop_copy (loop, cloop);

  /* Add it to target.  */
  flow_loop_tree_node_add (target, cloop, after);

  return cloop;
}

/* Copies structure of subloops of LOOP into TARGET loop, placing
   newly created loops into loop tree at the end of TARGETs sibling
   list in the original order.  */
void
duplicate_subloops (class loop *loop, class loop *target)
{
  class loop *aloop, *cloop, *tail;

  for (tail = target->inner; tail && tail->next; tail = tail->next)
    ;
  for (aloop = loop->inner; aloop; aloop = aloop->next)
    {
      cloop = duplicate_loop (aloop, target, tail);
      tail = cloop;
      gcc_assert(!tail->next);
      duplicate_subloops (aloop, cloop);
    }
}

/* Copies structure of subloops of N loops, stored in array COPIED_LOOPS,
   into TARGET loop, placing newly created loops into loop tree adding
   them to TARGETs sibling list at the end in order.  */
static void
copy_loops_to (class loop **copied_loops, int n, class loop *target)
{
  class loop *aloop, *tail;
  int i;

  for (tail = target->inner; tail && tail->next; tail = tail->next)
    ;
  for (i = 0; i < n; i++)
    {
      aloop = duplicate_loop (copied_loops[i], target, tail);
      tail = aloop;
      gcc_assert(!tail->next);
      duplicate_subloops (copied_loops[i], aloop);
    }
}

/* Redirects edge E to basic block DEST.  */
static void
loop_redirect_edge (edge e, basic_block dest)
{
  if (e->dest == dest)
    return;

  redirect_edge_and_branch_force (e, dest);
}

/* Check whether LOOP's body can be duplicated.  */
bool
can_duplicate_loop_p (const class loop *loop)
{
  int ret;
  basic_block *bbs = get_loop_body (loop);

  ret = can_copy_bbs_p (bbs, loop->num_nodes);
  free (bbs);

  return ret;
}

/* Duplicates body of LOOP to given edge E NDUPL times.  Takes care of updating
   loop structure and dominators (order of inner subloops is retained).
   E's destination must be LOOP header for this to work, i.e. it must be entry
   or latch edge of this loop; these are unique, as the loops must have
   preheaders for this function to work correctly (in case E is latch, the
   function unrolls the loop, if E is entry edge, it peels the loop).  Store
   edges created by copying ORIG edge from copies corresponding to set bits in
   WONT_EXIT bitmap (bit 0 corresponds to original LOOP body, the other copies
   are numbered in order given by control flow through them) into TO_REMOVE
   array.  Returns false if duplication is
   impossible.  */

bool
duplicate_loop_to_header_edge (class loop *loop, edge e,
			       unsigned int ndupl, sbitmap wont_exit,
			       edge orig, vec<edge> *to_remove,
			       int flags)
{
  class loop *target, *aloop;
  class loop **orig_loops;
  unsigned n_orig_loops;
  basic_block header = loop->header, latch = loop->latch;
  basic_block *new_bbs, *bbs, *first_active;
  basic_block new_bb, bb, first_active_latch = NULL;
  edge ae, latch_edge;
  edge spec_edges[2], new_spec_edges[2];
  const int SE_LATCH = 0;
  const int SE_ORIG = 1;
  unsigned i, j, n;
  int is_latch = (latch == e->src);
  profile_probability *scale_step = NULL;
  profile_probability scale_main = profile_probability::always ();
  profile_probability scale_act = profile_probability::always ();
  profile_count after_exit_num = profile_count::zero (),
	        after_exit_den = profile_count::zero ();
  bool scale_after_exit = false;
  int add_irreducible_flag;
  basic_block place_after;
  bitmap bbs_to_scale = NULL;
  bitmap_iterator bi;

  gcc_assert (e->dest == loop->header);
  gcc_assert (ndupl > 0);

  if (orig)
    {
      /* Orig must be edge out of the loop.  */
      gcc_assert (flow_bb_inside_loop_p (loop, orig->src));
      gcc_assert (!flow_bb_inside_loop_p (loop, orig->dest));
    }

  n = loop->num_nodes;
  bbs = get_loop_body_in_dom_order (loop);
  gcc_assert (bbs[0] == loop->header);
  gcc_assert (bbs[n  - 1] == loop->latch);

  /* Check whether duplication is possible.  */
  if (!can_copy_bbs_p (bbs, loop->num_nodes))
    {
      free (bbs);
      return false;
    }
  new_bbs = XNEWVEC (basic_block, loop->num_nodes);

  /* In case we are doing loop peeling and the loop is in the middle of
     irreducible region, the peeled copies will be inside it too.  */
  add_irreducible_flag = e->flags & EDGE_IRREDUCIBLE_LOOP;
  gcc_assert (!is_latch || !add_irreducible_flag);

  /* Find edge from latch.  */
  latch_edge = loop_latch_edge (loop);

  if (flags & DLTHE_FLAG_UPDATE_FREQ)
    {
      /* Calculate coefficients by that we have to scale counts
	 of duplicated loop bodies.  */
      profile_count count_in = header->count;
      profile_count count_le = latch_edge->count ();
      profile_count count_out_orig = orig ? orig->count () : count_in - count_le;
      profile_probability prob_pass_thru = count_le.probability_in (count_in);
      profile_probability prob_pass_wont_exit =
	      (count_le + count_out_orig).probability_in (count_in);

      if (orig && orig->probability.initialized_p ()
	  && !(orig->probability == profile_probability::always ()))
	{
	  /* The blocks that are dominated by a removed exit edge ORIG have
	     frequencies scaled by this.  */
	  if (orig->count ().initialized_p ())
	    {
	      after_exit_num = orig->src->count;
	      after_exit_den = after_exit_num - orig->count ();
	      scale_after_exit = true;
	    }
	  bbs_to_scale = BITMAP_ALLOC (NULL);
	  for (i = 0; i < n; i++)
	    {
	      if (bbs[i] != orig->src
		  && dominated_by_p (CDI_DOMINATORS, bbs[i], orig->src))
		bitmap_set_bit (bbs_to_scale, i);
	    }
	}

      scale_step = XNEWVEC (profile_probability, ndupl);

      for (i = 1; i <= ndupl; i++)
	scale_step[i - 1] = bitmap_bit_p (wont_exit, i)
				? prob_pass_wont_exit
				: prob_pass_thru;

      /* Complete peeling is special as the probability of exit in last
	 copy becomes 1.  */
      if (flags & DLTHE_FLAG_COMPLETTE_PEEL)
	{
	  profile_count wanted_count = e->count ();

	  gcc_assert (!is_latch);
	  /* First copy has count of incoming edge.  Each subsequent
	     count should be reduced by prob_pass_wont_exit.  Caller
	     should've managed the flags so all except for original loop
	     has won't exist set.  */
	  scale_act = wanted_count.probability_in (count_in);
	  /* Now simulate the duplication adjustments and compute header
	     frequency of the last copy.  */
	  for (i = 0; i < ndupl; i++)
	    wanted_count = wanted_count.apply_probability (scale_step [i]);
	  scale_main = wanted_count.probability_in (count_in);
	}
      /* Here we insert loop bodies inside the loop itself (for loop unrolling).
	 First iteration will be original loop followed by duplicated bodies.
	 It is necessary to scale down the original so we get right overall
	 number of iterations.  */
      else if (is_latch)
	{
	  profile_probability prob_pass_main = bitmap_bit_p (wont_exit, 0)
							? prob_pass_wont_exit
							: prob_pass_thru;
	  profile_probability p = prob_pass_main;
	  profile_count scale_main_den = count_in;
	  for (i = 0; i < ndupl; i++)
	    {
	      scale_main_den += count_in.apply_probability (p);
	      p = p * scale_step[i];
	    }
	  /* If original loop is executed COUNT_IN times, the unrolled
	     loop will account SCALE_MAIN_DEN times.  */
	  scale_main = count_in.probability_in (scale_main_den);
	  scale_act = scale_main * prob_pass_main;
	}
      else
	{
	  profile_count preheader_count = e->count ();
	  for (i = 0; i < ndupl; i++)
	    scale_main = scale_main * scale_step[i];
	  scale_act = preheader_count.probability_in (count_in);
	}
    }

  /* Loop the new bbs will belong to.  */
  target = e->src->loop_father;

  /* Original loops.  */
  n_orig_loops = 0;
  for (aloop = loop->inner; aloop; aloop = aloop->next)
    n_orig_loops++;
  orig_loops = XNEWVEC (class loop *, n_orig_loops);
  for (aloop = loop->inner, i = 0; aloop; aloop = aloop->next, i++)
    orig_loops[i] = aloop;

  set_loop_copy (loop, target);

  first_active = XNEWVEC (basic_block, n);
  if (is_latch)
    {
      memcpy (first_active, bbs, n * sizeof (basic_block));
      first_active_latch = latch;
    }

  spec_edges[SE_ORIG] = orig;
  spec_edges[SE_LATCH] = latch_edge;

  place_after = e->src;
  for (j = 0; j < ndupl; j++)
    {
      /* Copy loops.  */
      copy_loops_to (orig_loops, n_orig_loops, target);

      /* Copy bbs.  */
      copy_bbs (bbs, n, new_bbs, spec_edges, 2, new_spec_edges, loop,
		place_after, true);
      place_after = new_spec_edges[SE_LATCH]->src;

      if (flags & DLTHE_RECORD_COPY_NUMBER)
	for (i = 0; i < n; i++)
	  {
	    gcc_assert (!new_bbs[i]->aux);
	    new_bbs[i]->aux = (void *)(size_t)(j + 1);
	  }

      /* Note whether the blocks and edges belong to an irreducible loop.  */
      if (add_irreducible_flag)
	{
	  for (i = 0; i < n; i++)
	    new_bbs[i]->flags |= BB_DUPLICATED;
	  for (i = 0; i < n; i++)
	    {
	      edge_iterator ei;
	      new_bb = new_bbs[i];
	      if (new_bb->loop_father == target)
		new_bb->flags |= BB_IRREDUCIBLE_LOOP;

	      FOR_EACH_EDGE (ae, ei, new_bb->succs)
		if ((ae->dest->flags & BB_DUPLICATED)
		    && (ae->src->loop_father == target
			|| ae->dest->loop_father == target))
		  ae->flags |= EDGE_IRREDUCIBLE_LOOP;
	    }
	  for (i = 0; i < n; i++)
	    new_bbs[i]->flags &= ~BB_DUPLICATED;
	}

      /* Redirect the special edges.  */
      if (is_latch)
	{
	  redirect_edge_and_branch_force (latch_edge, new_bbs[0]);
	  redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
					  loop->header);
	  set_immediate_dominator (CDI_DOMINATORS, new_bbs[0], latch);
	  latch = loop->latch = new_bbs[n - 1];
	  e = latch_edge = new_spec_edges[SE_LATCH];
	}
      else
	{
	  redirect_edge_and_branch_force (new_spec_edges[SE_LATCH],
					  loop->header);
	  redirect_edge_and_branch_force (e, new_bbs[0]);
	  set_immediate_dominator (CDI_DOMINATORS, new_bbs[0], e->src);
	  e = new_spec_edges[SE_LATCH];
	}

      /* Record exit edge in this copy.  */
      if (orig && bitmap_bit_p (wont_exit, j + 1))
	{
	  if (to_remove)
	    to_remove->safe_push (new_spec_edges[SE_ORIG]);
	  force_edge_cold (new_spec_edges[SE_ORIG], true);

	  /* Scale the frequencies of the blocks dominated by the exit.  */
	  if (bbs_to_scale && scale_after_exit)
	    {
	      EXECUTE_IF_SET_IN_BITMAP (bbs_to_scale, 0, i, bi)
		scale_bbs_frequencies_profile_count (new_bbs + i, 1, after_exit_num,
						     after_exit_den);
	    }
	}

      /* Record the first copy in the control flow order if it is not
	 the original loop (i.e. in case of peeling).  */
      if (!first_active_latch)
	{
	  memcpy (first_active, new_bbs, n * sizeof (basic_block));
	  first_active_latch = new_bbs[n - 1];
	}

      /* Set counts and frequencies.  */
      if (flags & DLTHE_FLAG_UPDATE_FREQ)
	{
	  scale_bbs_frequencies (new_bbs, n, scale_act);
	  scale_act = scale_act * scale_step[j];
	}
    }
  free (new_bbs);
  free (orig_loops);

  /* Record the exit edge in the original loop body, and update the frequencies.  */
  if (orig && bitmap_bit_p (wont_exit, 0))
    {
      if (to_remove)
	to_remove->safe_push (orig);
      force_edge_cold (orig, true);

      /* Scale the frequencies of the blocks dominated by the exit.  */
      if (bbs_to_scale && scale_after_exit)
	{
	  EXECUTE_IF_SET_IN_BITMAP (bbs_to_scale, 0, i, bi)
	    scale_bbs_frequencies_profile_count (bbs + i, 1, after_exit_num,
						 after_exit_den);
	}
    }

  /* Update the original loop.  */
  if (!is_latch)
    set_immediate_dominator (CDI_DOMINATORS, e->dest, e->src);
  if (flags & DLTHE_FLAG_UPDATE_FREQ)
    {
      scale_bbs_frequencies (bbs, n, scale_main);
      free (scale_step);
    }

  /* Update dominators of outer blocks if affected.  */
  for (i = 0; i < n; i++)
    {
      basic_block dominated, dom_bb;
      unsigned j;

      bb = bbs[i];
      bb->aux = 0;

      auto_vec<basic_block> dom_bbs = get_dominated_by (CDI_DOMINATORS, bb);
      FOR_EACH_VEC_ELT (dom_bbs, j, dominated)
	{
	  if (flow_bb_inside_loop_p (loop, dominated))
	    continue;
	  dom_bb = nearest_common_dominator (
			CDI_DOMINATORS, first_active[i], first_active_latch);
	  set_immediate_dominator (CDI_DOMINATORS, dominated, dom_bb);
	}
    }
  free (first_active);

  free (bbs);
  BITMAP_FREE (bbs_to_scale);

  return true;
}

/* A callback for make_forwarder block, to redirect all edges except for
   MFB_KJ_EDGE to the entry part.  E is the edge for that we should decide
   whether to redirect it.  */

edge mfb_kj_edge;
bool
mfb_keep_just (edge e)
{
  return e != mfb_kj_edge;
}

/* True when a candidate preheader BLOCK has predecessors from LOOP.  */

static bool
has_preds_from_loop (basic_block block, class loop *loop)
{
  edge e;
  edge_iterator ei;

  FOR_EACH_EDGE (e, ei, block->preds)
    if (e->src->loop_father == loop)
      return true;
  return false;
}

/* Creates a pre-header for a LOOP.  Returns newly created block.  Unless
   CP_SIMPLE_PREHEADERS is set in FLAGS, we only force LOOP to have single
   entry; otherwise we also force preheader block to have only one successor.
   When CP_FALLTHRU_PREHEADERS is set in FLAGS, we force the preheader block
   to be a fallthru predecessor to the loop header and to have only
   predecessors from outside of the loop.
   The function also updates dominators.  */

basic_block
create_preheader (class loop *loop, int flags)
{
  edge e;
  basic_block dummy;
  int nentry = 0;
  bool irred = false;
  bool latch_edge_was_fallthru;
  edge one_succ_pred = NULL, single_entry = NULL;
  edge_iterator ei;

  FOR_EACH_EDGE (e, ei, loop->header->preds)
    {
      if (e->src == loop->latch)
	continue;
      irred |= (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
      nentry++;
      single_entry = e;
      if (single_succ_p (e->src))
	one_succ_pred = e;
    }
  gcc_assert (nentry);
  if (nentry == 1)
    {
      bool need_forwarder_block = false;

      /* We do not allow entry block to be the loop preheader, since we
	     cannot emit code there.  */
      if (single_entry->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
        need_forwarder_block = true;
      else
        {
          /* If we want simple preheaders, also force the preheader to have
	     just a single successor and a normal edge.  */
          if ((flags & CP_SIMPLE_PREHEADERS)
	      && ((single_entry->flags & EDGE_COMPLEX)
		  || !single_succ_p (single_entry->src)))
            need_forwarder_block = true;
          /* If we want fallthru preheaders, also create forwarder block when
             preheader ends with a jump or has predecessors from loop.  */
          else if ((flags & CP_FALLTHRU_PREHEADERS)
                   && (JUMP_P (BB_END (single_entry->src))
                       || has_preds_from_loop (single_entry->src, loop)))
            need_forwarder_block = true;
        }
      if (! need_forwarder_block)
	return NULL;
    }

  mfb_kj_edge = loop_latch_edge (loop);
  latch_edge_was_fallthru = (mfb_kj_edge->flags & EDGE_FALLTHRU) != 0;
  if (nentry == 1
      && ((flags & CP_FALLTHRU_PREHEADERS) == 0
  	  || (single_entry->flags & EDGE_CROSSING) == 0))
    dummy = split_edge (single_entry);
  else
    {
      edge fallthru = make_forwarder_block (loop->header, mfb_keep_just, NULL);
      dummy = fallthru->src;
      loop->header = fallthru->dest;
    }

  /* Try to be clever in placing the newly created preheader.  The idea is to
     avoid breaking any "fallthruness" relationship between blocks.

     The preheader was created just before the header and all incoming edges
     to the header were redirected to the preheader, except the latch edge.
     So the only problematic case is when this latch edge was a fallthru
     edge: it is not anymore after the preheader creation so we have broken
     the fallthruness.  We're therefore going to look for a better place.  */
  if (latch_edge_was_fallthru)
    {
      if (one_succ_pred)
	e = one_succ_pred;
      else
	e = EDGE_PRED (dummy, 0);

      move_block_after (dummy, e->src);
    }

  if (irred)
    {
      dummy->flags |= BB_IRREDUCIBLE_LOOP;
      single_succ_edge (dummy)->flags |= EDGE_IRREDUCIBLE_LOOP;
    }

  if (dump_file)
    fprintf (dump_file, "Created preheader block for loop %i\n",
	     loop->num);

  if (flags & CP_FALLTHRU_PREHEADERS)
    gcc_assert ((single_succ_edge (dummy)->flags & EDGE_FALLTHRU)
                && !JUMP_P (BB_END (dummy)));

  return dummy;
}

/* Create preheaders for each loop; for meaning of FLAGS see create_preheader.  */

void
create_preheaders (int flags)
{
  if (!current_loops)
    return;

  for (auto loop : loops_list (cfun, 0))
    create_preheader (loop, flags);
  loops_state_set (LOOPS_HAVE_PREHEADERS);
}

/* Forces all loop latches to have only single successor.  */

void
force_single_succ_latches (void)
{
  edge e;

  for (auto loop : loops_list (cfun, 0))
    {
      if (loop->latch != loop->header && single_succ_p (loop->latch))
	continue;

      e = find_edge (loop->latch, loop->header);
      gcc_checking_assert (e != NULL);

      split_edge (e);
    }
  loops_state_set (LOOPS_HAVE_SIMPLE_LATCHES);
}

/* This function is called from loop_version.  It splits the entry edge
   of the loop we want to version, adds the versioning condition, and
   adjust the edges to the two versions of the loop appropriately.
   e is an incoming edge. Returns the basic block containing the
   condition.

   --- edge e ---- > [second_head]

   Split it and insert new conditional expression and adjust edges.

    --- edge e ---> [cond expr] ---> [first_head]
			|
			+---------> [second_head]

  THEN_PROB is the probability of then branch of the condition.
  ELSE_PROB is the probability of else branch. Note that they may be both
  REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED or
  IFN_LOOP_DIST_ALIAS.  */

static basic_block
lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
			   edge e, void *cond_expr,
			   profile_probability then_prob,
			   profile_probability else_prob)
{
  basic_block new_head = NULL;
  edge e1;

  gcc_assert (e->dest == second_head);

  /* Split edge 'e'. This will create a new basic block, where we can
     insert conditional expr.  */
  new_head = split_edge (e);

  lv_add_condition_to_bb (first_head, second_head, new_head,
			  cond_expr);

  /* Don't set EDGE_TRUE_VALUE in RTL mode, as it's invalid there.  */
  e = single_succ_edge (new_head);
  e1 = make_edge (new_head, first_head,
		  current_ir_type () == IR_GIMPLE ? EDGE_TRUE_VALUE : 0);
  e1->probability = then_prob;
  e->probability = else_prob;

  set_immediate_dominator (CDI_DOMINATORS, first_head, new_head);
  set_immediate_dominator (CDI_DOMINATORS, second_head, new_head);

  /* Adjust loop header phi nodes.  */
  lv_adjust_loop_header_phi (first_head, second_head, new_head, e1);

  return new_head;
}

/* Main entry point for Loop Versioning transformation.

   This transformation given a condition and a loop, creates
   -if (condition) { loop_copy1 } else { loop_copy2 },
   where loop_copy1 is the loop transformed in one way, and loop_copy2
   is the loop transformed in another way (or unchanged). COND_EXPR
   may be a run time test for things that were not resolved by static
   analysis (overlapping ranges (anti-aliasing), alignment, etc.).

   If non-NULL, CONDITION_BB is set to the basic block containing the
   condition.

   THEN_PROB is the probability of the then edge of the if.  THEN_SCALE
   is the ratio by that the frequencies in the original loop should
   be scaled.  ELSE_SCALE is the ratio by that the frequencies in the
   new loop should be scaled.

   If PLACE_AFTER is true, we place the new loop after LOOP in the
   instruction stream, otherwise it is placed before LOOP.  */

class loop *
loop_version (class loop *loop,
	      void *cond_expr, basic_block *condition_bb,
	      profile_probability then_prob, profile_probability else_prob,
	      profile_probability then_scale, profile_probability else_scale,
	      bool place_after)
{
  basic_block first_head, second_head;
  edge entry, latch_edge, true_edge, false_edge;
  int irred_flag;
  class loop *nloop;
  basic_block cond_bb;

  /* Record entry and latch edges for the loop */
  entry = loop_preheader_edge (loop);
  irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
  entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;

  /* Note down head of loop as first_head.  */
  first_head = entry->dest;

  /* Duplicate loop.  */
  if (!cfg_hook_duplicate_loop_to_header_edge (loop, entry, 1,
					       NULL, NULL, NULL, 0))
    {
      entry->flags |= irred_flag;
      return NULL;
    }

  /* After duplication entry edge now points to new loop head block.
     Note down new head as second_head.  */
  second_head = entry->dest;

  /* Split loop entry edge and insert new block with cond expr.  */
  cond_bb =  lv_adjust_loop_entry_edge (first_head, second_head,
					entry, cond_expr, then_prob, else_prob);
  if (condition_bb)
    *condition_bb = cond_bb;

  if (!cond_bb)
    {
      entry->flags |= irred_flag;
      return NULL;
    }

  latch_edge = single_succ_edge (get_bb_copy (loop->latch));

  extract_cond_bb_edges (cond_bb, &true_edge, &false_edge);
  nloop = loopify (latch_edge,
		   single_pred_edge (get_bb_copy (loop->header)),
		   cond_bb, true_edge, false_edge,
		   false /* Do not redirect all edges.  */,
		   then_scale, else_scale);

  copy_loop_info (loop, nloop);
  set_loop_copy (loop, nloop);

  /* loopify redirected latch_edge. Update its PENDING_STMTS.  */
  lv_flush_pending_stmts (latch_edge);

  /* loopify redirected condition_bb's succ edge. Update its PENDING_STMTS.  */
  extract_cond_bb_edges (cond_bb, &true_edge, &false_edge);
  lv_flush_pending_stmts (false_edge);
  /* Adjust irreducible flag.  */
  if (irred_flag)
    {
      cond_bb->flags |= BB_IRREDUCIBLE_LOOP;
      loop_preheader_edge (loop)->flags |= EDGE_IRREDUCIBLE_LOOP;
      loop_preheader_edge (nloop)->flags |= EDGE_IRREDUCIBLE_LOOP;
      single_pred_edge (cond_bb)->flags |= EDGE_IRREDUCIBLE_LOOP;
    }

  if (place_after)
    {
      basic_block *bbs = get_loop_body_in_dom_order (nloop), after;
      unsigned i;

      after = loop->latch;

      for (i = 0; i < nloop->num_nodes; i++)
	{
	  move_block_after (bbs[i], after);
	  after = bbs[i];
	}
      free (bbs);
    }

  /* At this point condition_bb is loop preheader with two successors,
     first_head and second_head.   Make sure that loop preheader has only
     one successor.  */
  split_edge (loop_preheader_edge (loop));
  split_edge (loop_preheader_edge (nloop));

  return nloop;
}
