Beispiel #1
0
edge
ssa_redirect_edge (edge e, basic_block dest)
{
  tree phi;
  tree list = NULL, *last = &list;
  tree src, dst, node;

  /* Remove the appropriate PHI arguments in E's destination block.  */
  for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
    {
      if (PHI_ARG_DEF (phi, e->dest_idx) == NULL_TREE)
	continue;

      src = PHI_ARG_DEF (phi, e->dest_idx);
      dst = PHI_RESULT (phi);
      node = build_tree_list (dst, src);
      *last = node;
      last = &TREE_CHAIN (node);
    }

  e = redirect_edge_succ_nodup (e, dest);
  PENDING_STMT (e) = list;

  return e;
}
Beispiel #2
0
static void
tree_ssa_phiopt (void)
{
  basic_block bb;
  bool removed_phis = false;

  /* Search every basic block for PHI nodes we may be able to optimize.  */
  FOR_EACH_BB (bb)
    {
      tree arg0, arg1, phi;

      /* We're searching for blocks with one PHI node which has two
	 arguments.  */
      phi = phi_nodes (bb);
      if (phi && PHI_CHAIN (phi) == NULL
	  && PHI_NUM_ARGS (phi) == 2)
	{
	  arg0 = PHI_ARG_DEF (phi, 0);
	  arg1 = PHI_ARG_DEF (phi, 1);
	    
	  /* Do the replacement of conditional if it can be done.  */
	    if (conditional_replacement (bb, phi, arg0, arg1)
		|| value_replacement (bb, phi, arg0, arg1)
		|| abs_replacement (bb, phi, arg0, arg1))
	      {
		/* We have done the replacement so we need to rebuild the
		   cfg when this pass is complete.  */
		removed_phis = true;
	      }
	}
    }
}
Beispiel #3
0
static basic_block
find_bb_for_arg (gphi *phi, tree def)
{
  size_t i;
  bool foundone = false;
  basic_block result = NULL;
  for (i = 0; i < gimple_phi_num_args (phi); i++)
    if (PHI_ARG_DEF (phi, i) == def)
      {
	if (foundone)
	  return NULL;
	foundone = true;
	result = gimple_phi_arg_edge (phi, i)->src;
      }
  return result;
}
Beispiel #4
0
static void
eliminate_build (elim_graph g)
{
  tree Ti;
  int p0, pi;
  gimple_stmt_iterator gsi;

  clear_elim_graph (g);

  for (gsi = gsi_start_phis (g->e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
    {
      gimple phi = gsi_stmt (gsi);
      source_location locus;

      p0 = var_to_partition (g->map, gimple_phi_result (phi));
      /* Ignore results which are not in partitions.  */
      if (p0 == NO_PARTITION)
	continue;

      Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
      locus = gimple_phi_arg_location_from_edge (phi, g->e);

      /* If this argument is a constant, or a SSA_NAME which is being
	 left in SSA form, just queue a copy to be emitted on this
	 edge.  */
      if (!phi_ssa_name_p (Ti)
	  || (TREE_CODE (Ti) == SSA_NAME
	      && var_to_partition (g->map, Ti) == NO_PARTITION))
        {
	  /* Save constant copies until all other copies have been emitted
	     on this edge.  */
	  VEC_safe_push (int, heap, g->const_dests, p0);
	  VEC_safe_push (tree, heap, g->const_copies, Ti);
	  VEC_safe_push (source_location, heap, g->copy_locus, locus);
	}
      else
        {
Beispiel #5
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;
}