[PATCH] Move profiling to SSA
Richard Guenther
rguenther@suse.de
Thu Sep 23 22:15:00 GMT 2010
This moves profile (and coverage) instrumentation to SSA, removing
the need of a separate early inliner and this eventually killing
the last non-SSA inlining path (well, not quite yet I guess).
The only issue is non-local gotos which need some new attribute
for the profile functions, Honza had some patch for this that needs
updating.
Another issue is that gcc.dg/tree-prof/inliner-1.c now fails, but
the function hot/coldness looks ok after profile-read, just we
seem to re-set and re-compute this all over the place eventually
reaching cold state before inlining. Honza, can you look at that?
It's a twisted maze to me.
Bootstrapped and tested on x86_64-unknown-linux-gnu (w/o Ada, that's
currently broken).
Richard.
2010-09-22 Richard Guenther <rguenther@suse.de>
* value-prof.c (gimple_divmod_fixed_value): Work on SSA form.
(gimple_mod_pow2): Likewise.
(gimple_mod_subtract): Likewise.
(gimple_ic): Likewise.
(gimple_stringop_fixed_value): Likewise.
* tree-profile.c (tree_init_edge_profiler): Mark profile
functions nothrow.
(tree_gen_edge_profiler): Work on SSA form.
(tree_gen_ic_profiler): Likewise.
(do_tree_profiling): Skip functions with non-local goto for now.
Update SSA form.
(gate_tree_profile_ipa): New function.
(pass_ipa_tree_profile): New.
* passes.c (init_optimization_passes): Remove early non-SSA
inlining. Move profiling after early optimizations.
* ipa-inline.c (cgraph_gate_ipa_early_inlining): Remove.
(pass_ipa_early_inline): Likewise.
* tree-pass.h (pass_ipa_early_inline): Remove.
(pass_ipa_tree_profile): Declare.
* gcc.dg/tree-prof/val-prof-1.c: Adjust.
* g++.dg/tree-prof/indir-call-prof.C: Likewise.
* g++.dg/tree-prof/inline_mismatch_args.C: Likewise.
* gcc.dg/tree-prof/tracer-1.c: Likewise.
* gcc.dg/tree-ssa/inline-4.c: Likewise.
* gcc.dg/tree-ssa/inline-3.c: Likewise.
* gcc.dg/tree-ssa/20080530.c: Likewise.
* g++.dg/tree-ssa/inline-3.C: Likewise.
* g++.dg/tree-ssa/inline-1.C: Likewise.
* g++.dg/tree-ssa/inline-2.C: Likewise.
Index: gcc/value-prof.c
===================================================================
*** gcc/value-prof.c.orig 2010-09-23 10:52:17.000000000 +0200
--- gcc/value-prof.c 2010-09-23 14:58:23.000000000 +0200
*************** gimple_divmod_fixed_value (gimple stmt,
*** 558,564 ****
gcov_type all)
{
gimple stmt1, stmt2, stmt3;
! tree tmp1, tmp2, tmpv;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
--- 558,564 ----
gcov_type all)
{
gimple stmt1, stmt2, stmt3;
! tree tmp0, tmp1, tmp2, tmpv;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
*************** gimple_divmod_fixed_value (gimple stmt,
*** 576,594 ****
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! tmpv = create_tmp_var (optype, "PROF");
! tmp1 = create_tmp_var (optype, "PROF");
! stmt1 = gimple_build_assign (tmpv, fold_convert (optype, value));
stmt2 = gimple_build_assign (tmp1, op2);
! stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
! tmp2 = create_tmp_var (optype, "PROF");
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
! op1, tmpv);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
--- 576,597 ----
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! tmpv = create_tmp_reg (optype, "PROF");
! tmp0 = make_ssa_name (tmpv, NULL);
! tmp1 = make_ssa_name (tmpv, NULL);
! stmt1 = gimple_build_assign (tmp0, fold_convert (optype, value));
! SSA_NAME_DEF_STMT (tmp0) = stmt1;
stmt2 = gimple_build_assign (tmp1, op2);
! SSA_NAME_DEF_STMT (tmp1) = stmt2;
! stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
! tmp2 = make_rename_temp (optype, "PROF");
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
! op1, tmp0);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
*************** static tree
*** 711,717 ****
gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
{
gimple stmt1, stmt2, stmt3, stmt4;
! tree tmp2, tmp3;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
--- 714,720 ----
gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
{
gimple stmt1, stmt2, stmt3, stmt4;
! tree tmp2, tmp3, tmpv;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
*************** gimple_mod_pow2 (gimple stmt, int prob,
*** 729,740 ****
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! result = create_tmp_var (optype, "PROF");
! tmp2 = create_tmp_var (optype, "PROF");
! tmp3 = create_tmp_var (optype, "PROF");
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2,
build_int_cst (optype, -1));
stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2);
stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0),
NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
--- 732,746 ----
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! result = make_rename_temp (optype, "PROF");
! tmpv = create_tmp_var (optype, "PROF");
! tmp2 = make_ssa_name (tmpv, NULL);
! tmp3 = make_ssa_name (tmpv, NULL);
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2,
build_int_cst (optype, -1));
+ SSA_NAME_DEF_STMT (tmp2) = stmt2;
stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2);
+ SSA_NAME_DEF_STMT (tmp3) = stmt3;
stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0),
NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
*************** gimple_mod_subtract (gimple stmt, int pr
*** 881,890 ****
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! result = create_tmp_var (optype, "PROF");
! tmp1 = create_tmp_var (optype, "PROF");
stmt1 = gimple_build_assign (result, op1);
stmt2 = gimple_build_assign (tmp1, op2);
stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
--- 887,897 ----
bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt);
! result = make_rename_temp (optype, "PROF");
! tmp1 = make_ssa_name (create_tmp_var (optype, "PROF"), NULL);
stmt1 = gimple_build_assign (result, op1);
stmt2 = gimple_build_assign (tmp1, op2);
+ SSA_NAME_DEF_STMT (tmp1) = stmt2;
stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
*************** gimple_ic (gimple icall_stmt, struct cgr
*** 1092,1098 ****
int prob, gcov_type count, gcov_type all)
{
gimple dcall_stmt, load_stmt, cond_stmt;
! tree tmp1, tmpv, tmp;
basic_block cond_bb, dcall_bb, icall_bb, join_bb;
tree optype = build_pointer_type (void_type_node);
edge e_cd, e_ci, e_di, e_dj, e_ij;
--- 1099,1105 ----
int prob, gcov_type count, gcov_type all)
{
gimple dcall_stmt, load_stmt, cond_stmt;
! tree tmp0, tmp1, tmpv, tmp;
basic_block cond_bb, dcall_bb, icall_bb, join_bb;
tree optype = build_pointer_type (void_type_node);
edge e_cd, e_ci, e_di, e_dj, e_ij;
*************** gimple_ic (gimple icall_stmt, struct cgr
*** 1102,1121 ****
cond_bb = gimple_bb (icall_stmt);
gsi = gsi_for_stmt (icall_stmt);
! tmpv = create_tmp_var (optype, "PROF");
! tmp1 = create_tmp_var (optype, "PROF");
tmp = unshare_expr (gimple_call_fn (icall_stmt));
! load_stmt = gimple_build_assign (tmpv, tmp);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
tmp = fold_convert (optype, build_addr (direct_call->decl,
current_function_decl));
load_stmt = gimple_build_assign (tmp1, tmp);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
! cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
dcall_stmt = gimple_copy (icall_stmt);
gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
--- 1109,1134 ----
cond_bb = gimple_bb (icall_stmt);
gsi = gsi_for_stmt (icall_stmt);
! tmpv = create_tmp_reg (optype, "PROF");
! tmp0 = make_ssa_name (tmpv, NULL);
! tmp1 = make_ssa_name (tmpv, NULL);
tmp = unshare_expr (gimple_call_fn (icall_stmt));
! load_stmt = gimple_build_assign (tmp0, tmp);
! SSA_NAME_DEF_STMT (tmp0) = load_stmt;
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
tmp = fold_convert (optype, build_addr (direct_call->decl,
current_function_decl));
load_stmt = gimple_build_assign (tmp1, tmp);
+ SSA_NAME_DEF_STMT (tmp1) = load_stmt;
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
! cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
+ gimple_set_vdef (icall_stmt, NULL_TREE);
+ gimple_set_vuse (icall_stmt, NULL_TREE);
+ update_stmt (icall_stmt);
dcall_stmt = gimple_copy (icall_stmt);
gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
*************** gimple_stringop_fixed_value (gimple vcal
*** 1289,1295 ****
gcov_type count, gcov_type all)
{
gimple tmp_stmt, cond_stmt, icall_stmt;
! tree tmp1, tmpv, vcall_size, optype;
basic_block cond_bb, icall_bb, vcall_bb, join_bb;
edge e_ci, e_cv, e_iv, e_ij, e_vj;
gimple_stmt_iterator gsi;
--- 1302,1308 ----
gcov_type count, gcov_type all)
{
gimple tmp_stmt, cond_stmt, icall_stmt;
! tree tmp0, tmp1, tmpv, vcall_size, optype;
basic_block cond_bb, icall_bb, vcall_bb, join_bb;
edge e_ci, e_cv, e_iv, e_ij, e_vj;
gimple_stmt_iterator gsi;
*************** gimple_stringop_fixed_value (gimple vcal
*** 1307,1322 ****
optype = TREE_TYPE (vcall_size);
tmpv = create_tmp_var (optype, "PROF");
! tmp1 = create_tmp_var (optype, "PROF");
! tmp_stmt = gimple_build_assign (tmpv, fold_convert (optype, icall_size));
gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
tmp_stmt = gimple_build_assign (tmp1, vcall_size);
gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
! cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
icall_stmt = gimple_copy (vcall_stmt);
gimple_call_set_arg (icall_stmt, size_arg, icall_size);
gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT);
--- 1320,1341 ----
optype = TREE_TYPE (vcall_size);
tmpv = create_tmp_var (optype, "PROF");
! tmp0 = make_ssa_name (tmpv, NULL);
! tmp1 = make_ssa_name (tmpv, NULL);
! tmp_stmt = gimple_build_assign (tmp0, fold_convert (optype, icall_size));
! SSA_NAME_DEF_STMT (tmp0) = tmp_stmt;
gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
tmp_stmt = gimple_build_assign (tmp1, vcall_size);
+ SSA_NAME_DEF_STMT (tmp1) = tmp_stmt;
gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
! cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
+ gimple_set_vdef (vcall_stmt, NULL);
+ gimple_set_vuse (vcall_stmt, NULL);
+ update_stmt (vcall_stmt);
icall_stmt = gimple_copy (vcall_stmt);
gimple_call_set_arg (icall_stmt, size_arg, icall_size);
gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT);
Index: gcc/tree-profile.c
===================================================================
*** gcc/tree-profile.c.orig 2010-09-23 10:52:17.000000000 +0200
--- gcc/tree-profile.c 2010-09-23 15:51:52.000000000 +0200
*************** tree_init_edge_profiler (void)
*** 120,125 ****
--- 120,126 ----
tree_interval_profiler_fn
= build_fn_decl ("__gcov_interval_profiler",
interval_profiler_fn_type);
+ TREE_NOTHROW (tree_interval_profiler_fn) = 1;
/* void (*) (gcov_type *, gcov_type) */
pow2_profiler_fn_type
*************** tree_init_edge_profiler (void)
*** 128,133 ****
--- 129,135 ----
NULL_TREE);
tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
pow2_profiler_fn_type);
+ TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
/* void (*) (gcov_type *, gcov_type) */
one_value_profiler_fn_type
*************** tree_init_edge_profiler (void)
*** 137,142 ****
--- 139,145 ----
tree_one_value_profiler_fn
= build_fn_decl ("__gcov_one_value_profiler",
one_value_profiler_fn_type);
+ TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
tree_init_ic_make_global_vars ();
*************** tree_init_edge_profiler (void)
*** 149,154 ****
--- 152,159 ----
tree_indirect_call_profiler_fn
= build_fn_decl ("__gcov_indirect_call_profiler",
ic_profiler_fn_type);
+ TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
+
/* void (*) (gcov_type *, gcov_type) */
average_profiler_fn_type
= build_function_type_list (void_type_node,
*************** tree_init_edge_profiler (void)
*** 156,164 ****
--- 161,172 ----
tree_average_profiler_fn
= build_fn_decl ("__gcov_average_profiler",
average_profiler_fn_type);
+ TREE_NOTHROW (tree_average_profiler_fn) = 1;
tree_ior_profiler_fn
= build_fn_decl ("__gcov_ior_profiler",
average_profiler_fn_type);
+ TREE_NOTHROW (tree_average_profiler_fn) = 1;
+
/* LTO streamer needs assembler names. Because we create these decls
late, we need to initialize them by hand. */
DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
*************** tree_gen_edge_profiler (int edgeno, edge
*** 197,209 ****
/* We share one temporary variable declaration per function. This
gets re-set in tree_profiling. */
if (gcov_type_tmp_var == NULL_TREE)
! gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter");
ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
one = build_int_cst (gcov_type_node, 1);
stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
! gcov_type_tmp_var, one);
! stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var);
gsi_insert_on_edge (e, stmt1);
gsi_insert_on_edge (e, stmt2);
gsi_insert_on_edge (e, stmt3);
--- 205,219 ----
/* We share one temporary variable declaration per function. This
gets re-set in tree_profiling. */
if (gcov_type_tmp_var == NULL_TREE)
! gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter");
ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
one = build_int_cst (gcov_type_node, 1);
stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
+ gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1));
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
! gimple_assign_lhs (stmt1), one);
! gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2));
! stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs (stmt2));
gsi_insert_on_edge (e, stmt1);
gsi_insert_on_edge (e, stmt2);
gsi_insert_on_edge (e, stmt3);
*************** tree_gen_ic_profiler (histogram_value va
*** 316,325 ****
__gcov_indirect_call_callee = (void *) indirect call argument;
*/
! tmp1 = create_tmp_var (ptr_void, "PROF");
stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
! stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
--- 326,336 ----
__gcov_indirect_call_callee = (void *) indirect call argument;
*/
! tmp1 = create_tmp_reg (ptr_void, "PROF");
stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
! gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2));
! stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
*************** tree_profiling (void)
*** 481,500 ****
branch_prob ();
if (! flag_branch_probabilities
! && flag_profile_values)
tree_gen_ic_func_profiler ();
if (flag_branch_probabilities
&& flag_profile_values
! && flag_value_profile_transformations)
value_profile_transformations ();
/* The above could hose dominator info. Currently there is
none coming in, this is a safety valve. It should be
easy to adjust it, if and when there is some. */
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
cfun->after_tree_profile = 1;
! return 0;
}
struct gimple_opt_pass pass_tree_profile =
--- 492,514 ----
branch_prob ();
if (! flag_branch_probabilities
! && flag_profile_values
! && !cfun->has_nonlocal_label)
tree_gen_ic_func_profiler ();
if (flag_branch_probabilities
&& flag_profile_values
! && flag_value_profile_transformations
! && !cfun->has_nonlocal_label)
value_profile_transformations ();
+
/* The above could hose dominator info. Currently there is
none coming in, this is a safety valve. It should be
easy to adjust it, if and when there is some. */
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
cfun->after_tree_profile = 1;
! return TODO_update_ssa;
}
struct gimple_opt_pass pass_tree_profile =
*************** struct gimple_opt_pass pass_tree_profile
*** 516,521 ****
--- 530,565 ----
}
};
+ /* When profile instrumentation, use or test coverage shall be performed. */
+
+ static bool
+ gate_tree_profile_ipa (void)
+ {
+ return (!in_lto_p
+ && (flag_branch_probabilities || flag_test_coverage
+ || profile_arc_flag));
+ }
+
+ struct simple_ipa_opt_pass pass_ipa_tree_profile =
+ {
+ {
+ SIMPLE_IPA_PASS,
+ "tree_profile_ipa", /* name */
+ gate_tree_profile_ipa, /* gate */
+ NULL, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_IPA_PROFILE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+ }
+ };
+
+
struct profile_hooks tree_profile_hooks =
{
tree_init_edge_profiler, /* init_edge_profiler */
Index: gcc/passes.c
===================================================================
*** gcc/passes.c.orig 2010-09-23 14:58:22.000000000 +0200
--- gcc/passes.c 2010-09-23 15:52:40.000000000 +0200
*************** init_optimization_passes (void)
*** 746,763 ****
p = &all_small_ipa_passes;
NEXT_PASS (pass_ipa_free_lang_data);
NEXT_PASS (pass_ipa_function_and_variable_visibility);
- NEXT_PASS (pass_ipa_early_inline);
- {
- struct opt_pass **p = &pass_ipa_early_inline.pass.sub;
- NEXT_PASS (pass_early_inline);
- NEXT_PASS (pass_inline_parameters);
- NEXT_PASS (pass_rebuild_cgraph_edges);
- }
NEXT_PASS (pass_early_local_passes);
{
struct opt_pass **p = &pass_early_local_passes.pass.sub;
NEXT_PASS (pass_fixup_cfg);
- NEXT_PASS (pass_tree_profile);
NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_expand_omp);
--- 746,755 ----
*************** init_optimization_passes (void)
*** 803,808 ****
--- 795,806 ----
NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_inline_parameters);
}
+ NEXT_PASS (pass_ipa_tree_profile);
+ {
+ struct opt_pass **p = &pass_ipa_tree_profile.pass.sub;
+ NEXT_PASS (pass_tree_profile);
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ }
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
NEXT_PASS (pass_ipa_lower_emutls);
Index: gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c.orig 2010-09-23 10:52:17.000000000 +0200
--- gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c 2010-09-23 14:58:23.000000000 +0200
*************** main ()
*** 15,21 ****
}
return 0;
}
! /* { dg-final-use { scan-tree-dump "Div.mod by constant n=257 transformation on insn" "tree_profile"} } */
/* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */
--- 15,21 ----
}
return 0;
}
! /* { dg-final-use { scan-tree-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "tree_profile"} } */
/* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: gcc/ipa-inline.c
===================================================================
*** gcc/ipa-inline.c.orig 2010-09-20 11:09:18.000000000 +0200
--- gcc/ipa-inline.c 2010-09-23 15:47:31.000000000 +0200
*************** struct gimple_opt_pass pass_early_inline
*** 1840,1875 ****
}
};
- /* When inlining shall be performed. */
- static bool
- cgraph_gate_ipa_early_inlining (void)
- {
- return (flag_early_inlining
- && !in_lto_p
- && (flag_branch_probabilities || flag_test_coverage
- || profile_arc_flag));
- }
-
- /* IPA pass wrapper for early inlining pass. We need to run early inlining
- before tree profiling so we have stand alone IPA pass for doing so. */
- struct simple_ipa_opt_pass pass_ipa_early_inline =
- {
- {
- SIMPLE_IPA_PASS,
- "einline_ipa", /* name */
- cgraph_gate_ipa_early_inlining, /* gate */
- NULL, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_INLINE_HEURISTICS, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_cgraph /* todo_flags_finish */
- }
- };
/* See if statement might disappear after inlining. We are not terribly
sophisficated, basically looking for simple abstraction penalty wrappers. */
--- 1840,1845 ----
Index: gcc/testsuite/g++.dg/tree-prof/indir-call-prof.C
===================================================================
*** gcc/testsuite/g++.dg/tree-prof/indir-call-prof.C.orig 2007-01-22 11:02:02.000000000 +0100
--- gcc/testsuite/g++.dg/tree-prof/indir-call-prof.C 2010-09-23 15:39:41.000000000 +0200
*************** struct B : public A {
*** 15,20 ****
--- 15,21 ----
{ return 1; }
};
+ void * __attribute__((noinline,noclone)) wrap (void *p) { return p; }
int
main (void)
{
*************** main (void)
*** 23,39 ****
A* p;
! p = &a;
p->AA ();
! p = &b;
p->AA ();
return 0;
}
! /* { dg-final-use { scan-tree-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile"} } */
! /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
! /* { dg-final-use { cleanup-tree-dump "optimized" } } */
! /* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
!
--- 24,39 ----
A* p;
! p = (A *)wrap ((void *)&a);
p->AA ();
! p = (B *)wrap ((void *)&b);
p->AA ();
return 0;
}
! /* { dg-final-use { scan-tree-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile" } } */
! /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized" } } */
! /* { dg-final-use { cleanup-tree-dump "optimized" } } */
! /* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
Index: gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
===================================================================
*** gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C.orig 2009-09-04 15:05:42.000000000 +0200
--- gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C 2010-09-23 15:35:24.000000000 +0200
***************
*** 1,4 ****
! /* { dg-options "-O2 -fdump-tree-einline2" } */
class DocId {
public:
DocId() { }
--- 1,4 ----
! /* { dg-options "-O2 -fdump-tree-einline" } */
class DocId {
public:
DocId() { }
*************** int main(void)
*** 31,36 ****
baz.Bar(&baz, gid);
return 0;
}
! /* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline2"} } */
! /* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline2"} } */
/* { dg-final-use { cleanup-tree-dump "einline2" } } */
--- 31,36 ----
baz.Bar(&baz, gid);
return 0;
}
! /* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline" } } */
! /* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline" } } */
/* { dg-final-use { cleanup-tree-dump "einline2" } } */
Index: gcc/testsuite/gcc.dg/tree-prof/tracer-1.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-prof/tracer-1.c.orig 2007-11-30 13:59:28.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-prof/tracer-1.c 2010-09-23 15:44:03.000000000 +0200
***************
*** 1,8 ****
/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
! main ()
{
int i;
- int a, b, c;
for (i = 0; i < 1000; i++)
{
if (i % 17)
--- 1,8 ----
/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
! volatile int a, b, c;
! int main ()
{
int i;
for (i = 0; i < 1000; i++)
{
if (i % 17)
*************** main ()
*** 14,18 ****
return 0;
}
/* Superblock formation should produce two copies of the increment of c */
! /* { dg-final-generate { scan-tree-dump-times "goto <bb 6>;" 2 "tracer" } } */
/* { dg-final-use { cleanup-tree-dump "tracer" } } */
--- 14,18 ----
return 0;
}
/* Superblock formation should produce two copies of the increment of c */
! /* { dg-final-generate { scan-tree-dump-times "c =" 2 "tracer" } } */
/* { dg-final-use { cleanup-tree-dump "tracer" } } */
Index: gcc/tree-pass.h
===================================================================
*** gcc/tree-pass.h.orig 2010-09-22 13:02:47.000000000 +0200
--- gcc/tree-pass.h 2010-09-23 15:51:27.000000000 +0200
*************** extern struct gimple_opt_pass pass_split
*** 447,453 ****
/* IPA Passes */
extern struct simple_ipa_opt_pass pass_ipa_lower_emutls;
extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
! extern struct simple_ipa_opt_pass pass_ipa_early_inline;
extern struct simple_ipa_opt_pass pass_early_local_passes;
--- 447,453 ----
/* IPA Passes */
extern struct simple_ipa_opt_pass pass_ipa_lower_emutls;
extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
! extern struct simple_ipa_opt_pass pass_ipa_tree_profile;
extern struct simple_ipa_opt_pass pass_early_local_passes;
Index: gcc/testsuite/g++.dg/tree-ssa/inline-1.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/inline-1.C.orig 2010-01-31 14:41:27.000000000 +0100
--- gcc/testsuite/g++.dg/tree-ssa/inline-1.C 2010-09-23 16:39:58.000000000 +0200
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline2" } */
/* { dg-add-options bind_pic_locally } */
namespace std {
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */
namespace std {
*************** int main(int argc, char **argv)
*** 31,36 ****
foreach (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline2"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 31,36 ----
foreach (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
Index: gcc/testsuite/g++.dg/tree-ssa/inline-2.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/inline-2.C.orig 2010-01-31 14:41:27.000000000 +0100
--- gcc/testsuite/g++.dg/tree-ssa/inline-2.C 2010-09-23 16:40:05.000000000 +0200
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline2" } */
/* { dg-add-options bind_pic_locally } */
namespace std {
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */
namespace std {
*************** int main(int argc, char **argv)
*** 31,36 ****
foreach (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline2"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 31,36 ----
foreach (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
Index: gcc/testsuite/g++.dg/tree-ssa/inline-3.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/inline-3.C.orig 2010-01-31 14:41:27.000000000 +0100
--- gcc/testsuite/g++.dg/tree-ssa/inline-3.C 2010-09-23 16:39:51.000000000 +0200
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline2" } */
/* { dg-add-options bind_pic_locally } */
#include <algorithm>
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */
#include <algorithm>
*************** int main(int argc, char **argv)
*** 26,31 ****
std::for_each (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline2"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 26,31 ----
std::for_each (argv, argv + argc, inline_me_too);
}
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me\\(" 1 "einline"} } */
! /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/20080530.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/20080530.c.orig 2008-08-20 10:24:07.000000000 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/20080530.c 2010-09-23 16:39:43.000000000 +0200
*************** baz (void)
*** 18,22 ****
return 6;
}
! /* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline2"} } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 18,22 ----
return 6;
}
! /* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline"} } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/inline-3.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/inline-3.c.orig 2009-10-16 23:15:31.000000000 +0200
--- gcc/testsuite/gcc.dg/tree-ssa/inline-3.c 2010-09-23 16:39:36.000000000 +0200
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline2" } */
/* { dg-add-options bind_pic_locally } */
extern void inlined ();
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */
extern void inlined ();
*************** inline_me_too (void)
*** 27,32 ****
{
inlined();
}
! /* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline2"} } */
! /* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline2"} } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 27,32 ----
{
inlined();
}
! /* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline"} } */
! /* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline"} } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/inline-4.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/inline-4.c.orig 2010-02-10 12:49:07.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/inline-4.c 2010-09-23 16:39:28.000000000 +0200
***************
*** 1,5 ****
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline2" } */
/* { dg-add-options bind_pic_locally } */
extern int rand(void);
--- 1,5 ----
/* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */
extern int rand(void);
*************** int main()
*** 23,27 ****
}
}
! /* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline2" } } */
! /* { dg-final { cleanup-tree-dump "einline2" } } */
--- 23,27 ----
}
}
! /* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline" } } */
! /* { dg-final { cleanup-tree-dump "einline" } } */
More information about the Gcc-patches
mailing list