diff mbox

[google] LIPO regression tests and bug fixes (issue4444076)

Message ID 20110428231831.0DC0A1B4093@aples.mtv.corp.google.com
State New
Headers show

Commit Message

Xinliang David Li April 28, 2011, 11:18 p.m. UTC
This patch added regression tests for LIPO in google/main and fixes a couple of bugs found
in app testing:

1) duplicate assembler labels in .s file
2) missing icall profling for static functions indirect called
3) assertion in type 'merging'
4) gcov-dump bug.

Bootstrap compiler, regression test, and SPEC06 LIPO build.

Will commit to google/main.

Thanks,

David

2011-04-28  David Li  <davidxl@google.com>

	* testsuite/gcc.dg/tree-prof/lipo/inliner-1.c	(revision 0): New test.
	* testsuite/gcc.dg/tree-prof/lipo/gdb_cmd	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/stringop-1.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/pr34999.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/stringop-2.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/update-loopch.c	(revision 0):
	* testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa	(revision 0):
	Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/lipo.exp	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/tracer-1.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/pr45354.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/pr47187.c	(revision 0): Ditto.
	* testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/partition1.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/partition2.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/partition3.C	(revision 0): Ditto.
	* testsuite/g++.dg/tree-prof/lipo/lipo.exp	(revision 0): Ditto.
	* final.c	(revision 173136) (profile_function): Use FUNC_LABEL_ID.
	* dwarf2out.c	(revision 173136) (dwarf2out_vms_end_prologue): Ditto.
	(dwarf2out_vms_begin_epilogue): Ditto.
	(dwarf2out_vms_debug_main_pointer): Ditto.
	* cgraphunit.c	(revision 173136) (cgraph_finalize_compilation_unit):
	Remove eq type alias set computation.
	* tree-profile.c	(revision 173136) (gimple_gen_ic_func_profiler):
	(gimple_gen_ic_func_topn_profiler): Do not skip any functions.
	(tree_profiling): Add type alias merging.
	* l-ipo.c	(revision 173136) (restore_post_parsing_states): Use
	max funcdef_no.
	(pop_module_scope): Use max funcdef_no.
	* gcov-dump.c	(revision 173136) (tag_function): Fix a bug in function
	read.


--
This patch is available for review at http://codereview.appspot.com/4444076

Comments

Rong Xu April 28, 2011, 11:32 p.m. UTC | #1
LGTM.

-Rong

On Thu, Apr 28, 2011 at 4:18 PM, David Li <davidxl@google.com> wrote:
> This patch added regression tests for LIPO in google/main and fixes a couple of bugs found
> in app testing:
>
> 1) duplicate assembler labels in .s file
> 2) missing icall profling for static functions indirect called
> 3) assertion in type 'merging'
> 4) gcov-dump bug.
>
> Bootstrap compiler, regression test, and SPEC06 LIPO build.
>
> Will commit to google/main.
>
> Thanks,
>
> David
>
> 2011-04-28  David Li  <davidxl@google.com>
>
>        * testsuite/gcc.dg/tree-prof/lipo/inliner-1.c   (revision 0): New test.
>        * testsuite/gcc.dg/tree-prof/lipo/gdb_cmd       (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c    (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/stringop-1.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/pr34999.c     (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/stringop-2.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/update-loopch.c       (revision 0):
>        * testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa       (revision 0):
>        Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c     (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c        (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/lipo.exp      (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/tracer-1.c    (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized      (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c     (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/pr45354.c     (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c  (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/pr47187.c     (revision 0): Ditto.
>        * testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c    (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C        (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C   (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C     (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/partition1.C  (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/partition2.C  (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/partition3.C  (revision 0): Ditto.
>        * testsuite/g++.dg/tree-prof/lipo/lipo.exp      (revision 0): Ditto.
>        * final.c       (revision 173136) (profile_function): Use FUNC_LABEL_ID.
>        * dwarf2out.c   (revision 173136) (dwarf2out_vms_end_prologue): Ditto.
>        (dwarf2out_vms_begin_epilogue): Ditto.
>        (dwarf2out_vms_debug_main_pointer): Ditto.
>        * cgraphunit.c  (revision 173136) (cgraph_finalize_compilation_unit):
>        Remove eq type alias set computation.
>        * tree-profile.c        (revision 173136) (gimple_gen_ic_func_profiler):
>        (gimple_gen_ic_func_topn_profiler): Do not skip any functions.
>        (tree_profiling): Add type alias merging.
>        * l-ipo.c       (revision 173136) (restore_post_parsing_states): Use
>        max funcdef_no.
>        (pop_module_scope): Use max funcdef_no.
>        * gcov-dump.c   (revision 173136) (tag_function): Fix a bug in function
>        read.
>
> Index: final.c
> ===================================================================
> --- final.c     (revision 173136)
> +++ final.c     (working copy)
> @@ -1623,7 +1623,7 @@ profile_function (FILE *file ATTRIBUTE_U
>       int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
>       switch_to_section (data_section);
>       ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
> -      targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
> +      targetm.asm_out.internal_label (file, "LP", FUNC_LABEL_ID (cfun));
>       assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
>     }
>
> @@ -1636,7 +1636,7 @@ profile_function (FILE *file ATTRIBUTE_U
>     ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
>  #endif
>
> -  FUNCTION_PROFILER (file, current_function_funcdef_no);
> +  FUNCTION_PROFILER (file, FUNC_LABEL_ID (cfun));
>
>  #ifdef ASM_OUTPUT_REG_PUSH
>   if (chain && REG_P (chain))
> Index: cgraphunit.c
> ===================================================================
> --- cgraphunit.c        (revision 173136)
> +++ cgraphunit.c        (working copy)
> @@ -1117,11 +1117,6 @@ cgraph_finalize_compilation_unit (void)
>   /* Gimplify and lower thunks.  */
>   cgraph_analyze_functions ();
>
> -  /* LIPO support  */
> -  /* Recognize equivalent types across modules and
> -     merge their alias sets.  */
> -  cgraph_unify_type_alias_sets ();
> -
>   /* Finally drive the pass manager.  */
>   cgraph_optimize ();
>
> Index: testsuite/gcc.dg/tree-prof/lipo/inliner-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/inliner-1.c (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/inliner-1.c (revision 0)
> @@ -0,0 +1,42 @@
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +int a;
> +int b[100];
> +void abort (void);
> +
> +inline void
> +cold_function ()
> +{
> +  int i;
> +  for (i = 0; i < 99; i++)
> +    if (b[i] / (b[i+1] + 1))
> +      abort ();
> +}
> +
> +inline void
> +hot_function ()
> +{
> +  int i;
> +  for (i = 0; i < 99; i++)
> +    if (b[i] / (b[i+1] + 1))
> +      abort ();
> +}
> +
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < 100; i++)
> +    {
> +      if (a)
> +        cold_function ();
> +      else
> +        hot_function ();
> +    }
> +  return 0;
> +}
> +
> +/* cold function should be inlined, while hot function should not.
> +   Look for "cold_function () [tail call];" call statement not for the
> +   declaration or other apperances of the string in dump.  */
> +/* { dg-final-use { scan-tree-dump "cold_function ..;" "optimized"} } */
> +/* { dg-final-use { scan-tree-dump-not "hot_function ..;" "optimized"} } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/gdb_cmd
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/gdb_cmd     (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/gdb_cmd     (revision 0)
> @@ -0,0 +1,5 @@
> +file /usr/local/google/davidxl/dev/gcc/gcc-gmain-native_64-linux/libexec/gcc/x86_64-linux/4.6.0-google-main/cc1
> +set args -quiet -v indir-call-prof.c -march=core2 -mcx16 -msahf --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=4096 -mtune=core2 -quiet -dumpbase indir-call-prof.c -auxbase indir-call-prof -g -O2 -version -fprofile-generate -fripa -fdump-ipa-tree_profile_ipa -fdump-tree-optimized-blocks -o /tmp/ccdBoNgb.s
> +b  main
> +b internal_error
> +b fancy_abort
> Index: testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c  (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c  (revision 0)
> @@ -0,0 +1,39 @@
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
> +
> +#include <string.h>
> +
> +#define SIZE 1000
> +int t0 = 0;
> +const char *t2[SIZE];
> +char buf[SIZE];
> +
> +void
> +foo (void)
> +{
> +  char *s = buf;
> +  t0 = 1;
> +
> +  for (;;)
> +    {
> +      if (*s == '\0')
> +       break;
> +      else
> +       {
> +         t2[t0] = s;
> +         t0++;
> +       }
> +      *s++ = '\0';
> +    }
> +  t2[t0] = NULL;
> +}
> +
> +
> +int
> +main ()
> +{
> +  strcpy (buf, "hello");
> +  foo ();
> +  return 0;
> +}
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/stringop-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/stringop-1.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/stringop-1.c        (revision 0)
> @@ -0,0 +1,22 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +int a[1000];
> +int b[1000];
> +int size=1;
> +int max=10000;
> +main()
> +{
> +  int i;
> +  for (i=0;i<max; i++)
> +    {
> +      __builtin_memcpy (a, b, size * sizeof (a[0]));
> +      asm("");
> +    }
> +   return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/pr34999.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/pr34999.c   (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/pr34999.c   (revision 0)
> @@ -0,0 +1,45 @@
> +/* Same test as built-in-setjmp.c.  Includes the case where
> +   the source block of a crossing fallthru edge ends with a call.  */
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
> +
> +extern int strcmp(const char *, const char *);
> +extern char *strcpy(char *, const char *);
> +extern void abort(void);
> +extern void exit(int);
> +
> +void *buf[20];
> +
> +void __attribute__((noinline))
> +sub2 (void)
> +{
> +  __builtin_longjmp (buf, 1);
> +}
> +
> +int
> +main ()
> +{
> +  char *p = (char *) __builtin_alloca (20);
> +
> +  strcpy (p, "test");
> +
> +  if (__builtin_setjmp (buf))
> +    {
> +      if (strcmp (p, "test") != 0)
> +       abort ();
> +
> +      exit (0);
> +    }
> +
> +  {
> +    int *q = (int *) __builtin_alloca (p[2] * sizeof (int));
> +    int i;
> +
> +    for (i = 0; i < p[2]; i++)
> +      q[i] = 0;
> +
> +    while (1)
> +      sub2 ();
> +  }
> +}
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/stringop-2.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/stringop-2.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/stringop-2.c        (revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +int a[1000];
> +int b[1000];
> +int size=1;
> +int max=10000;
> +main()
> +{
> +  int i;
> +  for (i=0;i<max; i++)
> +    {
> +      __builtin_memset (a, 10, size * sizeof (a[0]));
> +      asm("");
> +    }
> +   return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/update-loopch.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/update-loopch.c     (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/update-loopch.c     (revision 0)
> @@ -0,0 +1,21 @@
> +/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
> +int max = 33333;
> +int a[8];
> +int
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < max; i++)
> +    {
> +      a[i % 8]++;
> +    }
> +  return 0;
> +}
> +/* 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-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-ipa-dump "tree_profile_ipa" } } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa     (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa     (revision 0)
> @@ -0,0 +1,306 @@
> +Abnormal edge 3 to 1 put to tree
> +Abnormal edge 4 to 1 put to tree
> +Abnormal edge 7 to 1 put to tree
> +Normal edge 0 to 2 put to tree
> +Normal edge 2 to 6 put to tree
> +Normal edge 4 to 5 put to tree
> +8 basic blocks
> +10 edges
> +0 ignored edges
> +Stmt p.0_3 ();
> +Indirect call -- top N
> +Merged 1 profiles with maximal count 10.
> +
> +Read edge from 3 to 4, count:10
> +Read edge from 5 to 6, count:10
> +Read edge from 6 to 3, count:10
> +Read edge from 6 to 7, count:1
> +4 edge counts read
> +
> +8 basic blocks, 10 edges.
> +
> +Basic block 0 , next 2, loop_depth 0, count 1, freq 909, maybe hot.
> +Predecessors:
> +Successors:  2 [100.0%]  count:1 (fallthru,exec)
> +
> +Basic block 2 , prev 0, next 3, loop_depth 0, count 1, freq 909, maybe hot.
> +Predecessors:  ENTRY [100.0%]  count:1 (fallthru,exec)
> +Successors:  6 [100.0%]  count:1 (fallthru,exec)
> +
> +Basic block 3 , prev 2, next 4, loop_depth 1, count 10, freq 9091, maybe hot.
> +Predecessors:  6 [90.9%]  count:10 (true,exec)
> +Successors:  4 [100.0%]  count:10 (fallthru) EXIT (fake)
> +
> +Basic block 4 , prev 3, next 5, loop_depth 1, count 10, freq 9091, maybe hot.
> +Predecessors:  3 [100.0%]  count:10 (fallthru)
> +Successors:  5 [100.0%]  count:10 (fallthru) EXIT (fake)
> +
> +Basic block 5 , prev 4, next 6, loop_depth 1, count 10, freq 9091, maybe hot.
> +Predecessors:  4 [100.0%]  count:10 (fallthru)
> +Successors:  6 [100.0%]  count:10 (fallthru,dfs_back,exec)
> +
> +Basic block 6 , prev 5, next 7, loop_depth 1, count 11, freq 10000, maybe hot.
> +Predecessors:  2 [100.0%]  count:1 (fallthru,exec) 5 [100.0%]  count:10 (fallthru,dfs_back,exec)
> +Successors:  3 [90.9%]  count:10 (true,exec) 7 [9.1%]  count:1 (false,exec)
> +
> +Basic block 7 , prev 6, next 1, loop_depth 0, count 1, freq 909, maybe hot.
> +Predecessors:  6 [9.1%]  count:1 (false,exec)
> +Successors:  EXIT [100.0%]  count:1
> +
> +Basic block 1 , prev 7, loop_depth 0, count 1, freq 909, maybe hot.
> +Predecessors:  7 [100.0%]  count:1 4 (fake) 3 (fake)
> +Successors:
> +
> +Graph solving took 3 passes.
> +
> +1 branches
> +0% branches in range 0-5%
> +100% branches in range 5-10%
> +0% branches in range 10-15%
> +0% branches in range 15-20%
> +0% branches in range 20-25%
> +0% branches in range 25-30%
> +0% branches in range 30-35%
> +0% branches in range 35-40%
> +0% branches in range 40-45%
> +0% branches in range 45-50%
> +
> +
> +Trying transformations on stmt p.0_3 ();
> +Indirect call -- top N
> +Indirect call -> direct call p.0_3=> a1 (module_id:1, func_id:1)
> +Transformation on insn:
> +p.0_3 ();
> +==>
> +a1 ();
> +hist->count 9 hist->all 10
> +Analyzing function body size: main
> +  freq: 10001 size:  3 time: 12 setp (&p, i_1);
> +  freq: 10001 size:  1 time:  1 p.0_3 = p;
> +  freq: 10001 size:  0 time:  0 PROF.1_10 = p.0_3;
> +  freq: 10001 size:  0 time:  0 PROF.1_11 = (void *) a1;
> +  freq: 10001 size:  2 time:  2 if (PROF.1_11 == PROF.1_10)
> +  freq:  9001 size:  2 time: 11 a1 ();
> +  freq:  1000 size:  2 time: 11 p.0_3 ();
> +  freq: 10001 size:  1 time:  1 i_4 = i_1 + 1;
> +  freq: 11001 size:  2 time:  2 if (i_1 <= 9)
> +  freq:  1000 size:  1 time:  2 return 0;
> +Overall function body time: 294-2 size: 16-3
> +With function call overhead time: 294-13 size: 16-5
> +Abnormal edge 5 to 1 put to tree
> +Normal edge 0 to 2 put to tree
> +Normal edge 2 to 3 put to tree
> +Normal edge 2 to 4 put to tree
> +6 basic blocks
> +6 edges
> +0 ignored edges
> +Merged 1 profiles with maximal count 10.
> +
> +Read edge from 3 to 5, count:1
> +Read edge from 4 to 5, count:9
> +2 edge counts read
> +
> +6 basic blocks, 6 edges.
> +
> +Basic block 0 , next 2, loop_depth 0, count 10, freq 10000, maybe hot.
> +Predecessors:
> +Successors:  2 [100.0%]  count:10 (fallthru,exec)
> +
> +Basic block 2 , prev 0, next 3, loop_depth 0, count 10, freq 10000, maybe hot.
> +Predecessors:  ENTRY [100.0%]  count:10 (fallthru,exec)
> +Successors:  3 [39.0%]  count:1 (true,exec) 4 [61.0%]  count:9 (false,exec)
> +
> +Basic block 3 , prev 2, next 4, loop_depth 0, count 1, freq 3900, maybe hot.
> +Predecessors:  2 [39.0%]  count:1 (true,exec)
> +Successors:  5 [100.0%]  count:1 (fallthru,exec)
> +
> +Basic block 4 , prev 3, next 5, loop_depth 0, count 9, freq 6100, maybe hot.
> +Predecessors:  2 [61.0%]  count:9 (false,exec)
> +Successors:  5 [100.0%]  count:9 (fallthru,exec)
> +
> +Basic block 5 , prev 4, next 1, loop_depth 0, count 10, freq 10000, maybe hot.
> +Predecessors:  3 [100.0%]  count:1 (fallthru,exec) 4 [100.0%]  count:9 (fallthru,exec)
> +Successors:  EXIT [100.0%]  count:10
> +
> +Basic block 1 , prev 5, loop_depth 0, count 10, freq 10000, maybe hot.
> +Predecessors:  5 [100.0%]  count:10
> +Successors:
> +
> +Graph solving took 3 passes.
> +
> +1 branches
> +0% branches in range 0-5%
> +0% branches in range 5-10%
> +100% branches in range 10-15%
> +0% branches in range 15-20%
> +0% branches in range 20-25%
> +0% branches in range 25-30%
> +0% branches in range 30-35%
> +0% branches in range 35-40%
> +0% branches in range 40-45%
> +0% branches in range 45-50%
> +
> +
> +Abnormal edge 2 to 1 put to tree
> +3 basic blocks
> +2 edges
> +0 ignored edges
> +Merged 1 profiles with maximal count 10.
> +
> +Read edge from 0 to 2, count:1
> +1 edge counts read
> +
> +3 basic blocks, 2 edges.
> +
> +Basic block 0 , next 2, loop_depth 0, count 1, freq 10000, maybe hot.
> +Predecessors:
> +Successors:  2 [100.0%]  count:1 (fallthru,exec)
> +
> +Basic block 2 , prev 0, next 1, loop_depth 0, count 1, freq 10000, maybe hot.
> +Predecessors:  ENTRY [100.0%]  count:1 (fallthru,exec)
> +Successors:  EXIT [100.0%]  count:1
> +
> +Basic block 1 , prev 2, loop_depth 0, count 1, freq 10000, maybe hot.
> +Predecessors:  2 [100.0%]  count:1
> +Successors:
> +
> +Graph solving took 3 passes.
> +
> +0 branches
> +
> +
> +Abnormal edge 2 to 1 put to tree
> +3 basic blocks
> +2 edges
> +0 ignored edges
> +Merged 1 profiles with maximal count 10.
> +
> +Read edge from 0 to 2, count:9
> +1 edge counts read
> +
> +3 basic blocks, 2 edges.
> +
> +Basic block 0 , next 2, loop_depth 0, count 9, freq 10000, maybe hot.
> +Predecessors:
> +Successors:  2 [100.0%]  count:9 (fallthru,exec)
> +
> +Basic block 2 , prev 0, next 1, loop_depth 0, count 9, freq 10000, maybe hot.
> +Predecessors:  ENTRY [100.0%]  count:9 (fallthru,exec)
> +Successors:  EXIT [100.0%]  count:9
> +
> +Basic block 1 , prev 2, loop_depth 0, count 9, freq 10000, maybe hot.
> +Predecessors:  2 [100.0%]  count:9
> +Successors:
> +
> +Graph solving took 3 passes.
> +
> +0 branches
> +
> +
> +
> +
> +Symbols to be put in SSA form
> +
> +{ .MEM }
> +
> +
> +Incremental SSA update started at block: 0
> +
> +Number of blocks in CFG: 11
> +Number of blocks to update: 10 ( 91%)
> +
> +
> +
> +main ()
> +{
> +  void * PROF.1;
> +  int i;
> +  int (*<T352>) (void) p;
> +  int (*<T352>) (void) p.0;
> +
> +<bb 2>:
> +  goto <bb 6>;
> +
> +<bb 3>:
> +  setp (&p, i_1);
> +
> +<bb 4>:
> +  p.0_3 = p;
> +  PROF.1_10 = p.0_3;
> +  PROF.1_11 = (void *) a1;
> +  if (PROF.1_11 == PROF.1_10)
> +    goto <bb 8>;
> +  else
> +    goto <bb 9>;
> +
> +<bb 8>:
> +  a1 ();
> +  goto <bb 10>;
> +
> +<bb 9>:
> +  p.0_3 ();
> +
> +<bb 10>:
> +
> +<bb 5>:
> +  i_4 = i_1 + 1;
> +
> +<bb 6>:
> +  # i_1 = PHI <0(2), i_4(5)>
> +  if (i_1 <= 9)
> +    goto <bb 3>;
> +  else
> +    goto <bb 7>;
> +
> +<bb 7>:
> +  return 0;
> +
> +}
> +
> +
> +setp (int (*<T352>) (void) * pp, int i)
> +{
> +  int (*tp) (void) D.4264;
> +  int D.4263;
> +  int D.4262;
> +  int (*tp) (void) D.4260;
> +
> +<bb 2>:
> +  if (i_1(D) == 0)
> +    goto <bb 3>;
> +  else
> +    goto <bb 4>;
> +
> +<bb 3>:
> +  D.4260_2 = aa[i_1(D)];
> +  *pp_3(D) = D.4260_2;
> +  goto <bb 5>;
> +
> +<bb 4>:
> +  D.4262_4 = i_1(D) & 2;
> +  D.4263_5 = D.4262_4 + 1;
> +  D.4264_6 = aa[D.4263_5];
> +  *pp_3(D) = D.4264_6;
> +
> +<bb 5>:
> +  return;
> +
> +}
> +
> +
> +a2 ()
> +{
> +<bb 2>:
> +  return 0;
> +
> +}
> +
> +
> +a1 ()
> +{
> +<bb 2>:
> +  return 10;
> +
> +}
> +
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c       (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c       (revision 0)
> @@ -0,0 +1,19 @@
> +/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa" } */
> +/* { dg-additional-sources "ic-misattribution-1a.c" } */
> +
> +extern void other_caller (void);
> +
> +void
> +callee (void)
> +{
> +  return;
> +}
> +
> +void
> +caller(void (*func) (void))
> +{
> +  func ();
> +}
> +
> +/* { 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: testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c   (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c   (revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-options "-O2 -fdump-tree-tailc -fdump-tree-optimized" } */
> +__attribute__ ((noinline))
> +int factorial(int x)
> +{
> +   if (x == 1)
> +     return 1;
> +   else
> +     return x*factorial(--x);
> +}
> +int gbl;
> +int
> +main()
> +{
> +   gbl = factorial(100);
> +   return 0;
> +}
> +/* { dg-final-use { scan-tree-dump-not "Invalid sum" "tailc"} } */
> +/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
> +/* { dg-final-use { cleanup-tree-dump "tailc" } } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c      (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c      (revision 0)
> @@ -0,0 +1,22 @@
> +/* { dg-options "-DEMPTY" } */
> +/* This file is only needed in combination with ic-misattribution-1.c
> +   but there's no easy way to make this file ignored. */
> +extern void callee (void);
> +extern void caller (void (*func) (void));
> +
> +typedef void (*func_t) (void);
> +func_t func;
> +
> +int
> +main ()
> +{
> +#ifdef EMPTY
> +#else
> +  func = callee;
> +  caller (callee);
> +  func ();
> +#endif
> +  return 0;
> +}
> +
> +/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/lipo.exp
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/lipo.exp    (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/lipo.exp    (revision 0)
> @@ -0,0 +1,54 @@
> +# Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
> +# Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with GCC; see the file COPYING3.  If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +# Test the functionality of programs compiled with profile-directed block
> +# ordering using -fprofile-generate followed by -fbranch-use.
> +
> +load_lib target-supports.exp
> +
> +# Some targets don't support tree profiling.
> +if { ![check_profiling_available ""] } {
> +    return
> +}
> +
> +# The procedures in profopt.exp need these parameters.
> +set tool gcc
> +set prof_ext "gcda"
> +
> +# Override the list defined in profopt.exp.
> +set PROFOPT_OPTIONS [list {}]
> +
> +if $tracelevel then {
> +    strace $tracelevel
> +}
> +
> +# Load support procs.
> +load_lib profopt.exp
> +
> +# These are globals used by profopt-execute.  The first is options
> +# needed to generate profile data, the second is options to use the
> +# profile data.
> +set profile_option "-fprofile-generate -fripa -D_PROFILE_GENERATE"
> +set feedback_option "-fprofile-use -fripa -D_PROFILE_USE"
> +
> +foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
> +    # If we're only testing specific files and this isn't one of them, skip it.
> +    if ![runtest_file_p $runtests $src] then {
> +        continue
> +    }
> +    profopt-execute $src
> +}
> Index: testsuite/gcc.dg/tree-prof/lipo/tracer-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/tracer-1.c  (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/tracer-1.c  (revision 0)
> @@ -0,0 +1,18 @@
> +/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
> +volatile int a, b, c;
> +int main ()
> +{
> +  int i;
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i % 17)
> +       a++;
> +      else
> +       b++;
> +      c++;
> +    }
> +  return 0;
> +}
> +/* Superblock formation should produce two copies of the increment of c */
> +/* { dg-final-generate { scan-tree-dump-times "c =" 2 "tracer" } } */
> +/* { dg-final-use { cleanup-tree-dump "tracer" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized    (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized    (revision 0)
> @@ -0,0 +1,229 @@
> +
> +;; Function a1 (a1)[1:1] (unlikely executed)
> +
> +a1 ()
> +{
> +  # BLOCK 2 freq:10000
> +  # PRED: ENTRY [100.0%]  count:9 (fallthru,exec)
> +  return 10;
> +  # SUCC: EXIT [100.0%]
> +
> +}
> +
> +
> +
> +;; Function a2 (a2)[1:2]
> +
> +a2 ()
> +{
> +  # BLOCK 2 freq:10000 count:1
> +  # PRED: ENTRY [100.0%]  count:1 (fallthru,exec)
> +  return 0;
> +  # SUCC: EXIT [100.0%]  count:1
> +
> +}
> +
> +
> +
> +;; Function setp (setp)[1:3]
> +
> +Merging blocks 3 and 5
> +Merging blocks 4 and 6
> +setp (int (*<T352>) (void) * pp, int i)
> +{
> +  int (*tp) (void) D.4264;
> +  int D.4263;
> +  int D.4262;
> +
> +  # BLOCK 2 freq:10000 count:10
> +  # PRED: ENTRY [100.0%]  count:10 (fallthru,exec)
> +  if (i_1(D) == 0)
> +    goto <bb 3>;
> +  else
> +    goto <bb 4>;
> +  # SUCC: 3 [10.0%]  count:1 (true,exec) 4 [90.0%]  count:9 (false,exec)
> +
> +  # BLOCK 3 freq:1000 count:1
> +  # PRED: 2 [10.0%]  count:1 (true,exec)
> +  *pp_3(D) = a2;
> +  return;
> +  # SUCC: EXIT [100.0%]  count:1
> +
> +  # BLOCK 4 freq:9000 count:9
> +  # PRED: 2 [90.0%]  count:9 (false,exec)
> +  D.4262_4 = i_1(D) & 2;
> +  D.4263_5 = D.4262_4 + 1;
> +  D.4264_6 = aa[D.4263_5];
> +  *pp_3(D) = D.4264_6;
> +  return;
> +  # SUCC: EXIT [100.0%]  count:9
> +
> +}
> +
> +
> +
> +;; Function main (main)[1:4] (executed once)
> +
> +main ()
> +{
> +  int (*<T352>) (void) p;
> +  int (*<T352>) (void) p.0;
> +
> +  # BLOCK 2 freq:909 count:1
> +  # PRED: ENTRY [100.0%]  count:1 (fallthru,exec)
> +  setp (&p, 0);
> +  p.0_18 = p;
> +  if (p.0_18 == a1)
> +    goto <bb 4>;
> +  else
> +    goto <bb 3>;
> +  # SUCC: 4 [90.0%]  count:1 (true,exec) 3 [10.0%]  (false,exec)
> +
> +  # BLOCK 3 freq:91
> +  # PRED: 2 [10.0%]  (false,exec)
> +  p.0_18 ();
> +  # SUCC: 4 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 4 freq:909 count:1
> +  # PRED: 2 [90.0%]  count:1 (true,exec) 3 [100.0%]  (fallthru,exec)
> +  setp (&p, 1);
> +  p.0_27 = p;
> +  if (p.0_27 == a1)
> +    goto <bb 6>;
> +  else
> +    goto <bb 5>;
> +  # SUCC: 6 [90.0%]  count:1 (true,exec) 5 [10.0%]  (false,exec)
> +
> +  # BLOCK 5 freq:91
> +  # PRED: 4 [10.0%]  (false,exec)
> +  p.0_27 ();
> +  # SUCC: 6 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 6 freq:909 count:1
> +  # PRED: 4 [90.0%]  count:1 (true,exec) 5 [100.0%]  (fallthru,exec)
> +  setp (&p, 2);
> +  p.0_36 = p;
> +  if (p.0_36 == a1)
> +    goto <bb 8>;
> +  else
> +    goto <bb 7>;
> +  # SUCC: 8 [90.0%]  count:1 (true,exec) 7 [10.0%]  (false,exec)
> +
> +  # BLOCK 7 freq:91
> +  # PRED: 6 [10.0%]  (false,exec)
> +  p.0_36 ();
> +  # SUCC: 8 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 8 freq:909 count:1
> +  # PRED: 6 [90.0%]  count:1 (true,exec) 7 [100.0%]  (fallthru,exec)
> +  setp (&p, 3);
> +  p.0_45 = p;
> +  if (p.0_45 == a1)
> +    goto <bb 10>;
> +  else
> +    goto <bb 9>;
> +  # SUCC: 10 [90.0%]  count:1 (true,exec) 9 [10.0%]  (false,exec)
> +
> +  # BLOCK 9 freq:91
> +  # PRED: 8 [10.0%]  (false,exec)
> +  p.0_45 ();
> +  # SUCC: 10 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 10 freq:909 count:1
> +  # PRED: 8 [90.0%]  count:1 (true,exec) 9 [100.0%]  (fallthru,exec)
> +  setp (&p, 4);
> +  p.0_54 = p;
> +  if (p.0_54 == a1)
> +    goto <bb 12>;
> +  else
> +    goto <bb 11>;
> +  # SUCC: 12 [90.0%]  count:1 (true,exec) 11 [10.0%]  (false,exec)
> +
> +  # BLOCK 11 freq:91
> +  # PRED: 10 [10.0%]  (false,exec)
> +  p.0_54 ();
> +  # SUCC: 12 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 12 freq:909 count:1
> +  # PRED: 10 [90.0%]  count:1 (true,exec) 11 [100.0%]  (fallthru,exec)
> +  setp (&p, 5);
> +  p.0_63 = p;
> +  if (p.0_63 == a1)
> +    goto <bb 14>;
> +  else
> +    goto <bb 13>;
> +  # SUCC: 14 [90.0%]  count:1 (true,exec) 13 [10.0%]  (false,exec)
> +
> +  # BLOCK 13 freq:91
> +  # PRED: 12 [10.0%]  (false,exec)
> +  p.0_63 ();
> +  # SUCC: 14 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 14 freq:909 count:1
> +  # PRED: 12 [90.0%]  count:1 (true,exec) 13 [100.0%]  (fallthru,exec)
> +  setp (&p, 6);
> +  p.0_72 = p;
> +  if (p.0_72 == a1)
> +    goto <bb 16>;
> +  else
> +    goto <bb 15>;
> +  # SUCC: 16 [90.0%]  count:1 (true,exec) 15 [10.0%]  (false,exec)
> +
> +  # BLOCK 15 freq:91
> +  # PRED: 14 [10.0%]  (false,exec)
> +  p.0_72 ();
> +  # SUCC: 16 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 16 freq:909 count:1
> +  # PRED: 14 [90.0%]  count:1 (true,exec) 15 [100.0%]  (fallthru,exec)
> +  setp (&p, 7);
> +  p.0_81 = p;
> +  if (p.0_81 == a1)
> +    goto <bb 18>;
> +  else
> +    goto <bb 17>;
> +  # SUCC: 18 [90.0%]  count:1 (true,exec) 17 [10.0%]  (false,exec)
> +
> +  # BLOCK 17 freq:91
> +  # PRED: 16 [10.0%]  (false,exec)
> +  p.0_81 ();
> +  # SUCC: 18 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 18 freq:909 count:1
> +  # PRED: 16 [90.0%]  count:1 (true,exec) 17 [100.0%]  (fallthru,exec)
> +  setp (&p, 8);
> +  p.0_90 = p;
> +  if (p.0_90 == a1)
> +    goto <bb 20>;
> +  else
> +    goto <bb 19>;
> +  # SUCC: 20 [90.0%]  count:1 (true,exec) 19 [10.0%]  (false,exec)
> +
> +  # BLOCK 19 freq:91
> +  # PRED: 18 [10.0%]  (false,exec)
> +  p.0_90 ();
> +  # SUCC: 20 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 20 freq:909 count:1
> +  # PRED: 18 [90.0%]  count:1 (true,exec) 19 [100.0%]  (fallthru,exec)
> +  setp (&p, 9);
> +  p.0_3 = p;
> +  if (p.0_3 == a1)
> +    goto <bb 22>;
> +  else
> +    goto <bb 21>;
> +  # SUCC: 22 [90.0%]  count:1 (true,exec) 21 [10.0%]  (false,exec)
> +
> +  # BLOCK 21 freq:91
> +  # PRED: 20 [10.0%]  (false,exec)
> +  p.0_3 ();
> +  # SUCC: 22 [100.0%]  (fallthru,exec)
> +
> +  # BLOCK 22 freq:909 count:1
> +  # PRED: 21 [100.0%]  (fallthru,exec) 20 [90.0%]  count:1 (true,exec)
> +  return 0;
> +  # SUCC: EXIT [100.0%]  count:1
> +
> +}
> +
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c   (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c   (revision 0)
> @@ -0,0 +1,43 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +
> +static int a1 (void)
> +{
> +    return 10;
> +}
> +
> +static int a2 (void)
> +{
> +    return 0;
> +}
> +
> +typedef int (*tp) (void);
> +
> +static tp aa [] = {a2, a1, a1, a1, a1};
> +
> +__attribute__((noinline)) void setp (int (**pp) (void), int i)
> +{
> +  if (!i)
> +    *pp = aa [i];
> +  else
> +    *pp = aa [(i & 2) + 1];
> +}
> +
> +int
> +main (void)
> +{
> +  int (*p) (void);
> +  int  i;
> +
> +  for (i = 0; i < 10; i ++)
> +    {
> +       setp (&p, i);
> +       p ();
> +    }
> +
> +  return 0;
> +}
> +
> +/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1" "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: testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c        (revision 0)
> @@ -0,0 +1,22 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +int a[1000];
> +int b = 256;
> +int c = 257;
> +main ()
> +{
> +  int i;
> +  int n;
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i % 17)
> +       n = c;
> +      else n = b;
> +      a[i] /= n;
> +    }
> +  return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c        (revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-options "-O2 -Wno-coverage-mismatch" } */
> +
> +int __attribute__((noinline)) bar (void)
> +{
> +}
> +
> +int foo (int i)
> +{
> +#ifdef _PROFILE_USE
> +  if (i)
> +    bar ();
> +#endif
> +  return 0;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +  foo (argc);
> +  return 0;
> +}
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c        (revision 0)
> @@ -0,0 +1,32 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +unsigned int a[1000];
> +unsigned int b = 256;
> +unsigned int c = 1024;
> +unsigned int d = 17;
> +main ()
> +{
> +  int i;
> +  unsigned int n;
> +  for (i = 0; i < 1000; i++)
> +    {
> +           a[i]=100*i;
> +    }
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i % 2)
> +       n = b;
> +      else if (i % 3)
> +       n = c;
> +      else
> +       n = d;
> +      a[i] %= n;
> +    }
> +  return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/pr45354.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/pr45354.c   (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/pr45354.c   (revision 0)
> @@ -0,0 +1,43 @@
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling" { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
> +
> +extern void abort (void);
> +
> +int ifelse_val2;
> +
> +int __attribute__((noinline))
> +test_ifelse2 (int i)
> +{
> +  int result = 0;
> +  if (!i)                              /* count(6) */
> +    result = 1;                                /* count(1) */
> +  if (i == 1)                          /* count(6) */
> +    result = 1024;
> +  if (i == 2)                          /* count(6) */
> +    result = 2;                                /* count(3) */
> +  if (i == 3)                          /* count(6) */
> +    return 8;                          /* count(2) */
> +  if (i == 4)                          /* count(4) */
> +    return 2048;
> +  return result;                       /* count(4) */
> +}
> +
> +void __attribute__((noinline))
> +call_ifelse ()
> +{
> +  ifelse_val2 += test_ifelse2 (0);
> +  ifelse_val2 += test_ifelse2 (2);
> +  ifelse_val2 += test_ifelse2 (2);
> +  ifelse_val2 += test_ifelse2 (2);
> +  ifelse_val2 += test_ifelse2 (3);
> +  ifelse_val2 += test_ifelse2 (3);
> +}
> +
> +int
> +main()
> +{
> +  call_ifelse ();
> +  if (ifelse_val2 != 23)
> +    abort ();
> +  return 0;
> +}
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c        (revision 0)
> @@ -0,0 +1,32 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +unsigned int a[1000];
> +unsigned int b = 257;
> +unsigned int c = 1023;
> +unsigned int d = 19;
> +main ()
> +{
> +  int i;
> +  unsigned int n;
> +  for (i = 0; i < 1000; i++)
> +    {
> +           a[i]=18;
> +    }
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i % 2)
> +       n = b;
> +      else if (i % 3)
> +       n = c;
> +      else
> +       n = d;
> +      a[i] %= n;
> +    }
> +  return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c        (revision 0)
> @@ -0,0 +1,32 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +unsigned int a[1000];
> +unsigned int b = 999;
> +unsigned int c = 1002;
> +unsigned int d = 1003;
> +main ()
> +{
> +  int i;
> +  unsigned int n;
> +  for (i = 0; i < 1000; i++)
> +    {
> +           a[i]=1000+i;
> +    }
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i % 2)
> +       n = b;
> +      else if (i % 3)
> +       n = c;
> +      else
> +       n = d;
> +      a[i] %= n;
> +    }
> +  return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c        (revision 0)
> @@ -0,0 +1,17 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +int a[1000];
> +int b=997;
> +main()
> +{
> +       int i;
> +       for (i = 0; i < 1000; i++)
> +               if (a[i])
> +                       a[i]/=b;
> +               else
> +                       a[i]/=b;
> +       return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c        (revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +char a[1000];
> +char b[1000];
> +int size=1000;
> +__attribute__ ((noinline))
> +t(int size)
> +{
> +  __builtin_memcpy(a,b,size);
> +}
> +int
> +main()
> +{
> +  int i;
> +  for (i=0; i < size; i++)
> +    t(i);
> +  return 0;
> +}
> +/* { dg-final-use { scan-tree-dump "Average value sum:499500" "optimized"} } */
> +/* { dg-final-use { scan-tree-dump "IOR value" "optimized"} } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c        (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c        (revision 0)
> @@ -0,0 +1,26 @@
> +/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa -mtune=core2" } */
> +/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
> +
> +#include <strings.h>
> +
> +int foo(int len)
> +{
> +  char array[1000];
> +  bzero(array, len);
> +  return 0;
> +}
> +
> +int main() {
> +  int i;
> +  for (i = 0; i < 1000; i++)
> +    {
> +      if (i > 990)
> +       foo(16);
> +      else
> +       foo(8);
> +    }
> +  return 0;
> +}
> +
> +/* { 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: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.gcda.imports
> ===================================================================
> Index: testsuite/gcc.dg/tree-prof/lipo/pr47187.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/pr47187.c   (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/pr47187.c   (revision 0)
> @@ -0,0 +1,23 @@
> +/* PR bootstrap/47187 */
> +/* { dg-options "-O2" } */
> +
> +char buf[64];
> +char buf2[64];
> +
> +void *
> +foo (char *p, long size)
> +{
> +  return __builtin_memcpy (buf, p, size);
> +}
> +
> +int
> +main (void)
> +{
> +  long i;
> +  for (i = 0; i < 65536; i++)
> +    if (foo ("abcdefghijkl", 12) != buf)
> +      __builtin_abort ();
> +  if (foo (buf2, 64) != buf)
> +    __builtin_abort ();
> +  return 0;
> +}
> Index: testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c  (revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c  (revision 0)
> @@ -0,0 +1,21 @@
> +
> +/* { dg-options "-O2 -fdump-tree-optimized-blocks" } */
> +int a[8];
> +__attribute__ ((noinline))
> +int t()
> +{
> +       int i;
> +       for (i = 0; i < 3; i++)
> +               if (a[i])
> +                       break;
> +       return i;
> +}
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < 1000; i++)
> +    t ();
> +  return 0;
> +}
> +/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C      (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C      (revision 0)
> @@ -0,0 +1,36 @@
> +/* { dg-options "-O2 -fdump-tree-einline" } */
> +class DocId {
> + public:
> + DocId() { }
> + DocId(const DocId &other) {  }
> +};
> +
> +int g;
> +class Base {
> + public:
> + virtual void Foo(DocId id) { g++; }
> +};
> +
> +class Super: public Base {
> + public:
> + void Foo(DocId id) { }
> + void Bar(Base *base, DocId id) __attribute__((noinline));
> +};
> +
> +void Super::Bar(Base *base, DocId id) {
> + Super::Foo(id); // direct call is inlined
> + base->Foo(id); // indirect call is marked do not inline
> +}
> +
> +int main(void)
> +{
> + Base bah;
> + Super baz;
> + DocId gid;
> +
> + baz.Bar(&baz, gid);
> + return 0;
> +}
> +/* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline" } } */
> +/* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline" } } */
> +/* { dg-final-use { cleanup-tree-dump "einline" } } */
> Index: testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C (revision 0)
> @@ -0,0 +1,35 @@
> +/* { dg-options "-O" } */
> +
> +int foo1(void) { return 0; }
> +int bar1(void) { throw 1; }
> +void foo2(void) { }
> +void bar2(void) { throw 1; }
> +void __attribute__((noinline,noclone)) test1(void (*f)(void)) { (*f)(); }
> +void __attribute__((noinline,noclone)) test2(void (*f)(void)) { (*f)(); }
> +int __attribute__((noinline,noclone)) test3(int (*f)(void)) { return (*f)(); }
> +int __attribute__((noinline,noclone)) test4(int (*f)(void)) { return (*f)(); }
> +int __attribute__((noinline,noclone)) test5(int (*f)(void), int x) { return x ? x : (*f)(); }
> +int __attribute__((noinline,noclone)) test6(int (*f)(void), int x) { return x ? x : (*f)(); }
> +void __attribute__((noinline,noclone)) test7(void (*f)(void)) { try { (*f)(); } catch (...) {} }
> +void __attribute__((noinline,noclone)) test8(void (*f)(void)) { try { (*f)();  } catch (...) {}}
> +int __attribute__((noinline,noclone)) test9(int (*f)(void)) { try { return (*f)(); } catch (...) {return 0;} }
> +int __attribute__((noinline,noclone)) test10(int (*f)(void)) { try { return (*f)(); } catch (...) {return 0;} }
> +int __attribute__((noinline,noclone)) test11(int (*f)(void), int x) { try { return x ? x : (*f)(); } catch (...) {return 0;} }
> +int __attribute__((noinline,noclone)) test12(int (*f)(void), int x) { try { return x ? x : (*f)(); } catch (...) {return 0;} }
> +
> +int main()
> +{
> +  for (int i = 0; i < 100; ++i) test1(foo2);
> +  for (int i = 0; i < 100; ++i) try { test2(bar2); } catch (...) {}
> +  for (int i = 0; i < 100; ++i) test3(foo1);
> +  for (int i = 0; i < 100; ++i) try { test4(bar1); } catch (...) {}
> +  for (int i = 0; i < 100; ++i) test5(foo1, 0);
> +  for (int i = 0; i < 100; ++i) try { test6(bar1, 0); } catch (...) {}
> +  for (int i = 0; i < 100; ++i) test7(foo2);
> +  for (int i = 0; i < 100; ++i) try { test8(bar2); } catch (...) {}
> +  for (int i = 0; i < 100; ++i) test9(foo1);
> +  for (int i = 0; i < 100; ++i) try { test10(bar1); } catch (...) {}
> +  for (int i = 0; i < 100; ++i) test11(foo1, 0);
> +  for (int i = 0; i < 100; ++i) try { test12(bar1, 0); } catch (...) {}
> +  return 0;
> +}
> Index: testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C   (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C   (revision 0)
> @@ -0,0 +1,39 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +
> +struct A {
> +  A () {}
> +
> +  virtual int AA (void)
> +  { return 0; }
> +
> +};
> +
> +struct B : public A {
> +  B () {}
> +
> +  virtual int AA (void)
> +  { return 1; }
> +};
> +
> +void * __attribute__((noinline,noclone)) wrap (void *p) { return p; }
> +int
> +main (void)
> +{
> +  A a;
> +  B b;
> +
> +  A* p;
> +
> +  p = (A *)wrap ((void *)&a);
> +  p->AA ();
> +
> +  p = (B *)wrap ((void *)&b);
> +  p->AA ();
> +
> +  return 0;
> +}
> +
> +/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA " "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: testsuite/g++.dg/tree-prof/lipo/partition1.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/partition1.C        (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/partition1.C        (revision 0)
> @@ -0,0 +1,54 @@
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
> +/* { dg-skip-if "PR target/47683" { mips-sgi-irix* } } */
> +
> +struct A { A () __attribute__((noinline)); ~A () __attribute__((noinline)); };
> +A::A () { asm volatile ("" : : : "memory"); }
> +A::~A () { asm volatile ("" : : : "memory"); }
> +
> +int bar () __attribute__((noinline));
> +void foo () __attribute__((noinline));
> +
> +volatile int k, l;
> +
> +int bar (int i)
> +{
> +  void *p = __builtin_alloca (i);
> +  asm volatile ("" : : "r" (i), "r" (p) : "memory");
> +  if (k) throw 6;
> +  return ++l;
> +}
> +
> +void foo ()
> +{
> +  A a;
> +  try {
> +    A b;
> +    int i = bar (5);
> +    try { throw 6; } catch (int) {}
> +    if (__builtin_expect (i < 4500, 0)) {
> +      bar (7);
> +      try { bar (8); } catch (long) {}
> +      bar (10);
> +      if (__builtin_expect (i < 0, 0)) {
> +       try { bar (12); } catch (...) {}
> +       bar (16);
> +       bar (122);
> +      } else {
> +       try { bar (bar (7)); } catch (int) {}
> +      }
> +    } else {
> +      try { bar (bar (bar (9))); } catch (...) {}
> +      bar (5);
> +    }
> +  } catch (...) {
> +  }
> +}
> +
> +int
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < 10000; i++)
> +    foo ();
> +}
> Index: testsuite/g++.dg/tree-prof/lipo/partition2.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/partition2.C        (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/partition2.C        (revision 0)
> @@ -0,0 +1,16 @@
> +// PR middle-end/45458
> +// { dg-require-effective-target freorder }
> +// { dg-options "-fnon-call-exceptions -freorder-blocks-and-partition" }
> +// { dg-skip-if "PR target/47683" { mips-sgi-irix* } }
> +
> +int
> +main ()
> +{
> +  try
> +  {
> +    throw 6;
> +  }
> +  catch (...)
> +  {
> +  }
> +}
> Index: testsuite/g++.dg/tree-prof/lipo/partition3.C
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/partition3.C        (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/partition3.C        (revision 0)
> @@ -0,0 +1,18 @@
> +// PR middle-end/45566
> +// { dg-require-effective-target freorder }
> +// { dg-options "-O -fnon-call-exceptions -freorder-blocks-and-partition" }
> +
> +int k;
> +
> +int
> +main ()
> +{
> +  try
> +  {
> +    if (k)
> +      throw 6;
> +  }
> +  catch (...)
> +  {
> +  }
> +}
> Index: testsuite/g++.dg/tree-prof/lipo/lipo.exp
> ===================================================================
> --- testsuite/g++.dg/tree-prof/lipo/lipo.exp    (revision 0)
> +++ testsuite/g++.dg/tree-prof/lipo/lipo.exp    (revision 0)
> @@ -0,0 +1,54 @@
> +# Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
> +# Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with GCC; see the file COPYING3.  If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +# Test the functionality of programs compiled with profile-directed block
> +# ordering using -fprofile-generate followed by -fprofile-use.
> +
> +load_lib target-supports.exp
> +
> +# Some targets don't support tree profiling.
> +if { ![check_profiling_available ""] } {
> +    return
> +}
> +
> +# The procedures in profopt.exp need these parameters.
> +set tool g++
> +set prof_ext "gcda"
> +
> +# Override the list defined in profopt.exp.
> +set PROFOPT_OPTIONS [list {}]
> +
> +if $tracelevel then {
> +    strace $tracelevel
> +}
> +
> +# Load support procs.
> +load_lib profopt.exp
> +
> +# These are globals used by profopt-execute.  The first is options
> +# needed to generate profile data, the second is options to use the
> +# profile data.
> +set profile_option "-fprofile-generate -fripa"
> +set feedback_option "-fprofile-use -fripa"
> +
> +foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.C]] {
> +    # If we're only testing specific files and this isn't one of them, skip it.
> +    if ![runtest_file_p $runtests $src] then {
> +        continue
> +    }
> +    profopt-execute $src
> +}
> Index: dwarf2out.c
> ===================================================================
> --- dwarf2out.c (revision 173136)
> +++ dwarf2out.c (working copy)
> @@ -4184,9 +4184,9 @@ dwarf2out_vms_end_prologue (unsigned int
>   /* Output a label to mark the endpoint of the code generated for this
>      function.  */
>   ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
> -                              current_function_funcdef_no);
> +                              FUNC_LABEL_ID (cfun));
>   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, PROLOGUE_END_LABEL,
> -                         current_function_funcdef_no);
> +                         FUNC_LABEL_ID (cfun));
>   fde = &fde_table[fde_table_in_use - 1];
>   fde->dw_fde_vms_end_prologue = xstrdup (label);
>  }
> @@ -4209,9 +4209,9 @@ dwarf2out_vms_begin_epilogue (unsigned i
>   /* Output a label to mark the endpoint of the code generated for this
>      function.  */
>   ASM_GENERATE_INTERNAL_LABEL (label, EPILOGUE_BEGIN_LABEL,
> -                              current_function_funcdef_no);
> +                              FUNC_LABEL_ID (cfun));
>   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, EPILOGUE_BEGIN_LABEL,
> -                         current_function_funcdef_no);
> +                         FUNC_LABEL_ID (cfun));
>   fde->dw_fde_vms_begin_epilogue = xstrdup (label);
>  }
>
> @@ -17918,7 +17918,7 @@ dwarf2out_vms_debug_main_pointer (void)
>   die->die_tag = DW_TAG_subprogram;
>   add_name_attribute (die, VMS_DEBUG_MAIN_POINTER);
>   ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
> -                              current_function_funcdef_no);
> +                              FUNC_LABEL_ID (cfun));
>   add_AT_lbl_id (die, DW_AT_entry_pc, label);
>
>   /* Make it the first child of comp_unit_die ().  */
> Index: tree-profile.c
> ===================================================================
> --- tree-profile.c      (revision 173136)
> +++ tree-profile.c      (working copy)
> @@ -473,7 +473,6 @@ gimple_gen_ic_func_profiler (void)
>  static void
>  gimple_gen_ic_func_topn_profiler (void)
>  {
> -  struct cgraph_node * c_node = cgraph_node (current_function_decl);
>   gimple_stmt_iterator gsi;
>   gimple stmt1;
>   tree cur_func, gcov_info, cur_func_id;
> @@ -483,16 +482,6 @@ gimple_gen_ic_func_topn_profiler (void)
>       || DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (current_function_decl))
>     return;
>
> -  /* We want to make sure template functions are instrumented even though
> -     it is not 'needed' in this module. It is possible that the function
> -     is needed (e.g, as icall target) in another module. Note that for
> -     functions in comdat groups, there is no guarantee which copy will be
> -     picked up by the linker.  */
> -
> -  if (!c_node->needed
> -      && (!c_node->reachable || !DECL_COMDAT (c_node->decl)))
> -    return;
> -
>   gimple_init_edge_profiler ();
>
>   gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
> @@ -659,6 +648,7 @@ tree_profiling (void)
>   /* Now perform link to allow cross module inlining.  */
>   cgraph_do_link ();
>   varpool_do_link ();
> +  cgraph_unify_type_alias_sets ();
>
>   init_node_map();
>
> Index: l-ipo.c
> ===================================================================
> --- l-ipo.c     (revision 173136)
> +++ l-ipo.c     (working copy)
> @@ -42,7 +42,12 @@ struct GTY(()) saved_module_scope
>
>  static GTY (()) struct saved_module_scope *current_module_scope;
>  static GTY ((param_is (struct saved_module_scope))) htab_t saved_module_scope_map;
> -static int primary_module_last_fundef_no = 0;
> +static int primary_module_last_funcdef_no = 0;
> +/* Function id space for each module are qualified by the module id. After all the files
> +   are parsed, we need to reset the funcdef_no to the max value from all module so that
> +   the function clones do not assigned with ids colliding with some other orignal function
> +   in the same module.  */
> +static int max_funcdef_no = 0;
>  static location_t primary_module_last_loc;
>  /* Primary module pending templates.  */
>  /* Referenced asm ids in primary module.  */
> @@ -348,7 +353,7 @@ restore_post_parsing_states (void)
>  {
>   current_module_id = primary_module_id;
>   current_module_scope = get_module_scope (primary_module_id);
> -  set_funcdef_no (primary_module_last_fundef_no);
> +  set_funcdef_no (max_funcdef_no);
>   input_location = primary_module_last_loc;
>
>   restore_assembler_name_reference_bit ();
> @@ -364,6 +369,8 @@ void
>  pop_module_scope (void)
>  {
>   bool is_last = false;
> +  int  last_funcdef_no;
> +
>   if (!flag_dyn_ipa || !L_IPO_COMP_MODE)
>     return;
>
> @@ -379,13 +386,17 @@ pop_module_scope (void)
>
>   is_last = is_last_module (current_module_id);
>
> +  last_funcdef_no = get_last_funcdef_no ();
> +  if (last_funcdef_no > max_funcdef_no)
> +    max_funcdef_no = last_funcdef_no;
> +
>   lang_hooks.l_ipo.save_built_in_decl_post_module_parsing ();
>   /* Save primary module state if needed (when module group
>      size > 1)  */
>   if (L_IPO_IS_PRIMARY_MODULE && num_in_fnames > 1)
>     {
>       save_assembler_name_reference_bit ();
> -      primary_module_last_fundef_no = get_last_funcdef_no ();
> +      primary_module_last_funcdef_no = last_funcdef_no;
>     }
>
>   if (!is_last)
> Index: gcov-dump.c
> ===================================================================
> --- gcov-dump.c (revision 173136)
> +++ gcov-dump.c (working copy)
> @@ -326,14 +326,15 @@ tag_function (const char *filename ATTRI
>              unsigned tag ATTRIBUTE_UNUSED, unsigned length)
>  {
>   unsigned long pos = gcov_position ();
> -  const char *name;
>
>   printf (" ident=%u", gcov_read_unsigned ());
>   printf (", checksum=0x%08x", gcov_read_unsigned ());
> -  name = gcov_read_string ();
> -  printf (", `%s'", name ? name : "NULL");
>   if (gcov_position () - pos < length)
>     {
> +      const char *name;
> +
> +      name = gcov_read_string ();
> +      printf (", `%s'", name ? name : "NULL");
>       name = gcov_read_string ();
>       printf (" %s", name ? name : "NULL");
>       printf (":%u", gcov_read_unsigned ());
>
> --
> This patch is available for review at http://codereview.appspot.com/4444076
>
Jan Hubicka April 29, 2011, 11:16 p.m. UTC | #2
Hi,
It seems that majority of testcases are independent of lipo. We could probably
enjoy more of testing on mainline, so could you please take those working on
mainline and make mainline patch and let me know what of the tests are not working
there? 
> Index: testsuite/gcc.dg/tree-prof/lipo/inliner-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/inliner-1.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/inliner-1.c	(revision 0)
> @@ -0,0 +1,42 @@
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +int a;
> +int b[100];
> +void abort (void);
> +
> +inline void
> +cold_function ()
> +{
> +  int i;
> +  for (i = 0; i < 99; i++)
> +    if (b[i] / (b[i+1] + 1))
> +      abort ();
> +}
> +
> +inline void
> +hot_function ()
> +{
> +  int i;
> +  for (i = 0; i < 99; i++)
> +    if (b[i] / (b[i+1] + 1))
> +      abort ();
> +}
> +
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < 100; i++)
> +    {
> +      if (a)
> +        cold_function ();
> +      else
> +        hot_function ();
> +    }
> +  return 0;
> +}
> +
> +/* cold function should be inlined, while hot function should not.  
> +   Look for "cold_function () [tail call];" call statement not for the
> +   declaration or other apperances of the string in dump.  */
> +/* { dg-final-use { scan-tree-dump "cold_function ..;" "optimized"} } */
> +/* { dg-final-use { scan-tree-dump-not "hot_function ..;" "optimized"} } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c	(revision 0)
> @@ -0,0 +1,39 @@
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
> +
> +#include <string.h>
> +
> +#define SIZE 1000
> +int t0 = 0;
> +const char *t2[SIZE];
> +char buf[SIZE];
> +
> +void
> +foo (void)
> +{
> +  char *s = buf;
> +  t0 = 1;
> +
> +  for (;;)
> +    {
> +      if (*s == '\0')
> +	break;
> +      else
> +	{
> +	  t2[t0] = s;
> +	  t0++;
> +	}
> +      *s++ = '\0';
> +    }
> +  t2[t0] = NULL;
> +}
> +
> +
> +int
> +main ()
> +{
> +  strcpy (buf, "hello");
> +  foo ();
> +  return 0; 
> +}
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/stringop-1.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/stringop-1.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/stringop-1.c	(revision 0)
> @@ -0,0 +1,22 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */

We probably ought to fix the pass name... We already have "ipa-profile" for profile
propagation.  What about "gcov", unless we could come with something better?
> +int a[1000];
> +int b[1000];
> +int size=1;
> +int max=10000;
> +main()
> +{
> +  int i;
> +  for (i=0;i<max; i++)
> +    {
> +      __builtin_memcpy (a, b, size * sizeof (a[0]));
> +      asm("");
> +    }
> +   return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/pr34999.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/pr34999.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/pr34999.c	(revision 0)
> @@ -0,0 +1,45 @@
> +/* Same test as built-in-setjmp.c.  Includes the case where
> +   the source block of a crossing fallthru edge ends with a call.  */
> +/* { dg-require-effective-target freorder } */
> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
> +
> +extern int strcmp(const char *, const char *);
> +extern char *strcpy(char *, const char *);
> +extern void abort(void);
> +extern void exit(int);
> +
> +void *buf[20];
> +
> +void __attribute__((noinline))
> +sub2 (void)
> +{
> +  __builtin_longjmp (buf, 1);
> +}
> +
> +int
> +main ()
> +{
> +  char *p = (char *) __builtin_alloca (20);
> +
> +  strcpy (p, "test");
> +
> +  if (__builtin_setjmp (buf))
> +    {
> +      if (strcmp (p, "test") != 0)
> +	abort ();
> +
> +      exit (0);
> +    }
> +
> +  {
> +    int *q = (int *) __builtin_alloca (p[2] * sizeof (int));
> +    int i;
> +    
> +    for (i = 0; i < p[2]; i++)
> +      q[i] = 0;
> +
> +    while (1)
> +      sub2 ();
> +  }
> +}
> +
> Index: testsuite/gcc.dg/tree-prof/lipo/stringop-2.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/stringop-2.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/stringop-2.c	(revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
> +int a[1000];
> +int b[1000];
> +int size=1;
> +int max=10000;
> +main()
> +{
> +  int i;
> +  for (i=0;i<max; i++)
> +    {
> +      __builtin_memset (a, 10, size * sizeof (a[0]));
> +      asm("");
> +    }
> +   return 0;
> +}
> +/* { 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-ipa-dump "tree_profile_ipa" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/update-loopch.c
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/update-loopch.c	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/update-loopch.c	(revision 0)
> @@ -0,0 +1,21 @@
> +/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
> +int max = 33333;
> +int a[8];
> +int
> +main ()
> +{
> +  int i;
> +  for (i = 0; i < max; i++)
> +    {
> +      a[i % 8]++;
> +    }
> +  return 0;
> +}
> +/* 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-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-ipa-dump "tree_profile_ipa" } } */
> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
> Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa
> ===================================================================
> --- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa	(revision 0)
> +++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa	(revision 0)

Suprious add?

Thanks,
Honza
Xinliang David Li April 29, 2011, 11:28 p.m. UTC | #3
On Fri, Apr 29, 2011 at 4:16 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> It seems that majority of testcases are independent of lipo. We could probably
> enjoy more of testing on mainline, so could you please take those working on
> mainline and make mainline patch and let me know what of the tests are not working
> there?

Actually those test cases are cloned from tree-prof directory into the
lipo sub-directory. The difference is that lipo.exp file passes
additional -fripa flag.  The missing tests for LIPO are ones with
multiple source with non trivial module group testing -- I have not
added those yet.

>
> We probably ought to fix the pass name... We already have "ipa-profile" for profile
> propagation.  What about "gcov", unless we could come with something better?

Yes -- tree_profile_ipa and ipa_profile confuses many people.


>> +int a[1000];
>> +int b[1000];
>> +int size=1;
>> +int max=10000;
>> +main()
>> +{
>> +  int i;
>> +  for (i=0;i<max; i++)
>> +    {
>> +      __builtin_memcpy (a, b, size * sizeof (a[0]));
>> +      asm("");
>> +    }
>> +   return 0;
>> +}
>> +/* { 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-ipa-dump "tree_profile_ipa" } } */
>> Index: testsuite/gcc.dg/tree-prof/lipo/pr34999.c
>> ===================================================================
>> --- testsuite/gcc.dg/tree-prof/lipo/pr34999.c (revision 0)
>> +++ testsuite/gcc.dg/tree-prof/lipo/pr34999.c (revision 0)
>> @@ -0,0 +1,45 @@
>> +/* Same test as built-in-setjmp.c.  Includes the case where
>> +   the source block of a crossing fallthru edge ends with a call.  */
>> +/* { dg-require-effective-target freorder } */
>> +/* { dg-options "-O2 -freorder-blocks-and-partition" } */
>> +
>> +extern int strcmp(const char *, const char *);
>> +extern char *strcpy(char *, const char *);
>> +extern void abort(void);
>> +extern void exit(int);
>> +
>> +void *buf[20];
>> +
>> +void __attribute__((noinline))
>> +sub2 (void)
>> +{
>> +  __builtin_longjmp (buf, 1);
>> +}
>> +
>> +int
>> +main ()
>> +{
>> +  char *p = (char *) __builtin_alloca (20);
>> +
>> +  strcpy (p, "test");
>> +
>> +  if (__builtin_setjmp (buf))
>> +    {
>> +      if (strcmp (p, "test") != 0)
>> +     abort ();
>> +
>> +      exit (0);
>> +    }
>> +
>> +  {
>> +    int *q = (int *) __builtin_alloca (p[2] * sizeof (int));
>> +    int i;
>> +
>> +    for (i = 0; i < p[2]; i++)
>> +      q[i] = 0;
>> +
>> +    while (1)
>> +      sub2 ();
>> +  }
>> +}
>> +
>> Index: testsuite/gcc.dg/tree-prof/lipo/stringop-2.c
>> ===================================================================
>> --- testsuite/gcc.dg/tree-prof/lipo/stringop-2.c      (revision 0)
>> +++ testsuite/gcc.dg/tree-prof/lipo/stringop-2.c      (revision 0)
>> @@ -0,0 +1,20 @@
>> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
>> +int a[1000];
>> +int b[1000];
>> +int size=1;
>> +int max=10000;
>> +main()
>> +{
>> +  int i;
>> +  for (i=0;i<max; i++)
>> +    {
>> +      __builtin_memset (a, 10, size * sizeof (a[0]));
>> +      asm("");
>> +    }
>> +   return 0;
>> +}
>> +/* { 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-ipa-dump "tree_profile_ipa" } } */
>> Index: testsuite/gcc.dg/tree-prof/lipo/update-loopch.c
>> ===================================================================
>> --- testsuite/gcc.dg/tree-prof/lipo/update-loopch.c   (revision 0)
>> +++ testsuite/gcc.dg/tree-prof/lipo/update-loopch.c   (revision 0)
>> @@ -0,0 +1,21 @@
>> +/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
>> +int max = 33333;
>> +int a[8];
>> +int
>> +main ()
>> +{
>> +  int i;
>> +  for (i = 0; i < max; i++)
>> +    {
>> +      a[i % 8]++;
>> +    }
>> +  return 0;
>> +}
>> +/* 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-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-ipa-dump "tree_profile_ipa" } } */
>> +/* { dg-final-use { cleanup-tree-dump "optimized" } } */
>> Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa
>> ===================================================================
>> --- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa   (revision 0)
>> +++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa   (revision 0)
>
> Suprious add?
>

Right.

Thanks,

David


> Thanks,
> Honza
>
Jan Hubicka April 30, 2011, 9:21 a.m. UTC | #4
> On Fri, Apr 29, 2011 at 4:16 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> > Hi,
> > It seems that majority of testcases are independent of lipo. We could probably
> > enjoy more of testing on mainline, so could you please take those working on
> > mainline and make mainline patch and let me know what of the tests are not working
> > there?
> 
> Actually those test cases are cloned from tree-prof directory into the
> lipo sub-directory. The difference is that lipo.exp file passes
> additional -fripa flag.  The missing tests for LIPO are ones with
> multiple source with non trivial module group testing -- I have not
> added those yet.

Hmm, the tests looked familiar so I wondered how redundant they are ;)
Well, any tests that you do have for PDO and are not in mainlie are welcome.
> 
> >
> > We probably ought to fix the pass name... We already have "ipa-profile" for profile
> > propagation.  What about "gcov", unless we could come with something better?
> 
> Yes -- tree_profile_ipa and ipa_profile confuses many people.

If we won't get better idea, I would go with gcov.

Honza
Xinliang David Li April 30, 2011, 4:37 p.m. UTC | #5
On Sat, Apr 30, 2011 at 2:21 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> On Fri, Apr 29, 2011 at 4:16 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> > Hi,
>> > It seems that majority of testcases are independent of lipo. We could probably
>> > enjoy more of testing on mainline, so could you please take those working on
>> > mainline and make mainline patch and let me know what of the tests are not working
>> > there?
>>
>> Actually those test cases are cloned from tree-prof directory into the
>> lipo sub-directory. The difference is that lipo.exp file passes
>> additional -fripa flag.  The missing tests for LIPO are ones with
>> multiple source with non trivial module group testing -- I have not
>> added those yet.
>
> Hmm, the tests looked familiar so I wondered how redundant they are ;)
> Well, any tests that you do have for PDO and are not in mainlie are welcome.
>>
>> >
>> > We probably ought to fix the pass name... We already have "ipa-profile" for profile
>> > propagation.  What about "gcov", unless we could come with something better?
>>
>> Yes -- tree_profile_ipa and ipa_profile confuses many people.
>
> If we won't get better idea, I would go with gcov.

Maybe it is better to change ipa-profile to something like
ipa_freq_prop.   Gcov is the name for coverage --- though it is
related to profiling and FDO, and it can so be confusing.

David

>
> Honza
>
Jan Hubicka April 30, 2011, 5:07 p.m. UTC | #6
> On Sat, Apr 30, 2011 at 2:21 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> >> On Fri, Apr 29, 2011 at 4:16 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> >> > Hi,
> >> > It seems that majority of testcases are independent of lipo. We could probably
> >> > enjoy more of testing on mainline, so could you please take those working on
> >> > mainline and make mainline patch and let me know what of the tests are not working
> >> > there?
> >>
> >> Actually those test cases are cloned from tree-prof directory into the
> >> lipo sub-directory. The difference is that lipo.exp file passes
> >> additional -fripa flag.  The missing tests for LIPO are ones with
> >> multiple source with non trivial module group testing -- I have not
> >> added those yet.
> >
> > Hmm, the tests looked familiar so I wondered how redundant they are ;)
> > Well, any tests that you do have for PDO and are not in mainlie are welcome.
> >>
> >> >
> >> > We probably ought to fix the pass name... We already have "ipa-profile" for profile
> >> > propagation.  What about "gcov", unless we could come with something better?
> >>
> >> Yes -- tree_profile_ipa and ipa_profile confuses many people.
> >
> > If we won't get better idea, I would go with gcov.
> 
> Maybe it is better to change ipa-profile to something like
> ipa_freq_prop.   Gcov is the name for coverage --- though it is
> related to profiling and FDO, and it can so be confusing.

Well, pass_ipa_profile is at IPA level what pass_profile does at tree level,
so we would need to rename both.  We could go with something like
guess_profile as opposed to read profile, unless we come with anything better.
gcov originales from coverage, indeed, but it is sort of used for the whole
profiling/feedback infrastructure.
I dunno what is better, both variants are fine with me.  Do we need to use _ instead
of - in pass names?  I quite dislike the -fdump-ipa-profile_estimate naming, so
I am usually trying to stick with one word pass names for this reason...

Honza
> 
> David
> 
> >
> > Honza
> >
Xinliang David Li April 30, 2011, 10:42 p.m. UTC | #7
On Sat, Apr 30, 2011 at 10:07 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> On Sat, Apr 30, 2011 at 2:21 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> >> On Fri, Apr 29, 2011 at 4:16 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> >> > Hi,
>> >> > It seems that majority of testcases are independent of lipo. We could probably
>> >> > enjoy more of testing on mainline, so could you please take those working on
>> >> > mainline and make mainline patch and let me know what of the tests are not working
>> >> > there?
>> >>
>> >> Actually those test cases are cloned from tree-prof directory into the
>> >> lipo sub-directory. The difference is that lipo.exp file passes
>> >> additional -fripa flag.  The missing tests for LIPO are ones with
>> >> multiple source with non trivial module group testing -- I have not
>> >> added those yet.
>> >
>> > Hmm, the tests looked familiar so I wondered how redundant they are ;)
>> > Well, any tests that you do have for PDO and are not in mainlie are welcome.
>> >>
>> >> >
>> >> > We probably ought to fix the pass name... We already have "ipa-profile" for profile
>> >> > propagation.  What about "gcov", unless we could come with something better?
>> >>
>> >> Yes -- tree_profile_ipa and ipa_profile confuses many people.
>> >
>> > If we won't get better idea, I would go with gcov.
>>
>> Maybe it is better to change ipa-profile to something like
>> ipa_freq_prop.   Gcov is the name for coverage --- though it is
>> related to profiling and FDO, and it can so be confusing.
>
> Well, pass_ipa_profile is at IPA level what pass_profile does at tree level,
> so we would need to rename both.  We could go with something like
> guess_profile as opposed to read profile, unless we come with anything better.
> gcov originales from coverage, indeed, but it is sort of used for the whole
> profiling/feedback infrastructure.
> I dunno what is better, both variants are fine with me.  Do we need to use _ instead
> of - in pass names?  I quite dislike the -fdump-ipa-profile_estimate naming, so
> I am usually trying to stick with one word pass names for this reason...
>

How about  change "tree_profile_ipa" to "tree-profile" and
"ipa-profile" to "profile-estimate" -- basically drop the ipa in the
name. There are also many other passes using '_' though. Can tree
level pass_profile's name also be changed to 'profile-estimate'? Their
dump names won't collide.

Thanks,

David


> Honza
>>
>> David
>>
>> >
>> > Honza
>> >
>
Jan Hubicka May 1, 2011, 2:16 p.m. UTC | #8
> How about  change "tree_profile_ipa" to "tree-profile" and
> "ipa-profile" to "profile-estimate" -- basically drop the ipa in the
> name. There are also many other passes using '_' though. Can tree
> level pass_profile's name also be changed to 'profile-estimate'? Their
> dump names won't collide.

profile-estimate for tree and IPA passes seems fine.  I would drop tree from
tree-profile pass name, too.  We no longer have RTL profiling.

Honza
> 
> Thanks,
> 
> David
> 
> 
> > Honza
> >>
> >> David
> >>
> >> >
> >> > Honza
> >> >
> >
Xinliang David Li May 1, 2011, 5:03 p.m. UTC | #9
On Sun, May 1, 2011 at 7:16 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> How about  change "tree_profile_ipa" to "tree-profile" and
>> "ipa-profile" to "profile-estimate" -- basically drop the ipa in the
>> name. There are also many other passes using '_' though. Can tree
>> level pass_profile's name also be changed to 'profile-estimate'? Their
>> dump names won't collide.
>
> profile-estimate for tree and IPA passes seems fine.  I would drop tree from
> tree-profile pass name, too.  We no longer have RTL profiling.

I agree.

Thanks,

David

>
> Honza
>>
>> Thanks,
>>
>> David
>>
>>
>> > Honza
>> >>
>> >> David
>> >>
>> >> >
>> >> > Honza
>> >> >
>> >
>
diff mbox

Patch

Index: final.c
===================================================================
--- final.c	(revision 173136)
+++ final.c	(working copy)
@@ -1623,7 +1623,7 @@  profile_function (FILE *file ATTRIBUTE_U
       int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
       switch_to_section (data_section);
       ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
-      targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
+      targetm.asm_out.internal_label (file, "LP", FUNC_LABEL_ID (cfun));
       assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
     }
 
@@ -1636,7 +1636,7 @@  profile_function (FILE *file ATTRIBUTE_U
     ASM_OUTPUT_REG_PUSH (file, REGNO (chain));
 #endif
 
-  FUNCTION_PROFILER (file, current_function_funcdef_no);
+  FUNCTION_PROFILER (file, FUNC_LABEL_ID (cfun));
 
 #ifdef ASM_OUTPUT_REG_PUSH
   if (chain && REG_P (chain))
Index: cgraphunit.c
===================================================================
--- cgraphunit.c	(revision 173136)
+++ cgraphunit.c	(working copy)
@@ -1117,11 +1117,6 @@  cgraph_finalize_compilation_unit (void)
   /* Gimplify and lower thunks.  */
   cgraph_analyze_functions ();
 
-  /* LIPO support  */
-  /* Recognize equivalent types across modules and
-     merge their alias sets.  */
-  cgraph_unify_type_alias_sets ();
-
   /* Finally drive the pass manager.  */
   cgraph_optimize ();
 
Index: testsuite/gcc.dg/tree-prof/lipo/inliner-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/inliner-1.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/inliner-1.c	(revision 0)
@@ -0,0 +1,42 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int a;
+int b[100];
+void abort (void);
+
+inline void
+cold_function ()
+{
+  int i;
+  for (i = 0; i < 99; i++)
+    if (b[i] / (b[i+1] + 1))
+      abort ();
+}
+
+inline void
+hot_function ()
+{
+  int i;
+  for (i = 0; i < 99; i++)
+    if (b[i] / (b[i+1] + 1))
+      abort ();
+}
+
+main ()
+{
+  int i;
+  for (i = 0; i < 100; i++)
+    {
+      if (a)
+        cold_function ();
+      else
+        hot_function ();
+    }
+  return 0;
+}
+
+/* cold function should be inlined, while hot function should not.  
+   Look for "cold_function () [tail call];" call statement not for the
+   declaration or other apperances of the string in dump.  */
+/* { dg-final-use { scan-tree-dump "cold_function ..;" "optimized"} } */
+/* { dg-final-use { scan-tree-dump-not "hot_function ..;" "optimized"} } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/gdb_cmd
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/gdb_cmd	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/gdb_cmd	(revision 0)
@@ -0,0 +1,5 @@ 
+file /usr/local/google/davidxl/dev/gcc/gcc-gmain-native_64-linux/libexec/gcc/x86_64-linux/4.6.0-google-main/cc1
+set args -quiet -v indir-call-prof.c -march=core2 -mcx16 -msahf --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=4096 -mtune=core2 -quiet -dumpbase indir-call-prof.c -auxbase indir-call-prof -g -O2 -version -fprofile-generate -fripa -fdump-ipa-tree_profile_ipa -fdump-tree-optimized-blocks -o /tmp/ccdBoNgb.s
+b  main
+b internal_error
+b fancy_abort
Index: testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/bb-reorg.c	(revision 0)
@@ -0,0 +1,39 @@ 
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+#include <string.h>
+
+#define SIZE 1000
+int t0 = 0;
+const char *t2[SIZE];
+char buf[SIZE];
+
+void
+foo (void)
+{
+  char *s = buf;
+  t0 = 1;
+
+  for (;;)
+    {
+      if (*s == '\0')
+	break;
+      else
+	{
+	  t2[t0] = s;
+	  t0++;
+	}
+      *s++ = '\0';
+    }
+  t2[t0] = NULL;
+}
+
+
+int
+main ()
+{
+  strcpy (buf, "hello");
+  foo ();
+  return 0; 
+}
+
Index: testsuite/gcc.dg/tree-prof/lipo/stringop-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/stringop-1.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/stringop-1.c	(revision 0)
@@ -0,0 +1,22 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+int a[1000];
+int b[1000];
+int size=1;
+int max=10000;
+main()
+{
+  int i;
+  for (i=0;i<max; i++)
+    {
+      __builtin_memcpy (a, b, size * sizeof (a[0]));
+      asm("");
+    }
+   return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/pr34999.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/pr34999.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/pr34999.c	(revision 0)
@@ -0,0 +1,45 @@ 
+/* Same test as built-in-setjmp.c.  Includes the case where
+   the source block of a crossing fallthru edge ends with a call.  */
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+
+extern int strcmp(const char *, const char *);
+extern char *strcpy(char *, const char *);
+extern void abort(void);
+extern void exit(int);
+
+void *buf[20];
+
+void __attribute__((noinline))
+sub2 (void)
+{
+  __builtin_longjmp (buf, 1);
+}
+
+int
+main ()
+{
+  char *p = (char *) __builtin_alloca (20);
+
+  strcpy (p, "test");
+
+  if (__builtin_setjmp (buf))
+    {
+      if (strcmp (p, "test") != 0)
+	abort ();
+
+      exit (0);
+    }
+
+  {
+    int *q = (int *) __builtin_alloca (p[2] * sizeof (int));
+    int i;
+    
+    for (i = 0; i < p[2]; i++)
+      q[i] = 0;
+
+    while (1)
+      sub2 ();
+  }
+}
+
Index: testsuite/gcc.dg/tree-prof/lipo/stringop-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/stringop-2.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/stringop-2.c	(revision 0)
@@ -0,0 +1,20 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+int a[1000];
+int b[1000];
+int size=1;
+int max=10000;
+main()
+{
+  int i;
+  for (i=0;i<max; i++)
+    {
+      __builtin_memset (a, 10, size * sizeof (a[0]));
+      asm("");
+    }
+   return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/update-loopch.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/update-loopch.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/update-loopch.c	(revision 0)
@@ -0,0 +1,21 @@ 
+/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa-blocks -fdump-tree-optimized-blocks" } */
+int max = 33333;
+int a[8];
+int
+main ()
+{
+  int i;
+  for (i = 0; i < max; i++)
+    {
+      a[i % 8]++;
+    }
+  return 0;
+}
+/* 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-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-ipa-dump "tree_profile_ipa" } } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.040i.tree_profile_ipa	(revision 0)
@@ -0,0 +1,306 @@ 
+Abnormal edge 3 to 1 put to tree
+Abnormal edge 4 to 1 put to tree
+Abnormal edge 7 to 1 put to tree
+Normal edge 0 to 2 put to tree
+Normal edge 2 to 6 put to tree
+Normal edge 4 to 5 put to tree
+8 basic blocks
+10 edges
+0 ignored edges
+Stmt p.0_3 ();
+Indirect call -- top N
+Merged 1 profiles with maximal count 10.
+
+Read edge from 3 to 4, count:10
+Read edge from 5 to 6, count:10
+Read edge from 6 to 3, count:10
+Read edge from 6 to 7, count:1
+4 edge counts read
+
+8 basic blocks, 10 edges.
+
+Basic block 0 , next 2, loop_depth 0, count 1, freq 909, maybe hot.
+Predecessors: 
+Successors:  2 [100.0%]  count:1 (fallthru,exec)
+
+Basic block 2 , prev 0, next 3, loop_depth 0, count 1, freq 909, maybe hot.
+Predecessors:  ENTRY [100.0%]  count:1 (fallthru,exec)
+Successors:  6 [100.0%]  count:1 (fallthru,exec)
+
+Basic block 3 , prev 2, next 4, loop_depth 1, count 10, freq 9091, maybe hot.
+Predecessors:  6 [90.9%]  count:10 (true,exec)
+Successors:  4 [100.0%]  count:10 (fallthru) EXIT (fake)
+
+Basic block 4 , prev 3, next 5, loop_depth 1, count 10, freq 9091, maybe hot.
+Predecessors:  3 [100.0%]  count:10 (fallthru)
+Successors:  5 [100.0%]  count:10 (fallthru) EXIT (fake)
+
+Basic block 5 , prev 4, next 6, loop_depth 1, count 10, freq 9091, maybe hot.
+Predecessors:  4 [100.0%]  count:10 (fallthru)
+Successors:  6 [100.0%]  count:10 (fallthru,dfs_back,exec)
+
+Basic block 6 , prev 5, next 7, loop_depth 1, count 11, freq 10000, maybe hot.
+Predecessors:  2 [100.0%]  count:1 (fallthru,exec) 5 [100.0%]  count:10 (fallthru,dfs_back,exec)
+Successors:  3 [90.9%]  count:10 (true,exec) 7 [9.1%]  count:1 (false,exec)
+
+Basic block 7 , prev 6, next 1, loop_depth 0, count 1, freq 909, maybe hot.
+Predecessors:  6 [9.1%]  count:1 (false,exec)
+Successors:  EXIT [100.0%]  count:1
+
+Basic block 1 , prev 7, loop_depth 0, count 1, freq 909, maybe hot.
+Predecessors:  7 [100.0%]  count:1 4 (fake) 3 (fake)
+Successors: 
+
+Graph solving took 3 passes.
+
+1 branches
+0% branches in range 0-5%
+100% branches in range 5-10%
+0% branches in range 10-15%
+0% branches in range 15-20%
+0% branches in range 20-25%
+0% branches in range 25-30%
+0% branches in range 30-35%
+0% branches in range 35-40%
+0% branches in range 40-45%
+0% branches in range 45-50%
+
+
+Trying transformations on stmt p.0_3 ();
+Indirect call -- top N
+Indirect call -> direct call p.0_3=> a1 (module_id:1, func_id:1)
+Transformation on insn:
+p.0_3 ();
+==>
+a1 ();
+hist->count 9 hist->all 10
+Analyzing function body size: main
+  freq: 10001 size:  3 time: 12 setp (&p, i_1);
+  freq: 10001 size:  1 time:  1 p.0_3 = p;
+  freq: 10001 size:  0 time:  0 PROF.1_10 = p.0_3;
+  freq: 10001 size:  0 time:  0 PROF.1_11 = (void *) a1;
+  freq: 10001 size:  2 time:  2 if (PROF.1_11 == PROF.1_10)
+  freq:  9001 size:  2 time: 11 a1 ();
+  freq:  1000 size:  2 time: 11 p.0_3 ();
+  freq: 10001 size:  1 time:  1 i_4 = i_1 + 1;
+  freq: 11001 size:  2 time:  2 if (i_1 <= 9)
+  freq:  1000 size:  1 time:  2 return 0;
+Overall function body time: 294-2 size: 16-3
+With function call overhead time: 294-13 size: 16-5
+Abnormal edge 5 to 1 put to tree
+Normal edge 0 to 2 put to tree
+Normal edge 2 to 3 put to tree
+Normal edge 2 to 4 put to tree
+6 basic blocks
+6 edges
+0 ignored edges
+Merged 1 profiles with maximal count 10.
+
+Read edge from 3 to 5, count:1
+Read edge from 4 to 5, count:9
+2 edge counts read
+
+6 basic blocks, 6 edges.
+
+Basic block 0 , next 2, loop_depth 0, count 10, freq 10000, maybe hot.
+Predecessors: 
+Successors:  2 [100.0%]  count:10 (fallthru,exec)
+
+Basic block 2 , prev 0, next 3, loop_depth 0, count 10, freq 10000, maybe hot.
+Predecessors:  ENTRY [100.0%]  count:10 (fallthru,exec)
+Successors:  3 [39.0%]  count:1 (true,exec) 4 [61.0%]  count:9 (false,exec)
+
+Basic block 3 , prev 2, next 4, loop_depth 0, count 1, freq 3900, maybe hot.
+Predecessors:  2 [39.0%]  count:1 (true,exec)
+Successors:  5 [100.0%]  count:1 (fallthru,exec)
+
+Basic block 4 , prev 3, next 5, loop_depth 0, count 9, freq 6100, maybe hot.
+Predecessors:  2 [61.0%]  count:9 (false,exec)
+Successors:  5 [100.0%]  count:9 (fallthru,exec)
+
+Basic block 5 , prev 4, next 1, loop_depth 0, count 10, freq 10000, maybe hot.
+Predecessors:  3 [100.0%]  count:1 (fallthru,exec) 4 [100.0%]  count:9 (fallthru,exec)
+Successors:  EXIT [100.0%]  count:10
+
+Basic block 1 , prev 5, loop_depth 0, count 10, freq 10000, maybe hot.
+Predecessors:  5 [100.0%]  count:10
+Successors: 
+
+Graph solving took 3 passes.
+
+1 branches
+0% branches in range 0-5%
+0% branches in range 5-10%
+100% branches in range 10-15%
+0% branches in range 15-20%
+0% branches in range 20-25%
+0% branches in range 25-30%
+0% branches in range 30-35%
+0% branches in range 35-40%
+0% branches in range 40-45%
+0% branches in range 45-50%
+
+
+Abnormal edge 2 to 1 put to tree
+3 basic blocks
+2 edges
+0 ignored edges
+Merged 1 profiles with maximal count 10.
+
+Read edge from 0 to 2, count:1
+1 edge counts read
+
+3 basic blocks, 2 edges.
+
+Basic block 0 , next 2, loop_depth 0, count 1, freq 10000, maybe hot.
+Predecessors: 
+Successors:  2 [100.0%]  count:1 (fallthru,exec)
+
+Basic block 2 , prev 0, next 1, loop_depth 0, count 1, freq 10000, maybe hot.
+Predecessors:  ENTRY [100.0%]  count:1 (fallthru,exec)
+Successors:  EXIT [100.0%]  count:1
+
+Basic block 1 , prev 2, loop_depth 0, count 1, freq 10000, maybe hot.
+Predecessors:  2 [100.0%]  count:1
+Successors: 
+
+Graph solving took 3 passes.
+
+0 branches
+
+
+Abnormal edge 2 to 1 put to tree
+3 basic blocks
+2 edges
+0 ignored edges
+Merged 1 profiles with maximal count 10.
+
+Read edge from 0 to 2, count:9
+1 edge counts read
+
+3 basic blocks, 2 edges.
+
+Basic block 0 , next 2, loop_depth 0, count 9, freq 10000, maybe hot.
+Predecessors: 
+Successors:  2 [100.0%]  count:9 (fallthru,exec)
+
+Basic block 2 , prev 0, next 1, loop_depth 0, count 9, freq 10000, maybe hot.
+Predecessors:  ENTRY [100.0%]  count:9 (fallthru,exec)
+Successors:  EXIT [100.0%]  count:9
+
+Basic block 1 , prev 2, loop_depth 0, count 9, freq 10000, maybe hot.
+Predecessors:  2 [100.0%]  count:9
+Successors: 
+
+Graph solving took 3 passes.
+
+0 branches
+
+
+
+
+Symbols to be put in SSA form
+
+{ .MEM }
+
+
+Incremental SSA update started at block: 0
+
+Number of blocks in CFG: 11
+Number of blocks to update: 10 ( 91%)
+
+
+
+main ()
+{
+  void * PROF.1;
+  int i;
+  int (*<T352>) (void) p;
+  int (*<T352>) (void) p.0;
+
+<bb 2>:
+  goto <bb 6>;
+
+<bb 3>:
+  setp (&p, i_1);
+
+<bb 4>:
+  p.0_3 = p;
+  PROF.1_10 = p.0_3;
+  PROF.1_11 = (void *) a1;
+  if (PROF.1_11 == PROF.1_10)
+    goto <bb 8>;
+  else
+    goto <bb 9>;
+
+<bb 8>:
+  a1 ();
+  goto <bb 10>;
+
+<bb 9>:
+  p.0_3 ();
+
+<bb 10>:
+
+<bb 5>:
+  i_4 = i_1 + 1;
+
+<bb 6>:
+  # i_1 = PHI <0(2), i_4(5)>
+  if (i_1 <= 9)
+    goto <bb 3>;
+  else
+    goto <bb 7>;
+
+<bb 7>:
+  return 0;
+
+}
+
+
+setp (int (*<T352>) (void) * pp, int i)
+{
+  int (*tp) (void) D.4264;
+  int D.4263;
+  int D.4262;
+  int (*tp) (void) D.4260;
+
+<bb 2>:
+  if (i_1(D) == 0)
+    goto <bb 3>;
+  else
+    goto <bb 4>;
+
+<bb 3>:
+  D.4260_2 = aa[i_1(D)];
+  *pp_3(D) = D.4260_2;
+  goto <bb 5>;
+
+<bb 4>:
+  D.4262_4 = i_1(D) & 2;
+  D.4263_5 = D.4262_4 + 1;
+  D.4264_6 = aa[D.4263_5];
+  *pp_3(D) = D.4264_6;
+
+<bb 5>:
+  return;
+
+}
+
+
+a2 ()
+{
+<bb 2>:
+  return 0;
+
+}
+
+
+a1 ()
+{
+<bb 2>:
+  return 10;
+
+}
+
+
Index: testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1.c	(revision 0)
@@ -0,0 +1,19 @@ 
+/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa" } */
+/* { dg-additional-sources "ic-misattribution-1a.c" } */
+
+extern void other_caller (void);
+
+void
+callee (void)
+{
+  return;
+}
+
+void
+caller(void (*func) (void))
+{
+  func ();
+}
+
+/* { 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: testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/update-tailcall.c	(revision 0)
@@ -0,0 +1,20 @@ 
+/* { dg-options "-O2 -fdump-tree-tailc -fdump-tree-optimized" } */
+__attribute__ ((noinline))
+int factorial(int x)
+{
+   if (x == 1)
+     return 1;
+   else
+     return x*factorial(--x);
+}
+int gbl;
+int
+main()
+{
+   gbl = factorial(100);
+   return 0;
+}
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "tailc"} } */
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { cleanup-tree-dump "tailc" } } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/ic-misattribution-1a.c	(revision 0)
@@ -0,0 +1,22 @@ 
+/* { dg-options "-DEMPTY" } */
+/* This file is only needed in combination with ic-misattribution-1.c
+   but there's no easy way to make this file ignored. */
+extern void callee (void);
+extern void caller (void (*func) (void));
+
+typedef void (*func_t) (void);
+func_t func;
+
+int
+main ()
+{
+#ifdef EMPTY
+#else
+  func = callee;
+  caller (callee);
+  func ();
+#endif
+  return 0;
+}
+
+/* { dg-final-use { cleanup-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/lipo.exp
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/lipo.exp	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/lipo.exp	(revision 0)
@@ -0,0 +1,54 @@ 
+# Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Test the functionality of programs compiled with profile-directed block
+# ordering using -fprofile-generate followed by -fbranch-use.
+
+load_lib target-supports.exp
+
+# Some targets don't support tree profiling.
+if { ![check_profiling_available ""] } {
+    return
+}
+
+# The procedures in profopt.exp need these parameters.
+set tool gcc
+set prof_ext "gcda"
+
+# Override the list defined in profopt.exp.
+set PROFOPT_OPTIONS [list {}]
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Load support procs.
+load_lib profopt.exp
+
+# These are globals used by profopt-execute.  The first is options
+# needed to generate profile data, the second is options to use the
+# profile data.
+set profile_option "-fprofile-generate -fripa -D_PROFILE_GENERATE"
+set feedback_option "-fprofile-use -fripa -D_PROFILE_USE"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+        continue
+    }
+    profopt-execute $src
+}
Index: testsuite/gcc.dg/tree-prof/lipo/tracer-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/tracer-1.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/tracer-1.c	(revision 0)
@@ -0,0 +1,18 @@ 
+/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */
+volatile int a, b, c;
+int main ()
+{
+  int i;
+  for (i = 0; i < 1000; i++)
+    {
+      if (i % 17)
+	a++;
+      else
+	b++;
+      c++;
+    }
+  return 0;
+}
+/* Superblock formation should produce two copies of the increment of c */
+/* { dg-final-generate { scan-tree-dump-times "c =" 2 "tracer" } } */
+/* { dg-final-use { cleanup-tree-dump "tracer" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c.145t.optimized	(revision 0)
@@ -0,0 +1,229 @@ 
+
+;; Function a1 (a1)[1:1] (unlikely executed)
+
+a1 ()
+{
+  # BLOCK 2 freq:10000
+  # PRED: ENTRY [100.0%]  count:9 (fallthru,exec)
+  return 10;
+  # SUCC: EXIT [100.0%] 
+
+}
+
+
+
+;; Function a2 (a2)[1:2]
+
+a2 ()
+{
+  # BLOCK 2 freq:10000 count:1
+  # PRED: ENTRY [100.0%]  count:1 (fallthru,exec)
+  return 0;
+  # SUCC: EXIT [100.0%]  count:1
+
+}
+
+
+
+;; Function setp (setp)[1:3]
+
+Merging blocks 3 and 5
+Merging blocks 4 and 6
+setp (int (*<T352>) (void) * pp, int i)
+{
+  int (*tp) (void) D.4264;
+  int D.4263;
+  int D.4262;
+
+  # BLOCK 2 freq:10000 count:10
+  # PRED: ENTRY [100.0%]  count:10 (fallthru,exec)
+  if (i_1(D) == 0)
+    goto <bb 3>;
+  else
+    goto <bb 4>;
+  # SUCC: 3 [10.0%]  count:1 (true,exec) 4 [90.0%]  count:9 (false,exec)
+
+  # BLOCK 3 freq:1000 count:1
+  # PRED: 2 [10.0%]  count:1 (true,exec)
+  *pp_3(D) = a2;
+  return;
+  # SUCC: EXIT [100.0%]  count:1
+
+  # BLOCK 4 freq:9000 count:9
+  # PRED: 2 [90.0%]  count:9 (false,exec)
+  D.4262_4 = i_1(D) & 2;
+  D.4263_5 = D.4262_4 + 1;
+  D.4264_6 = aa[D.4263_5];
+  *pp_3(D) = D.4264_6;
+  return;
+  # SUCC: EXIT [100.0%]  count:9
+
+}
+
+
+
+;; Function main (main)[1:4] (executed once)
+
+main ()
+{
+  int (*<T352>) (void) p;
+  int (*<T352>) (void) p.0;
+
+  # BLOCK 2 freq:909 count:1
+  # PRED: ENTRY [100.0%]  count:1 (fallthru,exec)
+  setp (&p, 0);
+  p.0_18 = p;
+  if (p.0_18 == a1)
+    goto <bb 4>;
+  else
+    goto <bb 3>;
+  # SUCC: 4 [90.0%]  count:1 (true,exec) 3 [10.0%]  (false,exec)
+
+  # BLOCK 3 freq:91
+  # PRED: 2 [10.0%]  (false,exec)
+  p.0_18 ();
+  # SUCC: 4 [100.0%]  (fallthru,exec)
+
+  # BLOCK 4 freq:909 count:1
+  # PRED: 2 [90.0%]  count:1 (true,exec) 3 [100.0%]  (fallthru,exec)
+  setp (&p, 1);
+  p.0_27 = p;
+  if (p.0_27 == a1)
+    goto <bb 6>;
+  else
+    goto <bb 5>;
+  # SUCC: 6 [90.0%]  count:1 (true,exec) 5 [10.0%]  (false,exec)
+
+  # BLOCK 5 freq:91
+  # PRED: 4 [10.0%]  (false,exec)
+  p.0_27 ();
+  # SUCC: 6 [100.0%]  (fallthru,exec)
+
+  # BLOCK 6 freq:909 count:1
+  # PRED: 4 [90.0%]  count:1 (true,exec) 5 [100.0%]  (fallthru,exec)
+  setp (&p, 2);
+  p.0_36 = p;
+  if (p.0_36 == a1)
+    goto <bb 8>;
+  else
+    goto <bb 7>;
+  # SUCC: 8 [90.0%]  count:1 (true,exec) 7 [10.0%]  (false,exec)
+
+  # BLOCK 7 freq:91
+  # PRED: 6 [10.0%]  (false,exec)
+  p.0_36 ();
+  # SUCC: 8 [100.0%]  (fallthru,exec)
+
+  # BLOCK 8 freq:909 count:1
+  # PRED: 6 [90.0%]  count:1 (true,exec) 7 [100.0%]  (fallthru,exec)
+  setp (&p, 3);
+  p.0_45 = p;
+  if (p.0_45 == a1)
+    goto <bb 10>;
+  else
+    goto <bb 9>;
+  # SUCC: 10 [90.0%]  count:1 (true,exec) 9 [10.0%]  (false,exec)
+
+  # BLOCK 9 freq:91
+  # PRED: 8 [10.0%]  (false,exec)
+  p.0_45 ();
+  # SUCC: 10 [100.0%]  (fallthru,exec)
+
+  # BLOCK 10 freq:909 count:1
+  # PRED: 8 [90.0%]  count:1 (true,exec) 9 [100.0%]  (fallthru,exec)
+  setp (&p, 4);
+  p.0_54 = p;
+  if (p.0_54 == a1)
+    goto <bb 12>;
+  else
+    goto <bb 11>;
+  # SUCC: 12 [90.0%]  count:1 (true,exec) 11 [10.0%]  (false,exec)
+
+  # BLOCK 11 freq:91
+  # PRED: 10 [10.0%]  (false,exec)
+  p.0_54 ();
+  # SUCC: 12 [100.0%]  (fallthru,exec)
+
+  # BLOCK 12 freq:909 count:1
+  # PRED: 10 [90.0%]  count:1 (true,exec) 11 [100.0%]  (fallthru,exec)
+  setp (&p, 5);
+  p.0_63 = p;
+  if (p.0_63 == a1)
+    goto <bb 14>;
+  else
+    goto <bb 13>;
+  # SUCC: 14 [90.0%]  count:1 (true,exec) 13 [10.0%]  (false,exec)
+
+  # BLOCK 13 freq:91
+  # PRED: 12 [10.0%]  (false,exec)
+  p.0_63 ();
+  # SUCC: 14 [100.0%]  (fallthru,exec)
+
+  # BLOCK 14 freq:909 count:1
+  # PRED: 12 [90.0%]  count:1 (true,exec) 13 [100.0%]  (fallthru,exec)
+  setp (&p, 6);
+  p.0_72 = p;
+  if (p.0_72 == a1)
+    goto <bb 16>;
+  else
+    goto <bb 15>;
+  # SUCC: 16 [90.0%]  count:1 (true,exec) 15 [10.0%]  (false,exec)
+
+  # BLOCK 15 freq:91
+  # PRED: 14 [10.0%]  (false,exec)
+  p.0_72 ();
+  # SUCC: 16 [100.0%]  (fallthru,exec)
+
+  # BLOCK 16 freq:909 count:1
+  # PRED: 14 [90.0%]  count:1 (true,exec) 15 [100.0%]  (fallthru,exec)
+  setp (&p, 7);
+  p.0_81 = p;
+  if (p.0_81 == a1)
+    goto <bb 18>;
+  else
+    goto <bb 17>;
+  # SUCC: 18 [90.0%]  count:1 (true,exec) 17 [10.0%]  (false,exec)
+
+  # BLOCK 17 freq:91
+  # PRED: 16 [10.0%]  (false,exec)
+  p.0_81 ();
+  # SUCC: 18 [100.0%]  (fallthru,exec)
+
+  # BLOCK 18 freq:909 count:1
+  # PRED: 16 [90.0%]  count:1 (true,exec) 17 [100.0%]  (fallthru,exec)
+  setp (&p, 8);
+  p.0_90 = p;
+  if (p.0_90 == a1)
+    goto <bb 20>;
+  else
+    goto <bb 19>;
+  # SUCC: 20 [90.0%]  count:1 (true,exec) 19 [10.0%]  (false,exec)
+
+  # BLOCK 19 freq:91
+  # PRED: 18 [10.0%]  (false,exec)
+  p.0_90 ();
+  # SUCC: 20 [100.0%]  (fallthru,exec)
+
+  # BLOCK 20 freq:909 count:1
+  # PRED: 18 [90.0%]  count:1 (true,exec) 19 [100.0%]  (fallthru,exec)
+  setp (&p, 9);
+  p.0_3 = p;
+  if (p.0_3 == a1)
+    goto <bb 22>;
+  else
+    goto <bb 21>;
+  # SUCC: 22 [90.0%]  count:1 (true,exec) 21 [10.0%]  (false,exec)
+
+  # BLOCK 21 freq:91
+  # PRED: 20 [10.0%]  (false,exec)
+  p.0_3 ();
+  # SUCC: 22 [100.0%]  (fallthru,exec)
+
+  # BLOCK 22 freq:909 count:1
+  # PRED: 21 [100.0%]  (fallthru,exec) 20 [90.0%]  count:1 (true,exec)
+  return 0;
+  # SUCC: EXIT [100.0%]  count:1
+
+}
+
+
Index: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.c	(revision 0)
@@ -0,0 +1,43 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+
+static int a1 (void)
+{
+    return 10;
+}
+
+static int a2 (void)
+{
+    return 0;
+}
+
+typedef int (*tp) (void);
+
+static tp aa [] = {a2, a1, a1, a1, a1};
+
+__attribute__((noinline)) void setp (int (**pp) (void), int i)
+{
+  if (!i)
+    *pp = aa [i];
+  else
+    *pp = aa [(i & 2) + 1];
+}
+
+int
+main (void)
+{
+  int (*p) (void);
+  int  i;
+
+  for (i = 0; i < 10; i ++)
+    {
+	setp (&p, i);
+	p ();
+    }
+  
+  return 0;
+}
+
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* a1" "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: testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-1.c	(revision 0)
@@ -0,0 +1,22 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+int a[1000];
+int b = 256;
+int c = 257;
+main ()
+{
+  int i;
+  int n;
+  for (i = 0; i < 1000; i++)
+    {
+      if (i % 17)
+	n = c;
+      else n = b;
+      a[i] /= n;
+    }
+  return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/wcoverage-mismatch.c	(revision 0)
@@ -0,0 +1,20 @@ 
+/* { dg-options "-O2 -Wno-coverage-mismatch" } */
+
+int __attribute__((noinline)) bar (void)
+{
+}
+
+int foo (int i)
+{
+#ifdef _PROFILE_USE
+  if (i)
+    bar ();
+#endif
+  return 0;
+}
+
+int main(int argc, char **argv)
+{
+  foo (argc);
+  return 0;
+}
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-2.c	(revision 0)
@@ -0,0 +1,32 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+unsigned int a[1000];
+unsigned int b = 256;
+unsigned int c = 1024;
+unsigned int d = 17;
+main ()
+{
+  int i;
+  unsigned int n;
+  for (i = 0; i < 1000; i++)
+    {
+	    a[i]=100*i;
+    }
+  for (i = 0; i < 1000; i++)
+    {
+      if (i % 2)
+	n = b;
+      else if (i % 3)
+	n = c;
+      else
+	n = d;
+      a[i] %= n;
+    }
+  return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/pr45354.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/pr45354.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/pr45354.c	(revision 0)
@@ -0,0 +1,43 @@ 
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O -freorder-blocks-and-partition -fschedule-insns -fselective-scheduling" { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
+
+extern void abort (void);
+
+int ifelse_val2;
+
+int __attribute__((noinline))
+test_ifelse2 (int i)
+{
+  int result = 0;
+  if (!i)				/* count(6) */
+    result = 1;				/* count(1) */
+  if (i == 1)				/* count(6) */
+    result = 1024;
+  if (i == 2)				/* count(6) */
+    result = 2;				/* count(3) */
+  if (i == 3)				/* count(6) */
+    return 8;				/* count(2) */
+  if (i == 4)				/* count(4) */
+    return 2048;
+  return result;			/* count(4) */
+}
+
+void __attribute__((noinline))
+call_ifelse ()
+{
+  ifelse_val2 += test_ifelse2 (0);
+  ifelse_val2 += test_ifelse2 (2);
+  ifelse_val2 += test_ifelse2 (2);
+  ifelse_val2 += test_ifelse2 (2);
+  ifelse_val2 += test_ifelse2 (3);
+  ifelse_val2 += test_ifelse2 (3);
+}
+
+int
+main()
+{
+  call_ifelse ();
+  if (ifelse_val2 != 23)
+    abort ();
+  return 0;
+}
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-3.c	(revision 0)
@@ -0,0 +1,32 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+unsigned int a[1000];
+unsigned int b = 257;
+unsigned int c = 1023;
+unsigned int d = 19;
+main ()
+{
+  int i;
+  unsigned int n;
+  for (i = 0; i < 1000; i++)
+    {
+	    a[i]=18;
+    }
+  for (i = 0; i < 1000; i++)
+    {
+      if (i % 2)
+	n = b;
+      else if (i % 3)
+	n = c;
+      else
+	n = d;
+      a[i] %= n;
+    }
+  return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-4.c	(revision 0)
@@ -0,0 +1,32 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+unsigned int a[1000];
+unsigned int b = 999;
+unsigned int c = 1002;
+unsigned int d = 1003;
+main ()
+{
+  int i;
+  unsigned int n;
+  for (i = 0; i < 1000; i++)
+    {
+	    a[i]=1000+i;
+    }
+  for (i = 0; i < 1000; i++)
+    {
+      if (i % 2)
+	n = b;
+      else if (i % 3)
+	n = c;
+      else
+	n = d;
+      a[i] %= n;
+    }
+  return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-5.c	(revision 0)
@@ -0,0 +1,17 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+int a[1000];
+int b=997;
+main()
+{
+	int i;
+	for (i = 0; i < 1000; i++)
+		if (a[i])
+			a[i]/=b;
+		else
+			a[i]/=b;
+	return 0;
+}
+/* { 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-ipa-dump "tree_profile_ipa" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-6.c	(revision 0)
@@ -0,0 +1,20 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+char a[1000];
+char b[1000];
+int size=1000;
+__attribute__ ((noinline))
+t(int size)
+{
+  __builtin_memcpy(a,b,size);
+}
+int
+main()
+{
+  int i;
+  for (i=0; i < size; i++)
+    t(i);
+  return 0;
+}
+/* { dg-final-use { scan-tree-dump "Average value sum:499500" "optimized"} } */
+/* { dg-final-use { scan-tree-dump "IOR value" "optimized"} } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/val-prof-7.c	(revision 0)
@@ -0,0 +1,26 @@ 
+/* { dg-options "-O2 -fdump-ipa-tree_profile_ipa -mtune=core2" } */
+/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
+
+#include <strings.h>
+
+int foo(int len)
+{
+  char array[1000];
+  bzero(array, len);
+  return 0;
+}
+
+int main() {
+  int i;
+  for (i = 0; i < 1000; i++)
+    {
+      if (i > 990)
+	foo(16);
+      else
+	foo(8);
+    }
+  return 0;
+}
+
+/* { 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: testsuite/gcc.dg/tree-prof/lipo/indir-call-prof.gcda.imports
===================================================================
Index: testsuite/gcc.dg/tree-prof/lipo/pr47187.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/pr47187.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/pr47187.c	(revision 0)
@@ -0,0 +1,23 @@ 
+/* PR bootstrap/47187 */
+/* { dg-options "-O2" } */
+
+char buf[64];
+char buf2[64];
+
+void *
+foo (char *p, long size)
+{
+  return __builtin_memcpy (buf, p, size);
+}
+
+int
+main (void)
+{
+  long i;
+  for (i = 0; i < 65536; i++)
+    if (foo ("abcdefghijkl", 12) != buf)
+      __builtin_abort ();
+  if (foo (buf2, 64) != buf)
+    __builtin_abort ();
+  return 0;
+}
Index: testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c
===================================================================
--- testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c	(revision 0)
+++ testsuite/gcc.dg/tree-prof/lipo/update-cunroll-2.c	(revision 0)
@@ -0,0 +1,21 @@ 
+
+/* { dg-options "-O2 -fdump-tree-optimized-blocks" } */
+int a[8];
+__attribute__ ((noinline))
+int t()
+{
+	int i;
+	for (i = 0; i < 3; i++)
+		if (a[i])
+			break;
+	return i;
+}
+main ()
+{
+  int i;
+  for (i = 0; i < 1000; i++)
+    t ();
+  return 0;
+}
+/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
+/* { dg-final-use { cleanup-tree-dump "optimized" } } */
Index: testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/inline_mismatch_args.C	(revision 0)
@@ -0,0 +1,36 @@ 
+/* { dg-options "-O2 -fdump-tree-einline" } */
+class DocId {
+ public:
+ DocId() { }
+ DocId(const DocId &other) {  }
+};
+
+int g;
+class Base {
+ public:
+ virtual void Foo(DocId id) { g++; }
+};
+
+class Super: public Base {
+ public:
+ void Foo(DocId id) { }
+ void Bar(Base *base, DocId id) __attribute__((noinline));
+};
+
+void Super::Bar(Base *base, DocId id) {
+ Super::Foo(id); // direct call is inlined
+ base->Foo(id); // indirect call is marked do not inline
+}
+
+int main(void)
+{
+ Base bah;
+ Super baz;
+ DocId gid;
+
+ baz.Bar(&baz, gid);
+ return 0;
+}
+/* { dg-final-use { scan-tree-dump "Inlining .*Super::Foo" "einline" } } */
+/* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline" } } */
+/* { dg-final-use { cleanup-tree-dump "einline" } } */
Index: testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/indir-call-prof-2.C	(revision 0)
@@ -0,0 +1,35 @@ 
+/* { dg-options "-O" } */
+
+int foo1(void) { return 0; }
+int bar1(void) { throw 1; }
+void foo2(void) { }
+void bar2(void) { throw 1; }
+void __attribute__((noinline,noclone)) test1(void (*f)(void)) { (*f)(); }
+void __attribute__((noinline,noclone)) test2(void (*f)(void)) { (*f)(); }
+int __attribute__((noinline,noclone)) test3(int (*f)(void)) { return (*f)(); }
+int __attribute__((noinline,noclone)) test4(int (*f)(void)) { return (*f)(); }
+int __attribute__((noinline,noclone)) test5(int (*f)(void), int x) { return x ? x : (*f)(); }
+int __attribute__((noinline,noclone)) test6(int (*f)(void), int x) { return x ? x : (*f)(); }
+void __attribute__((noinline,noclone)) test7(void (*f)(void)) { try { (*f)(); } catch (...) {} }
+void __attribute__((noinline,noclone)) test8(void (*f)(void)) { try { (*f)();  } catch (...) {}}
+int __attribute__((noinline,noclone)) test9(int (*f)(void)) { try { return (*f)(); } catch (...) {return 0;} }
+int __attribute__((noinline,noclone)) test10(int (*f)(void)) { try { return (*f)(); } catch (...) {return 0;} }
+int __attribute__((noinline,noclone)) test11(int (*f)(void), int x) { try { return x ? x : (*f)(); } catch (...) {return 0;} }
+int __attribute__((noinline,noclone)) test12(int (*f)(void), int x) { try { return x ? x : (*f)(); } catch (...) {return 0;} }
+
+int main()
+{
+  for (int i = 0; i < 100; ++i) test1(foo2);
+  for (int i = 0; i < 100; ++i) try { test2(bar2); } catch (...) {} 
+  for (int i = 0; i < 100; ++i) test3(foo1);
+  for (int i = 0; i < 100; ++i) try { test4(bar1); } catch (...) {} 
+  for (int i = 0; i < 100; ++i) test5(foo1, 0);
+  for (int i = 0; i < 100; ++i) try { test6(bar1, 0); } catch (...) {} 
+  for (int i = 0; i < 100; ++i) test7(foo2);
+  for (int i = 0; i < 100; ++i) try { test8(bar2); } catch (...) {} 
+  for (int i = 0; i < 100; ++i) test9(foo1);
+  for (int i = 0; i < 100; ++i) try { test10(bar1); } catch (...) {} 
+  for (int i = 0; i < 100; ++i) test11(foo1, 0);
+  for (int i = 0; i < 100; ++i) try { test12(bar1, 0); } catch (...) {} 
+  return 0;
+}
Index: testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/indir-call-prof.C	(revision 0)
@@ -0,0 +1,39 @@ 
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-ipa-tree_profile_ipa" } */
+
+struct A {
+  A () {}
+
+  virtual int AA (void)
+  { return 0; }
+
+};
+
+struct B : public A {
+  B () {}
+
+  virtual int AA (void)
+  { return 1; }
+};
+
+void * __attribute__((noinline,noclone)) wrap (void *p) { return p; }
+int
+main (void)
+{
+  A a;
+  B b;
+  
+  A* p;
+
+  p = (A *)wrap ((void *)&a);
+  p->AA ();
+
+  p = (B *)wrap ((void *)&b);
+  p->AA ();
+  
+  return 0;
+}
+
+/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call.* AA " "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: testsuite/g++.dg/tree-prof/lipo/partition1.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/partition1.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/partition1.C	(revision 0)
@@ -0,0 +1,54 @@ 
+/* { dg-require-effective-target freorder } */
+/* { dg-options "-O2 -freorder-blocks-and-partition" } */
+/* { dg-skip-if "PR target/47683" { mips-sgi-irix* } } */
+
+struct A { A () __attribute__((noinline)); ~A () __attribute__((noinline)); };
+A::A () { asm volatile ("" : : : "memory"); }
+A::~A () { asm volatile ("" : : : "memory"); }
+
+int bar () __attribute__((noinline));
+void foo () __attribute__((noinline));
+
+volatile int k, l;
+
+int bar (int i)
+{
+  void *p = __builtin_alloca (i);
+  asm volatile ("" : : "r" (i), "r" (p) : "memory");
+  if (k) throw 6;
+  return ++l;
+}
+
+void foo ()
+{
+  A a;
+  try {
+    A b;
+    int i = bar (5);
+    try { throw 6; } catch (int) {}
+    if (__builtin_expect (i < 4500, 0)) {
+      bar (7);
+      try { bar (8); } catch (long) {}
+      bar (10);
+      if (__builtin_expect (i < 0, 0)) {
+	try { bar (12); } catch (...) {}
+	bar (16);
+	bar (122);
+      } else {
+	try { bar (bar (7)); } catch (int) {}
+      }
+    } else {
+      try { bar (bar (bar (9))); } catch (...) {}
+      bar (5);
+    }
+  } catch (...) {
+  }
+}
+
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 10000; i++)
+    foo ();
+}
Index: testsuite/g++.dg/tree-prof/lipo/partition2.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/partition2.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/partition2.C	(revision 0)
@@ -0,0 +1,16 @@ 
+// PR middle-end/45458
+// { dg-require-effective-target freorder }
+// { dg-options "-fnon-call-exceptions -freorder-blocks-and-partition" }
+// { dg-skip-if "PR target/47683" { mips-sgi-irix* } }
+
+int
+main ()
+{
+  try
+  {
+    throw 6;
+  }
+  catch (...)
+  {
+  }
+}
Index: testsuite/g++.dg/tree-prof/lipo/partition3.C
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/partition3.C	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/partition3.C	(revision 0)
@@ -0,0 +1,18 @@ 
+// PR middle-end/45566
+// { dg-require-effective-target freorder }
+// { dg-options "-O -fnon-call-exceptions -freorder-blocks-and-partition" }
+
+int k;
+
+int
+main ()
+{
+  try
+  {
+    if (k)
+      throw 6;
+  }
+  catch (...)
+  {
+  }
+}
Index: testsuite/g++.dg/tree-prof/lipo/lipo.exp
===================================================================
--- testsuite/g++.dg/tree-prof/lipo/lipo.exp	(revision 0)
+++ testsuite/g++.dg/tree-prof/lipo/lipo.exp	(revision 0)
@@ -0,0 +1,54 @@ 
+# Copyright (C) 2001, 2002, 2004, 2005, 2007, 2008
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Test the functionality of programs compiled with profile-directed block
+# ordering using -fprofile-generate followed by -fprofile-use.
+
+load_lib target-supports.exp
+
+# Some targets don't support tree profiling.
+if { ![check_profiling_available ""] } {
+    return
+}
+
+# The procedures in profopt.exp need these parameters.
+set tool g++
+set prof_ext "gcda"
+
+# Override the list defined in profopt.exp.
+set PROFOPT_OPTIONS [list {}]
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Load support procs.
+load_lib profopt.exp
+
+# These are globals used by profopt-execute.  The first is options
+# needed to generate profile data, the second is options to use the
+# profile data.
+set profile_option "-fprofile-generate -fripa"
+set feedback_option "-fprofile-use -fripa"
+
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.C]] {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+        continue
+    }
+    profopt-execute $src
+}
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 173136)
+++ dwarf2out.c	(working copy)
@@ -4184,9 +4184,9 @@  dwarf2out_vms_end_prologue (unsigned int
   /* Output a label to mark the endpoint of the code generated for this
      function.  */
   ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
-			       current_function_funcdef_no);
+			       FUNC_LABEL_ID (cfun));
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, PROLOGUE_END_LABEL,
-			  current_function_funcdef_no);
+			  FUNC_LABEL_ID (cfun));
   fde = &fde_table[fde_table_in_use - 1];
   fde->dw_fde_vms_end_prologue = xstrdup (label);
 }
@@ -4209,9 +4209,9 @@  dwarf2out_vms_begin_epilogue (unsigned i
   /* Output a label to mark the endpoint of the code generated for this
      function.  */
   ASM_GENERATE_INTERNAL_LABEL (label, EPILOGUE_BEGIN_LABEL,
-			       current_function_funcdef_no);
+			       FUNC_LABEL_ID (cfun));
   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, EPILOGUE_BEGIN_LABEL,
-			  current_function_funcdef_no);
+			  FUNC_LABEL_ID (cfun));
   fde->dw_fde_vms_begin_epilogue = xstrdup (label);
 }
 
@@ -17918,7 +17918,7 @@  dwarf2out_vms_debug_main_pointer (void)
   die->die_tag = DW_TAG_subprogram;
   add_name_attribute (die, VMS_DEBUG_MAIN_POINTER);
   ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
-			       current_function_funcdef_no);
+			       FUNC_LABEL_ID (cfun));
   add_AT_lbl_id (die, DW_AT_entry_pc, label);
 
   /* Make it the first child of comp_unit_die ().  */
Index: tree-profile.c
===================================================================
--- tree-profile.c	(revision 173136)
+++ tree-profile.c	(working copy)
@@ -473,7 +473,6 @@  gimple_gen_ic_func_profiler (void)
 static void
 gimple_gen_ic_func_topn_profiler (void)
 {
-  struct cgraph_node * c_node = cgraph_node (current_function_decl);
   gimple_stmt_iterator gsi;
   gimple stmt1;
   tree cur_func, gcov_info, cur_func_id;
@@ -483,16 +482,6 @@  gimple_gen_ic_func_topn_profiler (void)
       || DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (current_function_decl))
     return;
 
-  /* We want to make sure template functions are instrumented even though
-     it is not 'needed' in this module. It is possible that the function
-     is needed (e.g, as icall target) in another module. Note that for
-     functions in comdat groups, there is no guarantee which copy will be
-     picked up by the linker.  */
-
-  if (!c_node->needed
-      && (!c_node->reachable || !DECL_COMDAT (c_node->decl)))
-    return;
-
   gimple_init_edge_profiler ();
 
   gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
@@ -659,6 +648,7 @@  tree_profiling (void)
   /* Now perform link to allow cross module inlining.  */
   cgraph_do_link ();
   varpool_do_link ();
+  cgraph_unify_type_alias_sets ();
 
   init_node_map();
 
Index: l-ipo.c
===================================================================
--- l-ipo.c	(revision 173136)
+++ l-ipo.c	(working copy)
@@ -42,7 +42,12 @@  struct GTY(()) saved_module_scope
 
 static GTY (()) struct saved_module_scope *current_module_scope;
 static GTY ((param_is (struct saved_module_scope))) htab_t saved_module_scope_map;
-static int primary_module_last_fundef_no = 0;
+static int primary_module_last_funcdef_no = 0;
+/* Function id space for each module are qualified by the module id. After all the files
+   are parsed, we need to reset the funcdef_no to the max value from all module so that
+   the function clones do not assigned with ids colliding with some other orignal function
+   in the same module.  */
+static int max_funcdef_no = 0;
 static location_t primary_module_last_loc;
 /* Primary module pending templates.  */
 /* Referenced asm ids in primary module.  */
@@ -348,7 +353,7 @@  restore_post_parsing_states (void)
 {
   current_module_id = primary_module_id;
   current_module_scope = get_module_scope (primary_module_id);
-  set_funcdef_no (primary_module_last_fundef_no);
+  set_funcdef_no (max_funcdef_no);
   input_location = primary_module_last_loc;
 
   restore_assembler_name_reference_bit ();
@@ -364,6 +369,8 @@  void
 pop_module_scope (void)
 {
   bool is_last = false;
+  int  last_funcdef_no;
+
   if (!flag_dyn_ipa || !L_IPO_COMP_MODE)
     return;
 
@@ -379,13 +386,17 @@  pop_module_scope (void)
 
   is_last = is_last_module (current_module_id);
 
+  last_funcdef_no = get_last_funcdef_no ();
+  if (last_funcdef_no > max_funcdef_no)
+    max_funcdef_no = last_funcdef_no;
+
   lang_hooks.l_ipo.save_built_in_decl_post_module_parsing ();
   /* Save primary module state if needed (when module group
      size > 1)  */
   if (L_IPO_IS_PRIMARY_MODULE && num_in_fnames > 1)
     {
       save_assembler_name_reference_bit ();
-      primary_module_last_fundef_no = get_last_funcdef_no ();
+      primary_module_last_funcdef_no = last_funcdef_no;
     }
 
   if (!is_last)
Index: gcov-dump.c
===================================================================
--- gcov-dump.c	(revision 173136)
+++ gcov-dump.c	(working copy)
@@ -326,14 +326,15 @@  tag_function (const char *filename ATTRI
 	      unsigned tag ATTRIBUTE_UNUSED, unsigned length)
 {
   unsigned long pos = gcov_position ();
-  const char *name;
 
   printf (" ident=%u", gcov_read_unsigned ());
   printf (", checksum=0x%08x", gcov_read_unsigned ());
-  name = gcov_read_string ();
-  printf (", `%s'", name ? name : "NULL");
   if (gcov_position () - pos < length)
     {
+      const char *name;
+
+      name = gcov_read_string ();
+      printf (", `%s'", name ? name : "NULL");
       name = gcov_read_string ();
       printf (" %s", name ? name : "NULL");
       printf (":%u", gcov_read_unsigned ());