value-prof.c (gimple_divmod_fixed_value): Work on SSA form.

2010-10-05  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 and leaf.
	(add_abnormal_goto_call_edges): Remove.
	(tree_gen_edge_profiler): Work on SSA form.
	(tree_gen_ic_profiler): Likewise.  Simplify.
	(do_tree_profiling): Update SSA form.
	(pass_tree_profile): Remove.
	(do_tree_profiling): Likewise.
	(gate_tree_profile_ipa): New function.
	(pass_ipa_tree_profile): New.
	(tree_profiling): Re-write as IPA pass.  Properly drop const/pure
	state of instrumented functions.
	* 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_tree_profile): Likewise.
	(pass_ipa_tree_profile): Declare.

	* gcc.dg/tree-prof/val-prof-1.c: Adjust.
	* gcc.dg/tree-prof/val-prof-2.c: Likewise.
	* gcc.dg/tree-prof/val-prof-3.c: Likewise.
	* gcc.dg/tree-prof/val-prof-4.c: Likewise.
	* gcc.dg/tree-prof/val-prof-5.c: Likewise.
	* gcc.dg/tree-prof/val-prof-7.c: Likewise.
	* gcc.dg/tree-prof/stringop-1.c: Likewise.
	* gcc.dg/tree-prof/stringop-2.c: Likewise.
	* gcc.dg/tree-prof/ic-misattribution-1.c: Likewise.
	* gcc.dg/tree-prof/indir-call-prof.c: Likewise.
	* gcc.dg/tree-prof/update-loopch.c: Likewise.
	* 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.
	* gcc.dg/profile-dir-1.c: Likewise.
	* gcc.dg/profile-dir-2.c: Likewise.
	* gcc.dg/profile-dir-3.c: Likewise.

From-SVN: r164986
This commit is contained in:
Richard Guenther 2010-10-05 10:42:24 +00:00 committed by Richard Biener
parent 65b1d8ea3e
commit 4d3814a514
30 changed files with 370 additions and 253 deletions

View File

@ -1,3 +1,30 @@
2010-10-05 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 and leaf.
(add_abnormal_goto_call_edges): Remove.
(tree_gen_edge_profiler): Work on SSA form.
(tree_gen_ic_profiler): Likewise. Simplify.
(do_tree_profiling): Update SSA form.
(pass_tree_profile): Remove.
(do_tree_profiling): Likewise.
(gate_tree_profile_ipa): New function.
(pass_ipa_tree_profile): New.
(tree_profiling): Re-write as IPA pass. Properly drop const/pure
state of instrumented functions.
* 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_tree_profile): Likewise.
(pass_ipa_tree_profile): Declare.
2010-10-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> 2010-10-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
Christian Borntraeger <Christian.Borntraeger@de.ibm.com> Christian Borntraeger <Christian.Borntraeger@de.ibm.com>

View File

@ -1841,36 +1841,6 @@ struct gimple_opt_pass pass_early_inline =
} }
}; };
/* 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 /* See if statement might disappear after inlining. We are not terribly
sophisficated, basically looking for simple abstraction penalty wrappers. */ sophisficated, basically looking for simple abstraction penalty wrappers. */

View File

@ -746,18 +746,10 @@ init_optimization_passes (void)
p = &all_small_ipa_passes; p = &all_small_ipa_passes;
NEXT_PASS (pass_ipa_free_lang_data); NEXT_PASS (pass_ipa_free_lang_data);
NEXT_PASS (pass_ipa_function_and_variable_visibility); 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); NEXT_PASS (pass_early_local_passes);
{ {
struct opt_pass **p = &pass_early_local_passes.pass.sub; struct opt_pass **p = &pass_early_local_passes.pass.sub;
NEXT_PASS (pass_fixup_cfg); NEXT_PASS (pass_fixup_cfg);
NEXT_PASS (pass_tree_profile);
NEXT_PASS (pass_init_datastructures); NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_expand_omp); NEXT_PASS (pass_expand_omp);
@ -802,6 +794,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_rebuild_cgraph_edges); NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_inline_parameters); NEXT_PASS (pass_inline_parameters);
} }
NEXT_PASS (pass_ipa_tree_profile);
NEXT_PASS (pass_ipa_increase_alignment); NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg); NEXT_PASS (pass_ipa_matrix_reorg);
NEXT_PASS (pass_ipa_lower_emutls); NEXT_PASS (pass_ipa_lower_emutls);

View File

@ -1,3 +1,29 @@
2010-10-05 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-prof/val-prof-1.c: Adjust.
* gcc.dg/tree-prof/val-prof-2.c: Likewise.
* gcc.dg/tree-prof/val-prof-3.c: Likewise.
* gcc.dg/tree-prof/val-prof-4.c: Likewise.
* gcc.dg/tree-prof/val-prof-5.c: Likewise.
* gcc.dg/tree-prof/val-prof-7.c: Likewise.
* gcc.dg/tree-prof/stringop-1.c: Likewise.
* gcc.dg/tree-prof/stringop-2.c: Likewise.
* gcc.dg/tree-prof/ic-misattribution-1.c: Likewise.
* gcc.dg/tree-prof/indir-call-prof.c: Likewise.
* gcc.dg/tree-prof/update-loopch.c: Likewise.
* 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.
* gcc.dg/profile-dir-1.c: Likewise.
* gcc.dg/profile-dir-2.c: Likewise.
* gcc.dg/profile-dir-3.c: Likewise.
2010-10-05 Richard Guenther <rguenther@suse.de> 2010-10-05 Richard Guenther <rguenther@suse.de>
PR middle-end/45877 PR middle-end/45877

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
struct A { struct A {
A () {} A () {}
@ -15,6 +15,7 @@ struct B : public A {
{ return 1; } { return 1; }
}; };
void * __attribute__((noinline,noclone)) wrap (void *p) { return p; }
int int
main (void) main (void)
{ {
@ -23,17 +24,16 @@ main (void)
A* p; A* p;
p = &a; p = (A *)wrap ((void *)&a);
p->AA (); p->AA ();
p = &b; p = (B *)wrap ((void *)&b);
p->AA (); p->AA ();
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA transformation on insn" "tree_profile_ipa" } } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized" } } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
class DocId { class DocId {
public: public:
DocId() { } DocId() { }
@ -31,6 +31,6 @@ int main(void)
baz.Bar(&baz, gid); baz.Bar(&baz, gid);
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline2"} } */ /* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline" } } */
/* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline2"} } */ /* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline" } } */
/* { dg-final-use { cleanup-tree-dump "einline2" } } */ /* { dg-final-use { cleanup-tree-dump "einline2" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */ /* { dg-add-options bind_pic_locally } */
namespace std { namespace std {
@ -31,6 +31,6 @@ int main(int argc, char **argv)
foreach (argv, argv + argc, inline_me_too); 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\\(" 1 "einline"} } */
/* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */ /* { dg-add-options bind_pic_locally } */
namespace std { namespace std {
@ -31,6 +31,6 @@ int main(int argc, char **argv)
foreach (argv, argv + argc, inline_me_too); 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\\(" 1 "einline"} } */
/* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */ /* { dg-add-options bind_pic_locally } */
#include <algorithm> #include <algorithm>
@ -26,6 +26,6 @@ int main(int argc, char **argv)
std::for_each (argv, argv + argc, inline_me_too); 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\\(" 1 "einline"} } */
/* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining void inline_me_too\\(" 1 "einline"} } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -1,6 +1,6 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O -fprofile-generate=. -fdump-tree-tree_profile" } */ /* { dg-options "-O -fprofile-generate=. -fdump-ipa-tree_profile_ipa" } */
/* { dg-final { scan-tree-dump " ./profile-dir-1.gcda" "tree_profile" } } */ /* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "tree_profile_ipa" } } */
int int
main(void) main(void)
@ -8,4 +8,4 @@ main(void)
return 0; return 0;
} }
/* { dg-final { cleanup-tree-dump "tree_profile" } } */ /* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,6 +1,6 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O -fprofile-generate -fdump-tree-tree_profile" } */ /* { dg-options "-O -fprofile-generate -fdump-ipa-tree_profile_ipa" } */
/* { dg-final { scan-tree-dump "/profile-dir-2.gcda" "tree_profile" } } */ /* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "tree_profile_ipa" } } */
int int
main(void) main(void)
@ -8,4 +8,4 @@ main(void)
return 0; return 0;
} }
/* { dg-final { cleanup-tree-dump "tree_profile" } } */ /* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,6 +1,6 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-tree-tree_profile" } */ /* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-tree_profile_ipa" } */
/* { dg-final { scan-tree-dump " ./profile-dir-3.gcda" "tree_profile" } } */ /* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "tree_profile_ipa" } } */
int int
main(void) main(void)
@ -8,4 +8,4 @@ main(void)
return 0; return 0;
} }
/* { dg-final { cleanup-tree-dump "tree_profile" } } */ /* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-ipa-tree_profile_ipa" } */
/* { dg-additional-sources "ic-misattribution-1a.c" } */ /* { dg-additional-sources "ic-misattribution-1a.c" } */
extern void other_caller (void); extern void other_caller (void);
@ -15,5 +15,5 @@ caller(void (*func) (void))
func (); func ();
} }
/* { dg-final-use { scan-tree-dump "hist->count 1 hist->all 1" "tree_profile" } } */ /* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "tree_profile_ipa" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
static int a1 (void) static int a1 (void)
{ {
@ -37,9 +37,7 @@ main (void)
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Indirect call -> direct call.* a1 transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1 transformation on insn" "tree_profile_ipa"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
int a[1000]; int a[1000];
int b[1000]; int b[1000];
int size=1; int size=1;
@ -13,10 +13,10 @@ main()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Single value 4 stringop" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
/* Really this ought to simplify into assignment, but we are not there yet. */ /* Really this ought to simplify into assignment, but we are not there yet. */
/* a[0] = b[0] is what we fold the resulting memcpy into. */ /* a[0] = b[0] is what we fold the resulting memcpy into. */
/* { dg-final-use { scan-tree-dump " = MEM.*&b" "optimized"} } */ /* { dg-final-use { scan-tree-dump " = MEM.*&b" "optimized"} } */
/* { dg-final-use { scan-tree-dump "MEM.*&a\\\] = " "optimized"} } */ /* { dg-final-use { scan-tree-dump "MEM.*&a\\\] = " "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
int a[1000]; int a[1000];
int b[1000]; int b[1000];
int size=1; int size=1;
@ -13,8 +13,8 @@ main()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Single value 4 stringop" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Single value 4 stringop" "tree_profile_ipa"} } */
/* The versioned memset of size 4 should be optimized to an assignment. */ /* The versioned memset of size 4 should be optimized to an assignment. */
/* { dg-final-use { scan-tree-dump "a\\\[0\\\] = 168430090" "optimized"} } */ /* { dg-final-use { scan-tree-dump "a\\\[0\\\] = 168430090" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,8 +1,8 @@
/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */ /* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
main () volatile int a, b, c;
int main ()
{ {
int i; int i;
int a, b, c;
for (i = 0; i < 1000; i++) for (i = 0; i < 1000; i++)
{ {
if (i % 17) if (i % 17)
@ -14,5 +14,5 @@ main ()
return 0; return 0;
} }
/* Superblock formation should produce two copies of the increment of c */ /* 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-generate { scan-tree-dump-times "c =" 2 "tracer" } } */
/* { dg-final-use { cleanup-tree-dump "tracer" } } */ /* { dg-final-use { cleanup-tree-dump "tracer" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-tree_profile-blocks -fdump-tree-optimized-blocks" } */ /* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
int max = 33333; int max = 33333;
int a[8]; int a[8];
int int
@ -14,8 +14,8 @@ main ()
/* Loop header copying will peel away the initial conditional, so the loop body /* Loop header copying will peel away the initial conditional, so the loop body
is once reached directly from entry point of function, rest via loopback is once reached directly from entry point of function, rest via loopback
edge. */ edge. */
/* { dg-final-use { scan-tree-dump "count:33333" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "count:33333" "tree_profile_ipa"} } */
/* { dg-final-use { scan-tree-dump "count:33332" "optimized"} } */ /* { dg-final-use { scan-tree-dump "count:33332" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
int a[1000]; int a[1000];
int b = 256; int b = 256;
int c = 257; int c = 257;
@ -15,8 +15,8 @@ main ()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Div.mod by constant n=257 transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Div.mod by constant n_\[0-9\]*=257 transformation on insn" "tree_profile_ipa"} } */
/* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* != 257\\)" "optimized"} } */ /* { 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 { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
unsigned int a[1000]; unsigned int a[1000];
unsigned int b = 256; unsigned int b = 256;
unsigned int c = 1024; unsigned int c = 1024;
@ -23,10 +23,10 @@ main ()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Mod power of 2 transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Mod power of 2 transformation on insn" "tree_profile_ipa" } } */
/* This is part of code checking that n is power of 2, so we are sure that the transformation /* This is part of code checking that n is power of 2, so we are sure that the transformation
didn't get optimized out. */ didn't get optimized out. */
/* { dg-final-use { scan-tree-dump "n_\[0-9\]* \\+ 0xffff" "optimized"} } */ /* { dg-final-use { scan-tree-dump "n_\[0-9\]* \\+ 0xffff" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
unsigned int a[1000]; unsigned int a[1000];
unsigned int b = 257; unsigned int b = 257;
unsigned int c = 1023; unsigned int c = 1023;
@ -23,10 +23,10 @@ main ()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Mod subtract transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
/* This is part of code checking that n is greater than the divisor so we are sure that it /* This is part of code checking that n is greater than the divisor so we are sure that it
didn't get optimized out. */ didn't get optimized out. */
/* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */ /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
unsigned int a[1000]; unsigned int a[1000];
unsigned int b = 999; unsigned int b = 999;
unsigned int c = 1002; unsigned int c = 1002;
@ -23,10 +23,10 @@ main ()
} }
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Mod subtract transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Mod subtract transformation on insn" "tree_profile_ipa" } } */
/* This is part of code checking that n is greater than the divisor so we are sure that it /* This is part of code checking that n is greater than the divisor so we are sure that it
didn't get optimized out. */ didn't get optimized out. */
/* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */ /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-tree_profile" } */ /* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
int a[1000]; int a[1000];
int b=997; int b=997;
main() main()
@ -11,7 +11,7 @@ main()
a[i]/=b; a[i]/=b;
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Div.mod by constant b.*=997 transformation on insn" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Div.mod by constant b.*=997 transformation on insn" "tree_profile_ipa" } } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
/* { dg-final-use { cleanup-tree-dump "optimized" } } */ /* { dg-final-use { cleanup-tree-dump "optimized" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -1,4 +1,4 @@
/* { dg-options "-O2 -fdump-tree-tree_profile -mtune=core2" } */ /* { dg-options "-O2 -fdump-ipa-tree_profile_ipa -mtune=core2" } */
/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */ /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
#include <strings.h> #include <strings.h>
@ -22,5 +22,5 @@ int main() {
return 0; return 0;
} }
/* { dg-final-use { scan-tree-dump "Single value 8 stringop transformation on bzero" "tree_profile"} } */ /* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "tree_profile_ipa" } } */
/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */ /* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */

View File

@ -18,5 +18,5 @@ baz (void)
return 6; return 6;
} }
/* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline"} } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */ /* { dg-add-options bind_pic_locally } */
extern void inlined (); extern void inlined ();
@ -27,6 +27,6 @@ inline_me_too (void)
{ {
inlined(); inlined();
} }
/* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline"} } */
/* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline2"} } */ /* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline"} } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-einline2" } */ /* { dg-options "-O2 -fdump-tree-einline" } */
/* { dg-add-options bind_pic_locally } */ /* { dg-add-options bind_pic_locally } */
extern int rand(void); extern int rand(void);
@ -23,5 +23,5 @@ int main()
} }
} }
/* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline2" } } */ /* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline" } } */
/* { dg-final { cleanup-tree-dump "einline2" } } */ /* { dg-final { cleanup-tree-dump "einline" } } */

View File

@ -353,7 +353,6 @@ extern struct gimple_opt_pass pass_lower_eh;
extern struct gimple_opt_pass pass_lower_eh_dispatch; extern struct gimple_opt_pass pass_lower_eh_dispatch;
extern struct gimple_opt_pass pass_lower_resx; extern struct gimple_opt_pass pass_lower_resx;
extern struct gimple_opt_pass pass_build_cfg; extern struct gimple_opt_pass pass_build_cfg;
extern struct gimple_opt_pass pass_tree_profile;
extern struct gimple_opt_pass pass_early_tree_profile; extern struct gimple_opt_pass pass_early_tree_profile;
extern struct gimple_opt_pass pass_referenced_vars; extern struct gimple_opt_pass pass_referenced_vars;
extern struct gimple_opt_pass pass_cleanup_eh; extern struct gimple_opt_pass pass_cleanup_eh;
@ -447,7 +446,7 @@ extern struct gimple_opt_pass pass_split_functions;
/* IPA Passes */ /* IPA Passes */
extern struct simple_ipa_opt_pass pass_ipa_lower_emutls; 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_function_and_variable_visibility;
extern struct simple_ipa_opt_pass pass_ipa_early_inline; extern struct simple_ipa_opt_pass pass_ipa_tree_profile;
extern struct simple_ipa_opt_pass pass_early_local_passes; extern struct simple_ipa_opt_pass pass_early_local_passes;

View File

@ -120,6 +120,10 @@ tree_init_edge_profiler (void)
tree_interval_profiler_fn tree_interval_profiler_fn
= build_fn_decl ("__gcov_interval_profiler", = build_fn_decl ("__gcov_interval_profiler",
interval_profiler_fn_type); interval_profiler_fn_type);
TREE_NOTHROW (tree_interval_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_interval_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_interval_profiler_fn));
/* void (*) (gcov_type *, gcov_type) */ /* void (*) (gcov_type *, gcov_type) */
pow2_profiler_fn_type pow2_profiler_fn_type
@ -128,6 +132,10 @@ tree_init_edge_profiler (void)
NULL_TREE); NULL_TREE);
tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
pow2_profiler_fn_type); pow2_profiler_fn_type);
TREE_NOTHROW (tree_pow2_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_pow2_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_pow2_profiler_fn));
/* void (*) (gcov_type *, gcov_type) */ /* void (*) (gcov_type *, gcov_type) */
one_value_profiler_fn_type one_value_profiler_fn_type
@ -137,6 +145,10 @@ tree_init_edge_profiler (void)
tree_one_value_profiler_fn tree_one_value_profiler_fn
= build_fn_decl ("__gcov_one_value_profiler", = build_fn_decl ("__gcov_one_value_profiler",
one_value_profiler_fn_type); one_value_profiler_fn_type);
TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_one_value_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_one_value_profiler_fn));
tree_init_ic_make_global_vars (); tree_init_ic_make_global_vars ();
@ -149,6 +161,11 @@ tree_init_edge_profiler (void)
tree_indirect_call_profiler_fn tree_indirect_call_profiler_fn
= build_fn_decl ("__gcov_indirect_call_profiler", = build_fn_decl ("__gcov_indirect_call_profiler",
ic_profiler_fn_type); ic_profiler_fn_type);
TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
/* void (*) (gcov_type *, gcov_type) */ /* void (*) (gcov_type *, gcov_type) */
average_profiler_fn_type average_profiler_fn_type
= build_function_type_list (void_type_node, = build_function_type_list (void_type_node,
@ -156,9 +173,18 @@ tree_init_edge_profiler (void)
tree_average_profiler_fn tree_average_profiler_fn
= build_fn_decl ("__gcov_average_profiler", = build_fn_decl ("__gcov_average_profiler",
average_profiler_fn_type); average_profiler_fn_type);
TREE_NOTHROW (tree_average_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_average_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_average_profiler_fn));
tree_ior_profiler_fn tree_ior_profiler_fn
= build_fn_decl ("__gcov_ior_profiler", = build_fn_decl ("__gcov_ior_profiler",
average_profiler_fn_type); average_profiler_fn_type);
TREE_NOTHROW (tree_ior_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_ior_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_ior_profiler_fn));
/* LTO streamer needs assembler names. Because we create these decls /* LTO streamer needs assembler names. Because we create these decls
late, we need to initialize them by hand. */ late, we need to initialize them by hand. */
DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
@ -170,20 +196,6 @@ tree_init_edge_profiler (void)
} }
} }
/* New call was added, make goto call edges if neccesary. */
static void
add_abnormal_goto_call_edges (gimple_stmt_iterator gsi)
{
gimple stmt = gsi_stmt (gsi);
if (!stmt_can_make_abnormal_goto (stmt))
return;
if (!gsi_end_p (gsi))
split_block (gimple_bb (stmt), stmt);
make_abnormal_goto_edges (gimple_bb (stmt), true);
}
/* Output instructions as GIMPLE trees to increment the edge /* Output instructions as GIMPLE trees to increment the edge
execution count, and insert them on E. We rely on execution count, and insert them on E. We rely on
gsi_insert_on_edge to preserve the order. */ gsi_insert_on_edge to preserve the order. */
@ -197,13 +209,15 @@ tree_gen_edge_profiler (int edgeno, edge e)
/* We share one temporary variable declaration per function. This /* We share one temporary variable declaration per function. This
gets re-set in tree_profiling. */ gets re-set in tree_profiling. */
if (gcov_type_tmp_var == NULL_TREE) if (gcov_type_tmp_var == NULL_TREE)
gcov_type_tmp_var = create_tmp_var (gcov_type_node, "PROF_edge_counter"); gcov_type_tmp_var = create_tmp_reg (gcov_type_node, "PROF_edge_counter");
ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno); ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
one = build_int_cst (gcov_type_node, 1); one = build_int_cst (gcov_type_node, 1);
stmt1 = gimple_build_assign (gcov_type_tmp_var, ref); 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, stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
gcov_type_tmp_var, one); gimple_assign_lhs (stmt1), one);
stmt3 = gimple_build_assign (unshare_expr (ref), gcov_type_tmp_var); 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, stmt1);
gsi_insert_on_edge (e, stmt2); gsi_insert_on_edge (e, stmt2);
gsi_insert_on_edge (e, stmt3); gsi_insert_on_edge (e, stmt3);
@ -246,7 +260,6 @@ tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
call = gimple_build_call (tree_interval_profiler_fn, 4, call = gimple_build_call (tree_interval_profiler_fn, 4,
ref_ptr, val, start, steps); ref_ptr, val, start, steps);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, call, GSI_NEW_STMT);
add_abnormal_goto_call_edges (gsi);
} }
/* Output instructions as GIMPLE trees to increment the power of two histogram /* Output instructions as GIMPLE trees to increment the power of two histogram
@ -267,7 +280,6 @@ tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
val = prepare_instrumented_value (&gsi, value); val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val); call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, call, GSI_NEW_STMT);
add_abnormal_goto_call_edges (gsi);
} }
/* Output instructions as GIMPLE trees for code to find the most common value. /* Output instructions as GIMPLE trees for code to find the most common value.
@ -288,7 +300,6 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
val = prepare_instrumented_value (&gsi, value); val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val); call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, call, GSI_NEW_STMT);
add_abnormal_goto_call_edges (gsi);
} }
@ -316,10 +327,11 @@ tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
__gcov_indirect_call_callee = (void *) indirect call argument; __gcov_indirect_call_callee = (void *) indirect call argument;
*/ */
tmp1 = create_tmp_var (ptr_void, "PROF"); tmp1 = create_tmp_reg (ptr_void, "PROF");
stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value)); stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
stmt3 = gimple_build_assign (ic_void_ptr_var, tmp1); 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, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@ -337,51 +349,38 @@ tree_gen_ic_func_profiler (void)
{ {
struct cgraph_node * c_node = cgraph_node (current_function_decl); struct cgraph_node * c_node = cgraph_node (current_function_decl);
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
edge e;
basic_block bb;
edge_iterator ei;
gimple stmt1, stmt2; gimple stmt1, stmt2;
tree tree_uid, cur_func, counter_ptr, ptr_var; tree tree_uid, cur_func, counter_ptr, ptr_var, void0;
if (cgraph_only_called_directly_p (c_node)) if (cgraph_only_called_directly_p (c_node))
return; return;
tree_init_edge_profiler (); tree_init_edge_profiler ();
FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
{
tree void0;
bb = split_edge (e);
gsi = gsi_start_bb (bb);
cur_func = force_gimple_operand_gsi (&gsi, cur_func = force_gimple_operand_gsi (&gsi,
build_addr (current_function_decl, build_addr (current_function_decl,
current_function_decl), current_function_decl),
true, NULL_TREE, true, NULL_TREE,
true, GSI_NEW_STMT); true, GSI_SAME_STMT);
counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var, counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
true, NULL_TREE, false, true, NULL_TREE, true,
GSI_NEW_STMT); GSI_SAME_STMT);
ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
true, NULL_TREE, false, true, NULL_TREE, true,
GSI_NEW_STMT); GSI_SAME_STMT);
tree_uid = build_int_cst (gcov_type_node, c_node->pid); tree_uid = build_int_cst (gcov_type_node, c_node->pid);
stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4, stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
counter_ptr, tree_uid, cur_func, ptr_var); counter_ptr, tree_uid, cur_func, ptr_var);
gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gcc_assert (EDGE_COUNT (bb->succs) == 1);
bb = split_edge (EDGE_I (bb->succs, 0));
add_abnormal_goto_call_edges (gsi);
gsi = gsi_start_bb (bb);
/* Set __gcov_indirect_call_callee to 0, /* Set __gcov_indirect_call_callee to 0,
so that calls from other modules won't get misattributed so that calls from other modules won't get misattributed
to the last caller of the current callee. */ to the last caller of the current callee. */
void0 = build_int_cst (build_pointer_type (void_type_node), 0); void0 = build_int_cst (build_pointer_type (void_type_node), 0);
stmt2 = gimple_build_assign (ic_void_ptr_var, void0); stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
}
} }
/* Output instructions as GIMPLE trees for code to find the most common value /* Output instructions as GIMPLE trees for code to find the most common value
@ -420,7 +419,6 @@ tree_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
val = prepare_instrumented_value (&gsi, value); val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val); call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, call, GSI_NEW_STMT);
add_abnormal_goto_call_edges (gsi);
} }
/* Output instructions as GIMPLE trees to increment the ior histogram /* Output instructions as GIMPLE trees to increment the ior histogram
@ -441,39 +439,39 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
val = prepare_instrumented_value (&gsi, value); val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val); call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, call, GSI_NEW_STMT);
add_abnormal_goto_call_edges (gsi);
} }
/* Return 1 if tree-based profiling is in effect, else 0. /* Profile all functions in the callgraph. */
If it is, set up hooks for tree-based profiling.
Gate for pass_tree_profile. */
static bool
do_tree_profiling (void)
{
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
tree_register_profile_hooks ();
gimple_register_value_prof_hooks ();
return true;
}
return false;
}
static unsigned int static unsigned int
tree_profiling (void) tree_profiling (void)
{ {
struct cgraph_node *node;
/* Don't profile functions produced at destruction time, particularly /* Don't profile functions produced at destruction time, particularly
the gcov datastructure initializer. Don't profile if it has been the gcov datastructure initializer. Don't profile if it has been
already instrumented either (when OpenMP expansion creates already instrumented either (when OpenMP expansion creates
child function from already instrumented body). */ child function from already instrumented body). */
if (cgraph_state == CGRAPH_STATE_FINISHED if (cgraph_state == CGRAPH_STATE_FINISHED)
|| cfun->after_tree_profile)
return 0; return 0;
tree_register_profile_hooks ();
gimple_register_value_prof_hooks ();
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->analyzed
|| !gimple_has_body_p (node->decl)
|| !(!node->clone_of || node->decl != node->clone_of->decl))
continue;
/* Don't profile functions produced for builtin stuff. */ /* Don't profile functions produced for builtin stuff. */
if (DECL_SOURCE_LOCATION (current_function_decl) == BUILTINS_LOCATION) if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
return 0; || DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
continue;
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
/* Re-set global shared temporary variable for edge-counters. */ /* Re-set global shared temporary variable for edge-counters. */
gcov_type_tmp_var = NULL_TREE; gcov_type_tmp_var = NULL_TREE;
@ -488,34 +486,106 @@ tree_profiling (void)
&& flag_profile_values && flag_profile_values
&& flag_value_profile_transformations) && flag_value_profile_transformations)
value_profile_transformations (); value_profile_transformations ();
/* The above could hose dominator info. Currently there is /* The above could hose dominator info. Currently there is
none coming in, this is a safety valve. It should be none coming in, this is a safety valve. It should be
easy to adjust it, if and when there is some. */ easy to adjust it, if and when there is some. */
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
current_function_decl = NULL;
pop_cfun ();
}
/* Drop pure/const flags from instrumented functions. */
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->analyzed
|| !gimple_has_body_p (node->decl)
|| !(!node->clone_of || node->decl != node->clone_of->decl))
continue;
/* Don't profile functions produced for builtin stuff. */
if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
|| DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
continue;
cgraph_set_readonly_flag (node, false);
cgraph_set_pure_flag (node, false);
cgraph_set_looping_const_or_pure_flag (node, false);
}
/* Update call statements and rebuild the cgraph. */
for (node = cgraph_nodes; node; node = node->next)
{
basic_block bb;
if (!node->analyzed
|| !gimple_has_body_p (node->decl)
|| !(!node->clone_of || node->decl != node->clone_of->decl))
continue;
/* Don't profile functions produced for builtin stuff. */
if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION
|| DECL_STRUCT_FUNCTION (node->decl)->after_tree_profile)
continue;
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
FOR_EACH_BB (bb)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
if (is_gimple_call (stmt))
update_stmt (stmt);
}
}
cfun->after_tree_profile = 1; cfun->after_tree_profile = 1;
update_ssa (TODO_update_ssa);
rebuild_cgraph_edges ();
current_function_decl = NULL;
pop_cfun ();
}
return 0; return 0;
} }
struct gimple_opt_pass pass_tree_profile = /* 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 =
{ {
{ {
GIMPLE_PASS, SIMPLE_IPA_PASS,
"tree_profile", /* name */ "tree_profile_ipa", /* name */
do_tree_profiling, /* gate */ gate_tree_profile_ipa, /* gate */
tree_profiling, /* execute */ tree_profiling, /* execute */
NULL, /* sub */ NULL, /* sub */
NULL, /* next */ NULL, /* next */
0, /* static_pass_number */ 0, /* static_pass_number */
TV_BRANCH_PROB, /* tv_id */ TV_IPA_PROFILE, /* tv_id */
PROP_gimple_leh | PROP_cfg, /* properties_required */ 0, /* properties_required */
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 0, /* todo_flags_start */
TODO_verify_stmts | TODO_dump_func /* todo_flags_finish */ TODO_dump_func /* todo_flags_finish */
} }
}; };
struct profile_hooks tree_profile_hooks = struct profile_hooks tree_profile_hooks =
{ {
tree_init_edge_profiler, /* init_edge_profiler */ tree_init_edge_profiler, /* init_edge_profiler */

View File

@ -558,7 +558,7 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gcov_type all) gcov_type all)
{ {
gimple stmt1, stmt2, stmt3; gimple stmt1, stmt2, stmt3;
tree tmp1, tmp2, tmpv; tree tmp0, tmp1, tmp2, tmpv;
gimple bb1end, bb2end, bb3end; gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4; basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2; tree optype, op1, op2;
@ -576,19 +576,22 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
bb = gimple_bb (stmt); bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt); gsi = gsi_for_stmt (stmt);
tmpv = create_tmp_var (optype, "PROF"); tmpv = create_tmp_reg (optype, "PROF");
tmp1 = create_tmp_var (optype, "PROF"); tmp0 = make_ssa_name (tmpv, NULL);
stmt1 = gimple_build_assign (tmpv, fold_convert (optype, value)); 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); stmt2 = gimple_build_assign (tmp1, op2);
stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE); 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, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3; bb1end = stmt3;
tmp2 = create_tmp_var (optype, "PROF"); tmp2 = make_rename_temp (optype, "PROF");
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2, stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
op1, tmpv); op1, tmp0);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1; bb2end = stmt1;
@ -711,7 +714,7 @@ static tree
gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all) gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
{ {
gimple stmt1, stmt2, stmt3, stmt4; gimple stmt1, stmt2, stmt3, stmt4;
tree tmp2, tmp3; tree tmp2, tmp3, tmpv;
gimple bb1end, bb2end, bb3end; gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4; basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2; tree optype, op1, op2;
@ -729,12 +732,15 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
bb = gimple_bb (stmt); bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt); gsi = gsi_for_stmt (stmt);
result = create_tmp_var (optype, "PROF"); result = make_rename_temp (optype, "PROF");
tmp2 = create_tmp_var (optype, "PROF"); tmpv = create_tmp_var (optype, "PROF");
tmp3 = 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, stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2,
build_int_cst (optype, -1)); build_int_cst (optype, -1));
SSA_NAME_DEF_STMT (tmp2) = stmt2;
stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2); 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), stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0),
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@ -881,10 +887,11 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts,
bb = gimple_bb (stmt); bb = gimple_bb (stmt);
gsi = gsi_for_stmt (stmt); gsi = gsi_for_stmt (stmt);
result = create_tmp_var (optype, "PROF"); result = make_rename_temp (optype, "PROF");
tmp1 = create_tmp_var (optype, "PROF"); tmp1 = make_ssa_name (create_tmp_var (optype, "PROF"), NULL);
stmt1 = gimple_build_assign (result, op1); stmt1 = gimple_build_assign (result, op1);
stmt2 = gimple_build_assign (tmp1, op2); stmt2 = gimple_build_assign (tmp1, op2);
SSA_NAME_DEF_STMT (tmp1) = stmt2;
stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE); stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@ -1092,7 +1099,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
int prob, gcov_type count, gcov_type all) int prob, gcov_type count, gcov_type all)
{ {
gimple dcall_stmt, load_stmt, cond_stmt; gimple dcall_stmt, load_stmt, cond_stmt;
tree tmp1, tmpv, tmp; 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;
tree optype = build_pointer_type (void_type_node); 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, e_ij;
@ -1102,20 +1109,26 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
cond_bb = gimple_bb (icall_stmt); cond_bb = gimple_bb (icall_stmt);
gsi = gsi_for_stmt (icall_stmt); gsi = gsi_for_stmt (icall_stmt);
tmpv = create_tmp_var (optype, "PROF"); tmpv = create_tmp_reg (optype, "PROF");
tmp1 = create_tmp_var (optype, "PROF"); tmp0 = make_ssa_name (tmpv, NULL);
tmp1 = make_ssa_name (tmpv, NULL);
tmp = unshare_expr (gimple_call_fn (icall_stmt)); tmp = unshare_expr (gimple_call_fn (icall_stmt));
load_stmt = gimple_build_assign (tmpv, tmp); load_stmt = gimple_build_assign (tmp0, tmp);
SSA_NAME_DEF_STMT (tmp0) = load_stmt;
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
tmp = fold_convert (optype, build_addr (direct_call->decl, tmp = fold_convert (optype, build_addr (direct_call->decl,
current_function_decl)); current_function_decl));
load_stmt = gimple_build_assign (tmp1, tmp); load_stmt = gimple_build_assign (tmp1, tmp);
SSA_NAME_DEF_STMT (tmp1) = load_stmt;
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE); cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT); 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); dcall_stmt = gimple_copy (icall_stmt);
gimple_call_set_fndecl (dcall_stmt, direct_call->decl); gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
@ -1151,6 +1164,21 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
e_ij->probability = REG_BR_PROB_BASE; e_ij->probability = REG_BR_PROB_BASE;
e_ij->count = all - count; e_ij->count = all - count;
/* Insert PHI node for the call result if necessary. */
if (gimple_call_lhs (icall_stmt)
&& TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME)
{
tree result = gimple_call_lhs (icall_stmt);
gimple phi = create_phi_node (result, join_bb);
SSA_NAME_DEF_STMT (result) = phi;
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);
gimple_call_set_lhs (dcall_stmt,
make_ssa_name (SSA_NAME_VAR (result), dcall_stmt));
add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION);
}
/* Fix eh edges */ /* Fix eh edges */
lp_nr = lookup_stmt_eh_lp (icall_stmt); lp_nr = lookup_stmt_eh_lp (icall_stmt);
if (lp_nr != 0) if (lp_nr != 0)
@ -1289,7 +1317,7 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob,
gcov_type count, gcov_type all) gcov_type count, gcov_type all)
{ {
gimple tmp_stmt, cond_stmt, icall_stmt; gimple tmp_stmt, cond_stmt, icall_stmt;
tree tmp1, tmpv, vcall_size, optype; tree tmp0, tmp1, tmpv, vcall_size, optype;
basic_block cond_bb, icall_bb, vcall_bb, join_bb; basic_block cond_bb, icall_bb, vcall_bb, join_bb;
edge e_ci, e_cv, e_iv, e_ij, e_vj; edge e_ci, e_cv, e_iv, e_ij, e_vj;
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
@ -1307,16 +1335,22 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob,
optype = TREE_TYPE (vcall_size); optype = TREE_TYPE (vcall_size);
tmpv = create_tmp_var (optype, "PROF"); tmpv = create_tmp_var (optype, "PROF");
tmp1 = create_tmp_var (optype, "PROF"); tmp0 = make_ssa_name (tmpv, NULL);
tmp_stmt = gimple_build_assign (tmpv, fold_convert (optype, icall_size)); 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); gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
tmp_stmt = gimple_build_assign (tmp1, vcall_size); tmp_stmt = gimple_build_assign (tmp1, vcall_size);
SSA_NAME_DEF_STMT (tmp1) = tmp_stmt;
gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE); cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT); 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); icall_stmt = gimple_copy (vcall_stmt);
gimple_call_set_arg (icall_stmt, size_arg, icall_size); gimple_call_set_arg (icall_stmt, size_arg, icall_size);
gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT); gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT);