Esempio n. 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;
}
Esempio n. 2
0
void
flush_pending_stmts (edge e)
{
  tree phi, arg;

  if (!PENDING_STMT (e))
    return;

  for (phi = phi_nodes (e->dest), arg = PENDING_STMT (e);
       phi;
       phi = PHI_CHAIN (phi), arg = TREE_CHAIN (arg))
    {
      tree def = TREE_VALUE (arg);
      add_phi_arg (phi, def, e);
    }

  PENDING_STMT (e) = NULL;
}
Esempio n. 3
0
void
gsi_commit_one_edge_insert (edge e, basic_block *new_bb)
{
  if (new_bb)
    *new_bb = NULL;

  if (PENDING_STMT (e))
    {
      gimple_stmt_iterator gsi;
      gimple_seq seq = PENDING_STMT (e);
      bool ins_after;

      PENDING_STMT (e) = NULL;

      ins_after = gimple_find_edge_insert_loc (e, &gsi, new_bb);
      update_call_edge_frequencies (gimple_seq_first (seq), gsi.bb);

      if (ins_after)
	gsi_insert_seq_after (&gsi, seq, GSI_NEW_STMT);
      else
	gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
    }
}
Esempio n. 4
0
basic_block
gsi_insert_seq_on_edge_immediate (edge e, gimple_seq stmts)
{
  gimple_stmt_iterator gsi;
  basic_block new_bb = NULL;
  bool ins_after;

  gcc_assert (!PENDING_STMT (e));

  ins_after = gimple_find_edge_insert_loc (e, &gsi, &new_bb);
  update_call_edge_frequencies (gimple_seq_first (stmts), gsi.bb);

  if (ins_after)
    gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
  else
    gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);

  return new_bb;
}
Esempio n. 5
0
basic_block
gsi_insert_on_edge_immediate (edge e, gimple stmt)
{
  gimple_stmt_iterator gsi;
  struct gimple_seq_node_d node;
  basic_block new_bb = NULL;
  bool ins_after;

  gcc_assert (!PENDING_STMT (e));

  ins_after = gimple_find_edge_insert_loc (e, &gsi, &new_bb);

  node.stmt = stmt;
  node.prev = node.next = NULL;
  update_call_edge_frequencies (&node, gsi.bb);

  if (ins_after)
    gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
  else
    gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);

  return new_bb;
}
Esempio n. 6
0
static void
eliminate_tail_call (struct tailcall *t)
{
  tree param, rslt;
  gimple stmt, call;
  tree arg;
  size_t idx;
  basic_block bb, first;
  edge e;
  gimple phi;
  gimple_stmt_iterator gsi;
  gimple orig_stmt;

  stmt = orig_stmt = gsi_stmt (t->call_gsi);
  bb = gsi_bb (t->call_gsi);

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file, "Eliminated tail recursion in bb %d : ",
	       bb->index);
      print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
      fprintf (dump_file, "\n");
    }

  gcc_assert (is_gimple_call (stmt));

  first = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));

  /* Remove the code after call_gsi that will become unreachable.  The
     possibly unreachable code in other blocks is removed later in
     cfg cleanup.  */
  gsi = t->call_gsi;
  gsi_next (&gsi);
  while (!gsi_end_p (gsi))
    {
      gimple t = gsi_stmt (gsi);
      /* Do not remove the return statement, so that redirect_edge_and_branch
	 sees how the block ends.  */
      if (gimple_code (t) == GIMPLE_RETURN)
	break;

      gsi_remove (&gsi, true);
      release_defs (t);
    }

  /* Number of executions of function has reduced by the tailcall.  */
  e = single_succ_edge (gsi_bb (t->call_gsi));
  decrease_profile (EXIT_BLOCK_PTR_FOR_FN (cfun), e->count, EDGE_FREQUENCY (e));
  decrease_profile (ENTRY_BLOCK_PTR_FOR_FN (cfun), e->count,
		    EDGE_FREQUENCY (e));
  if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    decrease_profile (e->dest, e->count, EDGE_FREQUENCY (e));

  /* Replace the call by a jump to the start of function.  */
  e = redirect_edge_and_branch (single_succ_edge (gsi_bb (t->call_gsi)),
				first);
  gcc_assert (e);
  PENDING_STMT (e) = NULL;

  /* Add phi node entries for arguments.  The ordering of the phi nodes should
     be the same as the ordering of the arguments.  */
  for (param = DECL_ARGUMENTS (current_function_decl),
	 idx = 0, gsi = gsi_start_phis (first);
       param;
       param = DECL_CHAIN (param), idx++)
    {
      if (!arg_needs_copy_p (param))
	continue;

      arg = gimple_call_arg (stmt, idx);
      phi = gsi_stmt (gsi);
      gcc_assert (param == SSA_NAME_VAR (PHI_RESULT (phi)));

      add_phi_arg (phi, arg, e, gimple_location (stmt));
      gsi_next (&gsi);
    }

  /* Update the values of accumulators.  */
  adjust_accumulator_values (t->call_gsi, t->mult, t->add, e);

  call = gsi_stmt (t->call_gsi);
  rslt = gimple_call_lhs (call);
  if (rslt != NULL_TREE)
    {
      /* Result of the call will no longer be defined.  So adjust the
	 SSA_NAME_DEF_STMT accordingly.  */
      SSA_NAME_DEF_STMT (rslt) = gimple_build_nop ();
    }

  gsi_remove (&t->call_gsi, true);
  release_defs (call);
}
Esempio n. 7
0
gimple_stmt_iterator
gsi_start_edge (edge e)
{
  return gsi_start (PENDING_STMT (e));
}
Esempio n. 8
0
void
gsi_insert_seq_on_edge (edge e, gimple_seq seq)
{
  gimple_seq_add_seq (&PENDING_STMT (e), seq);
}
Esempio n. 9
0
void
gsi_insert_on_edge (edge e, gimple *stmt)
{
  gimple_seq_add_stmt (&PENDING_STMT (e), stmt);
}