Index: gcc/gcc/tree-profile.c |
diff --git a/gcc/gcc/tree-profile.c b/gcc/gcc/tree-profile.c |
index 4467668a8858632e7af13b0f5081987d1d38bfb9..59d37666dbe1740a85e6a28340f3cfde923c0a60 100644 |
--- a/gcc/gcc/tree-profile.c |
+++ b/gcc/gcc/tree-profile.c |
@@ -431,6 +431,42 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base) |
add_abnormal_goto_call_edges (gsi); |
} |
+/* Output instructions as GIMPLE trees to suspend thread if needed. */ |
+ |
+static void |
+tree_gen_thread_suspension_instrumentation (edge e) |
+{ |
+ static tree tree_suspend_thread_fn = NULL_TREE; |
+ |
+ basic_block bb; |
+ gimple_stmt_iterator gsi; |
+ gimple stmt; |
+ |
+ if (tree_suspend_thread_fn == NULL_TREE) |
+ { |
+ tree type = build_function_type (void_type_node, void_list_node); |
+ tree id = get_identifier ("__nacl_suspend_thread_if_needed"); |
+ tree decl = build_decl (FUNCTION_DECL, id, type); |
+ |
+ tree libname = get_identifier ("__nacl_suspend_thread_if_needed"); |
+ |
+ TREE_PUBLIC (decl) = 1; |
+ DECL_EXTERNAL (decl) = 1; |
+ |
+ SET_DECL_ASSEMBLER_NAME (decl, libname); |
+ |
+ tree_suspend_thread_fn = decl; |
+ } |
+ |
+ bb = split_edge (e); |
+ gsi = gsi_start_bb (bb); |
+ |
+ stmt = gimple_build_call (tree_suspend_thread_fn, 0); |
+ |
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); |
+ add_abnormal_goto_call_edges (gsi); |
+} |
+ |
/* Return 1 if tree-based profiling is in effect, else 0. |
If it is, set up hooks for tree-based profiling. |
Gate for pass_tree_profile. */ |
@@ -444,12 +480,41 @@ do_tree_profiling (void) |
gimple_register_value_prof_hooks (); |
return true; |
} |
+ /* HACK: enable this pass for inserting thread suspension instrumentation. */ |
+ if (flag_instrument_for_thread_suspension) |
+ return true; |
return false; |
} |
static unsigned int |
tree_profiling (void) |
{ |
+ /* Perhaps this code should go somewhere else... |
+ And probably it should not run after_tree_profile... */ |
+ if (flag_instrument_for_thread_suspension) |
+ { |
+ basic_block bb; |
+ edge e; |
+ edge_iterator ei; |
+ |
+ mark_dfs_back_edges (); |
+ |
+ FOR_EACH_BB (bb) |
+ { |
+ FOR_EACH_EDGE (e, ei, bb->preds) |
+ { |
+ /* Instrument beginning of the function and back edges. */ |
+ if (e->src == ENTRY_BLOCK_PTR |
+ || e->flags & EDGE_DFS_BACK) |
+ tree_gen_thread_suspension_instrumentation (e); |
+ } |
+ } |
+ |
+ /* HACK: exit if we only need thread suspension instrumentation. */ |
+ if (!(profile_arc_flag || flag_test_coverage || flag_branch_probabilities)) |
+ return 0; |
+ } |
+ |
/* Don't profile functions produced at destruction time, particularly |
the gcov datastructure initializer. Don't profile if it has been |
already instrumented either (when OpenMP expansion creates |