/* Transformations based on profile information for values.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
#include "cgraph.h"
#include "timevar.h"
#include "tree-pass.h"
-#include "toplev.h"
#include "pointer-set.h"
-static struct value_prof_hooks *value_prof_hooks;
-
/* In this file value profile based optimizations are placed. Currently the
following optimizations are implemented (for more detailed descriptions
see comments at value_profile_transformations):
/* GIMPLE based transformations. */
-static bool
+bool
gimple_value_profile_transformations (void)
{
basic_block bb;
}
gimple_assign_set_rhs_from_tree (si, result);
+ update_stmt (gsi_stmt (*si));
return true;
}
result = gimple_mod_pow2 (stmt, prob, count, all);
gimple_assign_set_rhs_from_tree (si, result);
+ update_stmt (gsi_stmt (*si));
return true;
}
result = gimple_mod_subtract (stmt, prob1, prob2, i, count1, count2, all);
gimple_assign_set_rhs_from_tree (si, result);
+ update_stmt (gsi_stmt (*si));
return true;
}
icall_bb = e_di->dest;
icall_bb->count = all - count;
- e_ij = split_block (icall_bb, icall_stmt);
+ /* Do not disturb existing EH edges from the indirect call. */
+ if (!stmt_ends_bb_p (icall_stmt))
+ e_ij = split_block (icall_bb, icall_stmt);
+ else
+ {
+ e_ij = find_fallthru_edge (icall_bb->succs);
+ e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->count = all - count;
+ e_ij = single_pred_edge (split_edge (e_ij));
+ }
join_bb = e_ij->dest;
join_bb->count = all;
add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION);
}
- /* Fix eh edges */
+ /* Build an EH edge for the direct call if necessary. */
lp_nr = lookup_stmt_eh_lp (icall_stmt);
- if (lp_nr != 0)
+ if (lp_nr != 0
+ && stmt_could_throw_p (dcall_stmt))
{
- if (stmt_could_throw_p (dcall_stmt))
+ edge e_eh, e;
+ edge_iterator ei;
+ gimple_stmt_iterator psi;
+
+ add_stmt_to_eh_lp (dcall_stmt, lp_nr);
+ FOR_EACH_EDGE (e_eh, ei, icall_bb->succs)
+ if (e_eh->flags & EDGE_EH)
+ break;
+ e = make_edge (dcall_bb, e_eh->dest, EDGE_EH);
+ for (psi = gsi_start_phis (e_eh->dest);
+ !gsi_end_p (psi); gsi_next (&psi))
{
- add_stmt_to_eh_lp (dcall_stmt, lp_nr);
- make_eh_edges (dcall_stmt);
+ gimple phi = gsi_stmt (psi);
+ SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e),
+ PHI_ARG_DEF_FROM_EDGE (phi, e_eh));
}
-
- gcc_assert (stmt_could_throw_p (icall_stmt));
- make_eh_edges (icall_stmt);
-
- /* The old EH edges are sill on the join BB, purge them. */
- gimple_purge_dead_eh_edges (join_bb);
}
return dcall_stmt;
e_vj->probability = REG_BR_PROB_BASE;
e_vj->count = all - count;
+ /* Insert PHI node for the call result if necessary. */
+ if (gimple_call_lhs (vcall_stmt)
+ && TREE_CODE (gimple_call_lhs (vcall_stmt)) == SSA_NAME)
+ {
+ tree result = gimple_call_lhs (vcall_stmt);
+ gimple phi = create_phi_node (result, join_bb);
+ SSA_NAME_DEF_STMT (result) = phi;
+ gimple_call_set_lhs (vcall_stmt,
+ make_ssa_name (SSA_NAME_VAR (result), vcall_stmt));
+ add_phi_arg (phi, gimple_call_lhs (vcall_stmt), e_vj, UNKNOWN_LOCATION);
+ gimple_call_set_lhs (icall_stmt,
+ make_ssa_name (SSA_NAME_VAR (result), icall_stmt));
+ add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION);
+ }
+
/* Because these are all string op builtins, they're all nothrow. */
gcc_assert (!stmt_could_throw_p (vcall_stmt));
gcc_assert (!stmt_could_throw_p (icall_stmt));
}
}
-struct value_prof_hooks {
- /* Find list of values for which we want to measure histograms. */
- void (*find_values_to_profile) (histogram_values *);
-
- /* Identify and exploit properties of values that are hard to analyze
- statically. See value-prof.c for more detail. */
- bool (*value_profile_transformations) (void);
-};
\f
/* Find values inside STMT for that we want to measure histograms for
division/modulo optimization. */
}
}
-static void
+void
gimple_find_values_to_profile (histogram_values *values)
{
basic_block bb;
}
}
-static struct value_prof_hooks gimple_value_prof_hooks = {
- gimple_find_values_to_profile,
- gimple_value_profile_transformations
-};
-
-void
-gimple_register_value_prof_hooks (void)
-{
- gcc_assert (current_ir_type () == IR_GIMPLE);
- value_prof_hooks = &gimple_value_prof_hooks;
-}
-\f
-/* IR-independent entry points. */
-void
-find_values_to_profile (histogram_values *values)
-{
- (value_prof_hooks->find_values_to_profile) (values);
-}
-
-bool
-value_profile_transformations (void)
-{
- return (value_prof_hooks->value_profile_transformations) ();
-}
-\f