/* Gimple Represented as Polyhedra.
   Copyright (C) 2006-2018 Free Software Foundation, Inc.
   Contributed by Sebastian Pop <sebastian.pop@inria.fr>.

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

/* This pass converts GIMPLE to GRAPHITE, performs some loop
   transformations and then converts the resulting representation back
   to GIMPLE.

   An early description of this pass can be found in the GCC Summit'06
   paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC".
   The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to
   the related work.  */

#define USES_ISL

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "diagnostic-core.h"
#include "cfgloop.h"
#include "tree-pass.h"
#include "params.h"
#include "pretty-print.h"
#include "cfganal.h"

#ifdef HAVE_isl
#include "cfghooks.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "fold-const.h"
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "tree-ssa-loop.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
#include "dbgcnt.h"
#include "tree-parloops.h"
#include "tree-cfgcleanup.h"
#include "tree-vectorizer.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa.h"
#include "tree-into-ssa.h"
#include "graphite.h"

/* Print global statistics to FILE.  */

static void
print_global_statistics (FILE* file)
{
  long n_bbs = 0;
  long n_loops = 0;
  long n_stmts = 0;
  long n_conditions = 0;
  profile_count n_p_bbs = profile_count::zero ();
  profile_count n_p_loops = profile_count::zero ();
  profile_count n_p_stmts = profile_count::zero ();
  profile_count n_p_conditions = profile_count::zero ();

  basic_block bb;

  FOR_ALL_BB_FN (bb, cfun)
    {
      gimple_stmt_iterator psi;

      n_bbs++;
      if (bb->count.initialized_p ())
        n_p_bbs += bb->count;

      /* Ignore artificial surrounding loop.  */
      if (bb == bb->loop_father->header
	  && bb->index != 0)
	{
	  n_loops++;
	  n_p_loops += bb->count;
	}

      if (EDGE_COUNT (bb->succs) > 1)
	{
	  n_conditions++;
	  if (bb->count.initialized_p ())
	    n_p_conditions += bb->count;
	}

      for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
	{
	  n_stmts++;
	  if (bb->count.initialized_p ())
	    n_p_stmts += bb->count;
	}
    }

  fprintf (file, "\nGlobal statistics (");
  fprintf (file, "BBS:%ld, ", n_bbs);
  fprintf (file, "LOOPS:%ld, ", n_loops);
  fprintf (file, "CONDITIONS:%ld, ", n_conditions);
  fprintf (file, "STMTS:%ld)\n", n_stmts);
  fprintf (file, "Global profiling statistics (");
  fprintf (file, "BBS:");
  n_p_bbs.dump (file);
  fprintf (file, ", LOOPS:");
  n_p_loops.dump (file);
  fprintf (file, ", CONDITIONS:");
  n_p_conditions.dump (file);
  fprintf (file, ", STMTS:");
  n_p_stmts.dump (file);
  fprintf (file, ")\n\n");
}

/* Print statistics for SCOP to FILE.  */

static void
print_graphite_scop_statistics (FILE* file, scop_p scop)
{
  long n_bbs = 0;
  long n_loops = 0;
  long n_stmts = 0;
  long n_conditions = 0;
  profile_count n_p_bbs = profile_count::zero ();
  profile_count n_p_loops = profile_count::zero ();
  profile_count n_p_stmts = profile_count::zero ();
  profile_count n_p_conditions = profile_count::zero ();

  basic_block bb;

  FOR_ALL_BB_FN (bb, cfun)
    {
      gimple_stmt_iterator psi;
      loop_p loop = bb->loop_father;

      if (!bb_in_sese_p (bb, scop->scop_info->region))
	continue;

      n_bbs++;
      if (bb->count.initialized_p ())
        n_p_bbs += bb->count;

      if (EDGE_COUNT (bb->succs) > 1)
	{
	  n_conditions++;
	  n_p_conditions += bb->count;
	}

      for (psi = gsi_start_bb (bb); !gsi_end_p (psi); gsi_next (&psi))
	{
	  n_stmts++;
	  n_p_stmts += bb->count;
	}

      if (loop->header == bb && loop_in_sese_p (loop, scop->scop_info->region))
	{
	  n_loops++;
	  n_p_loops += bb->count;
	}
    }

  fprintf (file, "\nFunction Name: %s\n", current_function_name ());

  edge scop_begin = scop->scop_info->region.entry;
  edge scop_end = scop->scop_info->region.exit;

  fprintf (file, "\nSCoP (entry_edge (bb_%d, bb_%d), ",
	   scop_begin->src->index, scop_begin->dest->index);
  fprintf (file, "exit_edge (bb_%d, bb_%d))",
	   scop_end->src->index, scop_end->dest->index);

  fprintf (file, "\nSCoP statistics (");
  fprintf (file, "BBS:%ld, ", n_bbs);
  fprintf (file, "LOOPS:%ld, ", n_loops);
  fprintf (file, "CONDITIONS:%ld, ", n_conditions);
  fprintf (file, "STMTS:%ld)\n", n_stmts);
  fprintf (file, "SCoP profiling statistics (");
  fprintf (file, "BBS:");
  n_p_bbs.dump (file);
  fprintf (file, ", LOOPS:");
  n_p_loops.dump (file);
  fprintf (file, ", CONDITIONS:");
  n_p_conditions.dump (file);
  fprintf (file, ", STMTS:");
  n_p_stmts.dump (file);
  fprintf (file, ")\n\n");
}

/* Print statistics for SCOPS to FILE.  */

static void
print_graphite_statistics (FILE* file, vec<scop_p> scops)
{
  int i;
  scop_p scop;

  FOR_EACH_VEC_ELT (scops, i, scop)
    print_graphite_scop_statistics (file, scop);
}

/* Deletes all scops in SCOPS.  */

static void
free_scops (vec<scop_p> scops)
{
  int i;
  scop_p scop;

  FOR_EACH_VEC_ELT (scops, i, scop)
    free_scop (scop);

  scops.release ();
}

/* Transforms LOOP to the canonical loop closed SSA form.  */

static void
canonicalize_loop_closed_ssa (loop_p loop, edge e)
{
  basic_block bb;
  gphi_iterator psi;

  bb = e->dest;

  /* Make the loop-close PHI node BB contain only PHIs and have a
     single predecessor.  */
  if (single_pred_p (bb))
    {
      e = split_block_after_labels (bb);
      bb = e->src;
    }
  else
    {
      basic_block close = split_edge (e);
      e = single_succ_edge (close);
      for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
	{
	  gphi *phi = psi.phi ();
	  use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
	  tree arg = USE_FROM_PTR (use_p);

	  /* Only add close phi nodes for SSA_NAMEs defined in LOOP.  */
	  if (TREE_CODE (arg) != SSA_NAME
	      || SSA_NAME_IS_DEFAULT_DEF (arg)
	      || ! flow_bb_inside_loop_p (loop,
					  gimple_bb (SSA_NAME_DEF_STMT (arg))))
	    continue;

	  tree res = copy_ssa_name (arg);
	  gphi *close_phi = create_phi_node (res, close);
	  add_phi_arg (close_phi, arg, gimple_phi_arg_edge (close_phi, 0),
		       UNKNOWN_LOCATION);
	  SET_USE (use_p, res);
	}
      bb = close;
    }

  /* Eliminate duplicates.  This relies on processing loops from
     innermost to outer.  */
  for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
    {
      gphi_iterator gsi = psi;
      gphi *phi = psi.phi ();

      /* At this point, PHI should be a close phi in normal form.  */
      gcc_assert (gimple_phi_num_args (phi) == 1);

      /* Iterate over the next phis and remove duplicates.  */
      gsi_next (&gsi);
      while (!gsi_end_p (gsi))
	if (gimple_phi_arg_def (phi, 0) == gimple_phi_arg_def (gsi.phi (), 0))
	  {
	    replace_uses_by (gimple_phi_result (gsi.phi ()),
			     gimple_phi_result (phi));
	    remove_phi_node (&gsi, true);
	  }
	else
	  gsi_next (&gsi);
    }
}

/* Converts the current loop closed SSA form to a canonical form
   expected by the Graphite code generation.

   The loop closed SSA form has the following invariant: a variable
   defined in a loop that is used outside the loop appears only in the
   phi nodes in the destination of the loop exit.  These phi nodes are
   called close phi nodes.

   The canonical loop closed SSA form contains the extra invariants:

   - when the loop contains only one exit, the close phi nodes contain
   only one argument.  That implies that the basic block that contains
   the close phi nodes has only one predecessor, that is a basic block
   in the loop.

   - the basic block containing the close phi nodes does not contain
   other statements.

   - there exist only one phi node per definition in the loop.

   In addition to that we also make sure that loop exit edges are
   first in the successor edge vector.  This is to make RPO order
   as computed by pre_and_rev_post_order_compute be consistent with
   what initial schedule generation expects.
*/

static void
canonicalize_loop_form (void)
{
  loop_p loop;
  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
    {
      edge e = single_exit (loop);
      if (!e || (e->flags & (EDGE_COMPLEX|EDGE_FAKE)))
	continue;

      canonicalize_loop_closed_ssa (loop, e);

      /* If the exit is not first in the edge vector make it so.  */
      if (e != EDGE_SUCC (e->src, 0))
	{
	  unsigned ei;
	  for (ei = 0; EDGE_SUCC (e->src, ei) != e; ++ei)
	    ;
	  std::swap (EDGE_SUCC (e->src, ei), EDGE_SUCC (e->src, 0));
	}
    }

  /* We can end up releasing duplicate exit PHIs and also introduce
     additional copies so the cached information isn't correct anymore.  */
  scev_reset ();

  checking_verify_loop_closed_ssa (true);
}

isl_ctx *the_isl_ctx;

/* Perform a set of linear transforms on the loops of the current
   function.  */

void
graphite_transform_loops (void)
{
  int i;
  scop_p scop;
  bool changed = false;
  vec<scop_p> scops = vNULL;
  isl_ctx *ctx;

  /* If a function is parallel it was most probably already run through graphite
     once. No need to run again.  */
  if (parallelized_function_p (cfun->decl))
    return;

  calculate_dominance_info (CDI_DOMINATORS);

  /* We rely on post-dominators during merging of SESE regions so those
     have to be meaningful.  */
  connect_infinite_loops_to_exit ();

  ctx = isl_ctx_alloc ();
  isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
  the_isl_ctx = ctx;

  sort_sibling_loops (cfun);
  canonicalize_loop_form ();

  /* Print the loop structure.  */
  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      print_loops (dump_file, 2);
      print_loops (dump_file, 3);
    }

  calculate_dominance_info (CDI_POST_DOMINATORS);
  build_scops (&scops);
  free_dominance_info (CDI_POST_DOMINATORS);

  /* Remove the fake exits before transform given they are not reflected
     in loop structures we end up verifying.  */
  remove_fake_exit_edges ();

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      print_graphite_statistics (dump_file, scops);
      print_global_statistics (dump_file);
    }

  FOR_EACH_VEC_ELT (scops, i, scop)
    if (dbg_cnt (graphite_scop))
      {
	scop->isl_context = ctx;
	if (!build_poly_scop (scop))
	  continue;

	if (!apply_poly_transforms (scop))
	  continue;

	changed = true;
	if (graphite_regenerate_ast_isl (scop))
	  {
	    location_t loc = find_loop_location
	      (scops[i]->scop_info->region.entry->dest->loop_father);
	    dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
			     "loop nest optimized\n");
	  }
      }

  if (changed)
    {
      mark_virtual_operands_for_renaming (cfun);
      update_ssa (TODO_update_ssa);
      checking_verify_ssa (true, true);
      rewrite_into_loop_closed_ssa (NULL, 0);
      scev_reset ();
      checking_verify_loop_structure ();
    }

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      loop_p loop;
      int num_no_dependency = 0;

      FOR_EACH_LOOP (loop, 0)
	if (loop->can_be_parallel)
	  num_no_dependency++;

      fprintf (dump_file, "%d loops carried no dependency.\n",
	       num_no_dependency);
    }

  free_scops (scops);
  the_isl_ctx = NULL;
  isl_ctx_free (ctx);

  if (changed)
    {
      cleanup_tree_cfg ();
      profile_status_for_fn (cfun) = PROFILE_ABSENT;
      release_recorded_exits (cfun);
      tree_estimate_probability (false);
    }
}

#else /* If isl is not available: #ifndef HAVE_isl.  */

static void
graphite_transform_loops (void)
{
  sorry ("Graphite loop optimizations cannot be used (isl is not available).");
}

#endif


static unsigned int
graphite_transforms (struct function *fun)
{
  if (number_of_loops (fun) <= 1)
    return 0;

  graphite_transform_loops ();

  return 0;
}

static bool
gate_graphite_transforms (void)
{
  /* Enable -fgraphite pass if any one of the graphite optimization flags
     is turned on.  */
  if (flag_graphite_identity
      || flag_loop_parallelize_all
      || flag_loop_nest_optimize)
    flag_graphite = 1;

  return flag_graphite != 0;
}

namespace {

const pass_data pass_data_graphite =
{
  GIMPLE_PASS, /* type */
  "graphite0", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_GRAPHITE, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_graphite : public gimple_opt_pass
{
public:
  pass_graphite (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_graphite, ctxt)
  {}

  /* opt_pass methods: */
  virtual bool gate (function *) { return gate_graphite_transforms (); }

}; // class pass_graphite

} // anon namespace

gimple_opt_pass *
make_pass_graphite (gcc::context *ctxt)
{
  return new pass_graphite (ctxt);
}

namespace {

const pass_data pass_data_graphite_transforms =
{
  GIMPLE_PASS, /* type */
  "graphite", /* name */
  OPTGROUP_LOOP, /* optinfo_flags */
  TV_GRAPHITE_TRANSFORMS, /* tv_id */
  ( PROP_cfg | PROP_ssa ), /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_graphite_transforms : public gimple_opt_pass
{
public:
  pass_graphite_transforms (gcc::context *ctxt)
    : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
  {}

  /* opt_pass methods: */
  virtual bool gate (function *) { return gate_graphite_transforms (); }
  virtual unsigned int execute (function *fun) { return graphite_transforms (fun); }

}; // class pass_graphite_transforms

} // anon namespace

gimple_opt_pass *
make_pass_graphite_transforms (gcc::context *ctxt)
{
  return new pass_graphite_transforms (ctxt);
}


