예제 #1
0
/* Return SSA names that are unused to GGC memory and compact the SSA
   version namespace.  This is used to keep footprint of compiler during
   interprocedural optimization.  */
static unsigned int
release_dead_ssa_names (void)
{
  unsigned i, j;
  int n = vec_safe_length (FREE_SSANAMES (cfun));

  /* Now release the freelist.  */
  vec_free (FREE_SSANAMES (cfun));

  /* And compact the SSA number space.  We make sure to not change the
     relative order of SSA versions.  */
  for (i = 1, j = 1; i < cfun->gimple_df->ssa_names->length (); ++i)
    {
      tree name = ssa_name (i);
      if (name)
	{
	  if (i != j)
	    {
	      SSA_NAME_VERSION (name) = j;
	      (*cfun->gimple_df->ssa_names)[j] = name;
	    }
	  j++;
	}
    }
  cfun->gimple_df->ssa_names->truncate (j);

  statistics_counter_event (cfun, "SSA names released", n);
  statistics_counter_event (cfun, "SSA name holes removed", i - j);
  if (dump_file)
    fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n",
	     n, n * 100.0 / num_ssa_names, i - j);
  return 0;
}
예제 #2
0
/* Return SSA names that are unused to GGC memory.  This is used to keep
   footprint of compiler during interprocedural optimization.
   As a side effect the SSA_NAME_VERSION number reuse is reduced
   so this function should not be used too often.  */
static unsigned int
release_dead_ssa_names (void)
{
  tree t, next;
  int n = 0;
  referenced_var_iterator rvi;

  /* Current defs point to various dead SSA names that in turn point to
     eventually dead variables so a bunch of memory is held live.  */
  FOR_EACH_REFERENCED_VAR (t, rvi)
    set_current_def (t, NULL);
  /* Now release the freelist.  */
  for (t = FREE_SSANAMES (cfun); t; t = next)
    {
      next = TREE_CHAIN (t);
      /* Dangling pointers might make GGC to still see dead SSA names, so it is
 	 important to unlink the list and avoid GGC from seeing all subsequent
	 SSA names.  In longer run we want to have all dangling pointers here
	 removed (since they usually go through dead statements that consume
	 considerable amounts of memory).  */
      TREE_CHAIN (t) = NULL_TREE;
      n++;
    }
  FREE_SSANAMES (cfun) = NULL;

  statistics_counter_event (cfun, "SSA names released", n);
  if (dump_file)
    fprintf (dump_file, "Released %i names, %.2f%%\n",
	     n, n * 100.0 / num_ssa_names);
  return 0;
}
예제 #3
0
/* Return SSA names that are unused to GGC memory and compact the SSA
   version namespace.  This is used to keep footprint of compiler during
   interprocedural optimization.  */
static unsigned int
release_dead_ssa_names (void)
{
  tree t;
  unsigned i, j;
  int n = VEC_length (tree, FREE_SSANAMES (cfun));
  referenced_var_iterator rvi;

  /* Current defs point to various dead SSA names that in turn point to
     eventually dead variables so a bunch of memory is held live.  */
  FOR_EACH_REFERENCED_VAR (cfun, t, rvi)
    set_current_def (t, NULL);

  /* Now release the freelist.  */
  VEC_free (tree, gc, FREE_SSANAMES (cfun));
  FREE_SSANAMES (cfun) = NULL;

  /* And compact the SSA number space.  We make sure to not change the
     relative order of SSA versions.  */
  for (i = 1, j = 1; i < VEC_length (tree, cfun->gimple_df->ssa_names); ++i)
    {
      tree name = ssa_name (i);
      if (name)
	{
	  if (i != j)
	    {
	      SSA_NAME_VERSION (name) = j;
	      VEC_replace (tree, cfun->gimple_df->ssa_names, j, name);
	    }
	  j++;
	}
    }
  VEC_truncate (tree, cfun->gimple_df->ssa_names, j);

  statistics_counter_event (cfun, "SSA names released", n);
  statistics_counter_event (cfun, "SSA name holes removed", i - j);
  if (dump_file)
    fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n",
	     n, n * 100.0 / num_ssa_names, i - j);
  return 0;
}
예제 #4
0
static unsigned int
rename_ssa_copies (void)
{
  var_map map;
  basic_block bb;
  gimple_stmt_iterator gsi;
  tree var, part_var;
  gimple stmt, phi;
  unsigned x;
  FILE *debug;
  bool updated = false;

  memset (&stats, 0, sizeof (stats));

  if (dump_file && (dump_flags & TDF_DETAILS))
    debug = dump_file;
  else
    debug = NULL;

  map = init_var_map (num_ssa_names);

  FOR_EACH_BB (bb)
    {
      /* Scan for real copies.  */
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
	{
	  stmt = gsi_stmt (gsi);
	  if (gimple_assign_ssa_name_copy_p (stmt))
	    {
	      tree lhs = gimple_assign_lhs (stmt);
	      tree rhs = gimple_assign_rhs1 (stmt);

	      updated |= copy_rename_partition_coalesce (map, lhs, rhs, debug);
	    }
	}
    }

  FOR_EACH_BB (bb)
    {
      /* Treat PHI nodes as copies between the result and each argument.  */
      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          size_t i;
	  tree res;

	  phi = gsi_stmt (gsi);
	  res = gimple_phi_result (phi);

	  /* Do not process virtual SSA_NAMES.  */
	  if (virtual_operand_p (res))
	    continue;

	  /* Make sure to only use the same partition for an argument
	     as the result but never the other way around.  */
	  if (SSA_NAME_VAR (res)
	      && !DECL_IGNORED_P (SSA_NAME_VAR (res)))
	    for (i = 0; i < gimple_phi_num_args (phi); i++)
	      {
		tree arg = PHI_ARG_DEF (phi, i);
		if (TREE_CODE (arg) == SSA_NAME)
		  updated |= copy_rename_partition_coalesce (map, res, arg,
							     debug);
	      }
	  /* Else if all arguments are in the same partition try to merge
	     it with the result.  */
	  else
	    {
	      int all_p_same = -1;
	      int p = -1;
	      for (i = 0; i < gimple_phi_num_args (phi); i++)
		{
		  tree arg = PHI_ARG_DEF (phi, i);
		  if (TREE_CODE (arg) != SSA_NAME)
		    {
		      all_p_same = 0;
		      break;
		    }
		  else if (all_p_same == -1)
		    {
		      p = partition_find (map->var_partition,
					  SSA_NAME_VERSION (arg));
		      all_p_same = 1;
		    }
		  else if (all_p_same == 1
			   && p != partition_find (map->var_partition,
						   SSA_NAME_VERSION (arg)))
		    {
		      all_p_same = 0;
		      break;
		    }
		}
	      if (all_p_same == 1)
		updated |= copy_rename_partition_coalesce (map, res,
							   PHI_ARG_DEF (phi, 0),
							   debug);
	    }
        }
    }

  if (debug)
    dump_var_map (debug, map);

  /* Now one more pass to make all elements of a partition share the same
     root variable.  */

  for (x = 1; x < num_ssa_names; x++)
    {
      part_var = partition_to_var (map, x);
      if (!part_var)
        continue;
      var = ssa_name (x);
      if (SSA_NAME_VAR (var) == SSA_NAME_VAR (part_var))
	continue;
      if (debug)
        {
	  fprintf (debug, "Coalesced ");
	  print_generic_expr (debug, var, TDF_SLIM);
	  fprintf (debug, " to ");
	  print_generic_expr (debug, part_var, TDF_SLIM);
	  fprintf (debug, "\n");
	}
      stats.coalesced++;
      replace_ssa_name_symbol (var, SSA_NAME_VAR (part_var));
    }

  statistics_counter_event (cfun, "copies coalesced",
			    stats.coalesced);
  delete_var_map (map);
  return updated ? TODO_remove_unused_locals : 0;
}
예제 #5
0
unsigned
vectorize_loops (void)
{
  unsigned int i;
  unsigned int num_vectorized_loops = 0;
  unsigned int vect_loops_num;
  loop_iterator li;
  struct loop *loop;

  vect_loops_num = number_of_loops ();

  /* Bail out if there are no loops.  */
  if (vect_loops_num <= 1)
    return 0;

  /* Fix the verbosity level if not defined explicitly by the user.  */
  vect_set_dump_settings (false);

  init_stmt_vec_info_vec ();

  /*  ----------- Analyze loops. -----------  */

  /* If some loop was duplicated, it gets bigger number
     than all previously defined loops.  This fact allows us to run
     only over initial loops skipping newly generated ones.  */
  FOR_EACH_LOOP (li, loop, 0)
    if (optimize_loop_nest_for_speed_p (loop))
      {
	loop_vec_info loop_vinfo;

	vect_location = find_loop_location (loop);
        if (vect_location != UNKNOWN_LOC
            && vect_verbosity_level > REPORT_NONE)
	  fprintf (vect_dump, "\nAnalyzing loop at %s:%d\n",
            LOC_FILE (vect_location), LOC_LINE (vect_location));

	loop_vinfo = vect_analyze_loop (loop);
	loop->aux = loop_vinfo;

	if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo))
	  continue;

        if (vect_location != UNKNOWN_LOC
            && vect_verbosity_level > REPORT_NONE)
          fprintf (vect_dump, "\n\nVectorizing loop at %s:%d\n",
            LOC_FILE (vect_location), LOC_LINE (vect_location));

	vect_transform_loop (loop_vinfo);
	num_vectorized_loops++;
      }

  vect_location = UNKNOWN_LOC;

  statistics_counter_event (cfun, "Vectorized loops", num_vectorized_loops);
  if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS)
      || (num_vectorized_loops > 0
	  && vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS)))
    fprintf (vect_dump, "vectorized %u loops in function.\n",
	     num_vectorized_loops);

  /*  ----------- Finalize. -----------  */

  mark_sym_for_renaming (gimple_vop (cfun));

  for (i = 1; i < vect_loops_num; i++)
    {
      loop_vec_info loop_vinfo;

      loop = get_loop (i);
      if (!loop)
	continue;
      loop_vinfo = (loop_vec_info) loop->aux;
      destroy_loop_vec_info (loop_vinfo, true);
      loop->aux = NULL;
    }

  free_stmt_vec_info_vec ();

  return num_vectorized_loops > 0 ? TODO_cleanup_cfg : 0;
}
예제 #6
0
파일: tree-vectorizer.c 프로젝트: Lao16/gcc
unsigned
vectorize_loops (void)
{
  unsigned int i;
  unsigned int num_vectorized_loops = 0;
  unsigned int vect_loops_num;
  loop_iterator li;
  struct loop *loop;

  vect_loops_num = number_of_loops ();

  /* Bail out if there are no loops.  */
  if (vect_loops_num <= 1)
    return 0;

  init_stmt_vec_info_vec ();

  /*  ----------- Analyze loops. -----------  */

  /* If some loop was duplicated, it gets bigger number
     than all previously defined loops.  This fact allows us to run
     only over initial loops skipping newly generated ones.  */
  FOR_EACH_LOOP (li, loop, 0)
    if (optimize_loop_nest_for_speed_p (loop))
      {
	loop_vec_info loop_vinfo;
	vect_location = find_loop_location (loop);
        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
	    && dump_enabled_p ())
	  dump_printf (MSG_ALL, "\nAnalyzing loop at %s:%d\n",
                       LOC_FILE (vect_location), LOC_LINE (vect_location));

	loop_vinfo = vect_analyze_loop (loop);
	loop->aux = loop_vinfo;

	if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo))
	  continue;

        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
	    && dump_enabled_p ())
          dump_printf (MSG_ALL, "\n\nVectorizing loop at %s:%d\n",
                       LOC_FILE (vect_location), LOC_LINE (vect_location));
	vect_transform_loop (loop_vinfo);
	num_vectorized_loops++;
      }

  vect_location = UNKNOWN_LOC;

  statistics_counter_event (cfun, "Vectorized loops", num_vectorized_loops);
  if (dump_enabled_p ()
      || (num_vectorized_loops > 0 && dump_enabled_p ()))
    dump_printf_loc (MSG_ALL, vect_location,
                     "vectorized %u loops in function.\n",
                     num_vectorized_loops);

  /*  ----------- Finalize. -----------  */

  for (i = 1; i < vect_loops_num; i++)
    {
      loop_vec_info loop_vinfo;

      loop = get_loop (i);
      if (!loop)
	continue;
      loop_vinfo = (loop_vec_info) loop->aux;
      destroy_loop_vec_info (loop_vinfo, true);
      loop->aux = NULL;
    }

  free_stmt_vec_info_vec ();

  return num_vectorized_loops > 0 ? TODO_cleanup_cfg : 0;
}
예제 #7
0
파일: tree-vectorizer.c 프로젝트: Roffi/gcc
unsigned
vectorize_loops (void)
{
    unsigned int i;
    unsigned int num_vectorized_loops = 0;
    unsigned int vect_loops_num;
    loop_iterator li;
    struct loop *loop;

    vect_loops_num = number_of_loops (cfun);

    /* Bail out if there are no loops.  */
    if (vect_loops_num <= 1)
        return 0;

    init_stmt_vec_info_vec ();

    /*  ----------- Analyze loops. -----------  */

    /* If some loop was duplicated, it gets bigger number
       than all previously defined loops.  This fact allows us to run
       only over initial loops skipping newly generated ones.  */
    FOR_EACH_LOOP (li, loop, 0)
    if (optimize_loop_nest_for_speed_p (loop))
    {
        loop_vec_info loop_vinfo;
        vect_location = find_loop_location (loop);
        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
                && dump_enabled_p ())
            dump_printf (MSG_NOTE, "\nAnalyzing loop at %s:%d\n",
                         LOC_FILE (vect_location), LOC_LINE (vect_location));

        loop_vinfo = vect_analyze_loop (loop);
        loop->aux = loop_vinfo;

        if (!loop_vinfo || !LOOP_VINFO_VECTORIZABLE_P (loop_vinfo))
            continue;

        if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOC
                && dump_enabled_p ())
            dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
                             "Vectorized loop\n");
        vect_transform_loop (loop_vinfo);
        num_vectorized_loops++;
    }

    vect_location = UNKNOWN_LOC;

    statistics_counter_event (cfun, "Vectorized loops", num_vectorized_loops);
    if (dump_enabled_p ()
            || (num_vectorized_loops > 0 && dump_enabled_p ()))
        dump_printf_loc (MSG_NOTE, vect_location,
                         "vectorized %u loops in function.\n",
                         num_vectorized_loops);

    /*  ----------- Finalize. -----------  */

    for (i = 1; i < vect_loops_num; i++)
    {
        loop_vec_info loop_vinfo;

        loop = get_loop (cfun, i);
        if (!loop)
            continue;
        loop_vinfo = (loop_vec_info) loop->aux;
        destroy_loop_vec_info (loop_vinfo, true);
        loop->aux = NULL;
    }

    free_stmt_vec_info_vec ();

    if (num_vectorized_loops > 0)
    {
        /* If we vectorized any loop only virtual SSA form needs to be updated.
        ???  Also while we try hard to update loop-closed SSA form we fail
         to properly do this in some corner-cases (see PR56286).  */
        rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa_only_virtuals);
        return TODO_cleanup_cfg;
    }

    return 0;
}