2010-10-05 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 2010 10:42:24 +0000 (10:42 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 2010 10:42:24 +0000 (10:42 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164986 138bc75d-0d04-0410-961f-82ee72b054a4

30 files changed:
gcc/ChangeLog
gcc/ipa-inline.c
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-prof/indir-call-prof.C
gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
gcc/testsuite/g++.dg/tree-ssa/inline-1.C
gcc/testsuite/g++.dg/tree-ssa/inline-2.C
gcc/testsuite/g++.dg/tree-ssa/inline-3.C
gcc/testsuite/gcc.dg/profile-dir-1.c
gcc/testsuite/gcc.dg/profile-dir-2.c
gcc/testsuite/gcc.dg/profile-dir-3.c
gcc/testsuite/gcc.dg/tree-prof/ic-misattribution-1.c
gcc/testsuite/gcc.dg/tree-prof/indir-call-prof.c
gcc/testsuite/gcc.dg/tree-prof/stringop-1.c
gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
gcc/testsuite/gcc.dg/tree-prof/tracer-1.c
gcc/testsuite/gcc.dg/tree-prof/update-loopch.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-1.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-3.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-4.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-5.c
gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
gcc/testsuite/gcc.dg/tree-ssa/20080530.c
gcc/testsuite/gcc.dg/tree-ssa/inline-3.c
gcc/testsuite/gcc.dg/tree-ssa/inline-4.c
gcc/tree-pass.h
gcc/tree-profile.c
gcc/value-prof.c

index 00c90b9..7304d1e 100644 (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>
             Christian Borntraeger  <Christian.Borntraeger@de.ibm.com>
 
index ca3823b..8d9db0b 100644 (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
    sophisficated, basically looking for simple abstraction penalty wrappers.  */
index 24bae5f..1308ce9 100644 (file)
@@ -746,18 +746,10 @@ init_optimization_passes (void)
   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);
 
@@ -802,6 +794,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_rebuild_cgraph_edges);
       NEXT_PASS (pass_inline_parameters);
     }
+  NEXT_PASS (pass_ipa_tree_profile);
   NEXT_PASS (pass_ipa_increase_alignment);
   NEXT_PASS (pass_ipa_matrix_reorg);
   NEXT_PASS (pass_ipa_lower_emutls);
index cfa09f7..3471b51 100644 (file)
@@ -1,5 +1,31 @@
 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>
+
        PR middle-end/45877
        * g++.dg/torture/pr45877.C: New testcase.
 
index 98ab302..80b4186 100644 (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 {
   A () {}
@@ -15,6 +15,7 @@ struct B : public A {
   { return 1; }
 };
 
+void * __attribute__((noinline,noclone)) wrap (void *p) { return p; }
 int
 main (void)
 {
@@ -23,17 +24,16 @@ main (void)
   
   A* p;
 
-  p = &a;
+  p = (A *)wrap ((void *)&a);
   p->AA ();
 
-  p = &b;
+  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" } } */                                                                                           
-
+/* { 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 { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index 352e176..0049a5d 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 class DocId {
  public:
  DocId() { }
@@ -31,6 +31,6 @@ int main(void)
  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 { 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 fdd72fb..95b7d06 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 /* { dg-add-options bind_pic_locally } */
 
 namespace std {
@@ -31,6 +31,6 @@ int main(int argc, char **argv)
   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" } } */
+/* { 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 3d7c380..656cba0 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 /* { dg-add-options bind_pic_locally } */
 
 namespace std {
@@ -31,6 +31,6 @@ int main(int argc, char **argv)
   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" } } */
+/* { 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 01a10a2..57d175c 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 /* { dg-add-options bind_pic_locally } */
 
 #include <algorithm>
@@ -26,6 +26,6 @@ int main(int argc, char **argv)
   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" } } */
+/* { 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 2bfaf20..62f3130 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate=. -fdump-tree-tree_profile" } */
-/* { dg-final { scan-tree-dump " ./profile-dir-1.gcda" "tree_profile" } } */
+/* { dg-options "-O -fprofile-generate=. -fdump-ipa-tree_profile_ipa" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-1.gcda" "tree_profile_ipa" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
index 29bb969..7bad03c 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fdump-tree-tree_profile" } */
-/* { dg-final { scan-tree-dump "/profile-dir-2.gcda" "tree_profile" } } */
+/* { dg-options "-O -fprofile-generate -fdump-ipa-tree_profile_ipa" } */
+/* { dg-final { scan-ipa-dump "/profile-dir-2.gcda" "tree_profile_ipa" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
index 0686640..a462223 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-tree-tree_profile" } */
-/* { dg-final { scan-tree-dump " ./profile-dir-3.gcda" "tree_profile" } } */
+/* { dg-options "-O -fprofile-generate -fprofile-dir=. -fdump-ipa-tree_profile_ipa" } */
+/* { dg-final { scan-ipa-dump " ./profile-dir-3.gcda" "tree_profile_ipa" } } */
 
 int
 main(void)
@@ -8,4 +8,4 @@ main(void)
   return 0;
 }
 
-/* { dg-final { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final { cleanup-ipa-dump "tree_profile_ipa" } } */
index c36dd8d..94a5953 100644 (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" } */
 
 extern void other_caller (void);
@@ -15,5 +15,5 @@ caller(void (*func) (void))
   func ();
 }
 
-/* { dg-final-use { scan-tree-dump "hist->count 1 hist->all 1" "tree_profile" } } */
-/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final-use { scan-ipa-dump "hist->count 1 hist->all 1" "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index 101b972..8f7508b 100644 (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)
 {
@@ -37,9 +37,7 @@ main (void)
   return 0;
 }
 
-/* { dg-final-use { scan-tree-dump "Indirect call -> direct call.* a1 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" } } */
-                                                                                           
-
+/* { 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 { cleanup-tree-dump "optimized" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index 0f477b2..fe200c8 100644 (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 b[1000];
 int size=1;
@@ -13,10 +13,10 @@ main()
     }
    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.  */
 /* 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.*&a\\\] = " "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" } } */
index e6b4999..aa951c9 100644 (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 b[1000];
 int size=1;
@@ -13,8 +13,8 @@ main()
     }
    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.  */
 /* { dg-final-use { scan-tree-dump "a\\\[0\\\] = 168430090" "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" } } */
index 7654a53..385a1a5 100644 (file)
@@ -1,8 +1,8 @@
 /* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
-main ()
+volatile int a, b, c;
+int main ()
 {
   int i;
-  int a, b, c;
   for (i = 0; i < 1000; i++)
     {
       if (i % 17)
@@ -14,5 +14,5 @@ main ()
   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-generate { scan-tree-dump-times "c =" 2 "tracer" } } */
 /* { dg-final-use { cleanup-tree-dump "tracer" } } */
index b132e5a..6b7dbd4 100644 (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 a[8];
 int
@@ -14,8 +14,8 @@ main ()
 /* 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
    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-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" } } */
index 4d9cb1b..181b3d1 100644 (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 b = 256;
 int c = 257;
@@ -15,8 +15,8 @@ main ()
     }
   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-not "Invalid sum" "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" } } */
index 30a92c0..f96255d 100644 (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 b = 256;
 unsigned int c = 1024;
@@ -23,10 +23,10 @@ main ()
     }
   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
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "n_\[0-9\]* \\+ 0xffff" "optimized"} } */
 /* { 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" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index ad32a44..802dbf0 100644 (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 b = 257;
 unsigned int c = 1023;
@@ -23,10 +23,10 @@ main ()
     }
   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
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { 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" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index fdc2b0c..d4d3085 100644 (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 b = 999;
 unsigned int c = 1002;
@@ -23,10 +23,10 @@ main ()
     }
   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
    didn't get optimized out.  */
 /* { dg-final-use { scan-tree-dump "if \\(n_\[0-9\]* \\>" "optimized"} } */
 /* { 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" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index 095fb06..581f4d5 100644 (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 b=997;
 main()
@@ -11,7 +11,7 @@ main()
                        a[i]/=b;
        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 { cleanup-tree-dump "optimized" } } */
-/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index bb79c19..664b620 100644 (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-*-* } } { "*" } { "" } } */
 
 #include <strings.h>
@@ -22,5 +22,5 @@ int main() {
   return 0;
 }
 
-/* { dg-final-use { scan-tree-dump "Single value 8 stringop transformation on bzero" "tree_profile"} } */
-/* { dg-final-use { cleanup-tree-dump "tree_profile" } } */
+/* { dg-final-use { scan-ipa-dump "Single value 8 stringop transformation on bzero" "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
index 6da7cb8..bf222fe 100644 (file)
@@ -18,5 +18,5 @@ baz (void)
   return 6;
 }
 
-/* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline2"} } */
-/* { dg-final { cleanup-tree-dump "einline2" } } */
+/* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline"} } */
+/* { dg-final { cleanup-tree-dump "einline" } } */
index 511cc9e..ff140ed 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 /* { dg-add-options bind_pic_locally } */
 
 extern void inlined ();
@@ -27,6 +27,6 @@ inline_me_too (void)
 {
   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" } } */
+/* { 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 b89ce97..1e700ef 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-einline2" } */
+/* { dg-options "-O2 -fdump-tree-einline" } */
 /* { dg-add-options bind_pic_locally } */
 
 extern int rand(void);
@@ -23,5 +23,5 @@ int main()
     }
 }
 
-/* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline2" } } */
-/* { dg-final { cleanup-tree-dump "einline2" } } */
+/* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline" } } */
+/* { dg-final { cleanup-tree-dump "einline" } } */
index a16301c..a87a770 100644 (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_resx;
 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_referenced_vars;
 extern struct gimple_opt_pass pass_cleanup_eh;
@@ -447,7 +446,7 @@ extern struct gimple_opt_pass pass_split_functions;
 /* 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_ipa_tree_profile;
 
 extern struct simple_ipa_opt_pass pass_early_local_passes;
 
index 50ce013..5b7c12b 100644 (file)
@@ -120,6 +120,10 @@ tree_init_edge_profiler (void)
       tree_interval_profiler_fn
              = build_fn_decl ("__gcov_interval_profiler",
                                     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)  */
       pow2_profiler_fn_type
@@ -128,6 +132,10 @@ tree_init_edge_profiler (void)
                                          NULL_TREE);
       tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler",
                                                   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)  */
       one_value_profiler_fn_type
@@ -137,6 +145,10 @@ tree_init_edge_profiler (void)
       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;
+      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 ();
 
@@ -149,6 +161,11 @@ tree_init_edge_profiler (void)
       tree_indirect_call_profiler_fn
              = build_fn_decl ("__gcov_indirect_call_profiler",
                                     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)  */
       average_profiler_fn_type
              = build_function_type_list (void_type_node,
@@ -156,9 +173,18 @@ tree_init_edge_profiler (void)
       tree_average_profiler_fn
              = build_fn_decl ("__gcov_average_profiler",
                                     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
              = build_fn_decl ("__gcov_ior_profiler",
                                     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
          late, we need to initialize them by hand.  */
       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
    execution count, and insert them on E.  We rely on
    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
      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");
+    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,
-                                       gcov_type_tmp_var, one);
-  stmt3 = gimple_build_assign (unshare_expr (ref), 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);
@@ -246,7 +260,6 @@ tree_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base)
   call = gimple_build_call (tree_interval_profiler_fn, 4,
                            ref_ptr, val, start, steps);
   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
@@ -267,7 +280,6 @@ tree_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
   val = prepare_instrumented_value (&gsi, value);
   call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
   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.
@@ -288,7 +300,6 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
   val = prepare_instrumented_value (&gsi, value);
   call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
   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;
    */
 
-  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);
   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, stmt2, GSI_SAME_STMT);
@@ -337,51 +349,38 @@ tree_gen_ic_func_profiler (void)
 {
   struct cgraph_node * c_node = cgraph_node (current_function_decl);
   gimple_stmt_iterator gsi;
-  edge e;
-  basic_block bb;
-  edge_iterator ei;
   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))
     return;
 
   tree_init_edge_profiler ();
 
-  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
-    {
-      tree void0;
-
-      bb = split_edge (e);
-      gsi = gsi_start_bb (bb);
-
-      cur_func = force_gimple_operand_gsi (&gsi,
-                                          build_addr (current_function_decl,
-                                                      current_function_decl),
-                                          true, NULL_TREE,
-                                          true, GSI_NEW_STMT);
-      counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
-                                             true, NULL_TREE, false,
-                                             GSI_NEW_STMT);
-      ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
-                                         true, NULL_TREE, false,
-                                         GSI_NEW_STMT);
-      tree_uid = build_int_cst (gcov_type_node, c_node->pid);
-      stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
-                                counter_ptr, tree_uid, cur_func, ptr_var);
-      gsi_insert_after (&gsi, stmt1, GSI_NEW_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,
-         so that calls from other modules won't get misattributed
-        to the last caller of the current callee. */
-      void0 = build_int_cst (build_pointer_type (void_type_node), 0);
-      stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
-      gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
-    }
+  gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+
+  cur_func = force_gimple_operand_gsi (&gsi,
+                                      build_addr (current_function_decl,
+                                                  current_function_decl),
+                                      true, NULL_TREE,
+                                      true, GSI_SAME_STMT);
+  counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
+                                         true, NULL_TREE, true,
+                                         GSI_SAME_STMT);
+  ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
+                                     true, NULL_TREE, true,
+                                     GSI_SAME_STMT);
+  tree_uid = build_int_cst (gcov_type_node, c_node->pid);
+  stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
+                            counter_ptr, tree_uid, cur_func, ptr_var);
+  gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
+
+  /* Set __gcov_indirect_call_callee to 0,
+     so that calls from other modules won't get misattributed
+     to the last caller of the current callee. */
+  void0 = build_int_cst (build_pointer_type (void_type_node), 0);
+  stmt2 = gimple_build_assign (ic_void_ptr_var, void0);
+  gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
 }
 
 /* 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);
   call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
   gsi_insert_before (&gsi, call, GSI_NEW_STMT);
-  add_abnormal_goto_call_edges (gsi);
 }
 
 /* Output instructions as GIMPLE trees to increment the ior histogram
@@ -441,81 +439,153 @@ tree_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
   val = prepare_instrumented_value (&gsi, value);
   call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
   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.
-   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;
-}
+/* Profile all functions in the callgraph.  */
 
 static unsigned int
 tree_profiling (void)
 {
+  struct cgraph_node *node;
+
   /* 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
      child function from already instrumented body).  */
-  if (cgraph_state == CGRAPH_STATE_FINISHED
-      || cfun->after_tree_profile)
+  if (cgraph_state == CGRAPH_STATE_FINISHED)
     return 0;
 
-  /* Don't profile functions produced for builtin stuff.  */
-  if (DECL_SOURCE_LOCATION (current_function_decl) == BUILTINS_LOCATION)
-    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.  */
+      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;
+
+      /* Re-set global shared temporary variable for edge-counters.  */
+      gcov_type_tmp_var = NULL_TREE;
+
+      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);
+
+      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;
+      update_ssa (TODO_update_ssa);
+
+      rebuild_cgraph_edges ();
+
+      current_function_decl = NULL;
+      pop_cfun ();
+    }
 
-  /* Re-set global shared temporary variable for edge-counters.  */
-  gcov_type_tmp_var = NULL_TREE;
-
-  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 =
+/* 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,
-  "tree_profile",                      /* name */
-  do_tree_profiling,                   /* gate */
-  tree_profiling,                      /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  TV_BRANCH_PROB,                      /* tv_id */
-  PROP_gimple_leh | PROP_cfg,          /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  TODO_verify_stmts | TODO_dump_func   /* todo_flags_finish */
+  SIMPLE_IPA_PASS,
+  "tree_profile_ipa",                  /* name */
+  gate_tree_profile_ipa,               /* gate */
+  tree_profiling,                      /* 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 */
+  TODO_dump_func                       /* todo_flags_finish */
  }
 };
 
+
 struct profile_hooks tree_profile_hooks =
 {
   tree_init_edge_profiler,       /* init_edge_profiler */
index 84956cd..b0cc13b 100644 (file)
@@ -558,7 +558,7 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
                           gcov_type all)
 {
   gimple stmt1, stmt2, stmt3;
-  tree tmp1, tmp2, tmpv;
+  tree tmp0, tmp1, tmp2, tmpv;
   gimple bb1end, bb2end, bb3end;
   basic_block bb, bb2, bb3, bb4;
   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);
   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));
+  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);
-  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, stmt2, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
   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,
-                                       op1, tmpv);
+                                       op1, tmp0);
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
   bb2end = stmt1;
 
@@ -711,7 +714,7 @@ static tree
 gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
 {
   gimple stmt1, stmt2, stmt3, stmt4;
-  tree tmp2, tmp3;
+  tree tmp2, tmp3, tmpv;
   gimple bb1end, bb2end, bb3end;
   basic_block bb, bb2, bb3, bb4;
   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);
   gsi = gsi_for_stmt (stmt);
 
-  result = create_tmp_var (optype, "PROF");
-  tmp2 = create_tmp_var (optype, "PROF");
-  tmp3 = create_tmp_var (optype, "PROF");
+  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);
@@ -881,10 +887,11 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts,
   bb = gimple_bb (stmt);
   gsi = gsi_for_stmt (stmt);
 
-  result = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
+  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);
@@ -1092,7 +1099,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
           int prob, gcov_type count, gcov_type all)
 {
   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;
   tree optype = build_pointer_type (void_type_node);
   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);
   gsi = gsi_for_stmt (icall_stmt);
 
-  tmpv = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
+  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 (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);
 
   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, 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);
 
+  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);
@@ -1151,6 +1164,21 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
   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)
+      && 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 */
   lp_nr = lookup_stmt_eh_lp (icall_stmt);
   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)
 {
   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;
   edge e_ci, e_cv, e_iv, e_ij, e_vj;
   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);
 
   tmpv = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
-  tmp_stmt = gimple_build_assign (tmpv, fold_convert (optype, icall_size));
+  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, 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);
 
+  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);