#include "timevar.h"
#include "tree-pass.h"
#include "pointer-set.h"
+#include "profile.h"
/* In this file value profile based optimizations are placed. Currently the
following optimizations are implemented (for more detailed descriptions
return true;
}
-static struct cgraph_node** pid_map = NULL;
+static VEC(cgraph_node_ptr, heap) *cgraph_node_map = NULL;
-/* Initialize map of pids (pid -> cgraph node) */
+/* Initialize map from FUNCDEF_NO to CGRAPH_NODE. */
-static void
-init_pid_map (void)
+void
+init_node_map (void)
{
struct cgraph_node *n;
- if (pid_map != NULL)
- return;
-
- pid_map = XCNEWVEC (struct cgraph_node*, cgraph_max_pid);
+ if (get_last_funcdef_no ())
+ VEC_safe_grow_cleared (cgraph_node_ptr, heap,
+ cgraph_node_map, get_last_funcdef_no ());
for (n = cgraph_nodes; n; n = n->next)
{
- if (n->pid != -1)
- pid_map [n->pid] = n;
+ if (DECL_STRUCT_FUNCTION (n->decl))
+ VEC_replace (cgraph_node_ptr, cgraph_node_map,
+ DECL_STRUCT_FUNCTION (n->decl)->funcdef_no, n);
}
}
+/* Delete the CGRAPH_NODE_MAP. */
+
+void
+del_node_map (void)
+{
+ VEC_free (cgraph_node_ptr, heap, cgraph_node_map);
+ cgraph_node_map = NULL;
+}
+
/* Return cgraph node for function with pid */
static inline struct cgraph_node*
-find_func_by_pid (int pid)
+find_func_by_funcdef_no (int func_id)
{
- init_pid_map ();
+ int max_id = get_last_funcdef_no ();
+ if (func_id >= max_id || VEC_index (cgraph_node_ptr,
+ cgraph_node_map,
+ func_id) == NULL)
+ {
+ if (flag_profile_correction)
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "Inconsistent profile: indirect call target (%d) does not exist", func_id);
+ else
+ error ("Inconsistent profile: indirect call target (%d) does not exist", func_id);
+
+ return NULL;
+ }
- return pid_map [pid];
+ return VEC_index (cgraph_node_ptr, cgraph_node_map, func_id);
}
/* Perform sanity check on the indirect call target. Due to race conditions,
{
gimple dcall_stmt, load_stmt, cond_stmt;
tree tmp0, tmp1, tmpv, tmp;
- basic_block cond_bb, dcall_bb, icall_bb, join_bb;
+ basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL;
tree optype = build_pointer_type (void_type_node);
- edge e_cd, e_ci, e_di, e_dj, e_ij;
+ edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
gimple_stmt_iterator gsi;
int lp_nr;
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));
+ /* The indirect call might be noreturn. */
+ if (e_ij != NULL)
+ {
+ e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->count = all - count;
+ e_ij = single_pred_edge (split_edge (e_ij));
+ }
+ }
+ if (e_ij != NULL)
+ {
+ join_bb = e_ij->dest;
+ join_bb->count = all;
}
- join_bb = e_ij->dest;
- join_bb->count = all;
e_cd->flags = (e_cd->flags & ~EDGE_FALLTHRU) | EDGE_TRUE_VALUE;
e_cd->probability = prob;
remove_edge (e_di);
- e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
- e_dj->probability = REG_BR_PROB_BASE;
- e_dj->count = count;
+ if (e_ij != NULL)
+ {
+ e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
+ e_dj->probability = REG_BR_PROB_BASE;
+ e_dj->count = count;
- e_ij->probability = REG_BR_PROB_BASE;
- e_ij->count = all - count;
+ e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->count = all - count;
+ }
/* Insert PHI node for the call result if necessary. */
if (gimple_call_lhs (icall_stmt)
if (gimple_call_fndecl (stmt) != NULL_TREE)
return false;
+ if (gimple_call_internal_p (stmt))
+ return false;
+
histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
if (!histogram)
return false;
prob = (count * REG_BR_PROB_BASE + all / 2) / all;
else
prob = 0;
- direct_call = find_func_by_pid ((int)val);
+ direct_call = find_func_by_funcdef_no ((int)val);
if (direct_call == NULL)
return false;
tree callee;
if (gimple_code (stmt) != GIMPLE_CALL
+ || gimple_call_internal_p (stmt)
|| gimple_call_fndecl (stmt) != NULL_TREE)
return;