===================================================================
@@ -869,6 +869,14 @@ DEFPARAM (PARAM_LOOP_INVARIANT_MAX_BBS_I
"Max basic blocks number in loop for loop invariant motion",
10000, 0, 0)
+/* When the parameter is 1, use the internal function id
+ to look up for profile data. Otherwise, use a more stable
+ external id based on assembler name and source location. */
+DEFPARAM (PARAM_PROFILE_FUNC_INTERNAL_ID,
+ "profile-func-internal-id",
+ "use internal function id in profile lookup",
+ 0, 0, 1)
+
/* Avoid SLP vectorization of large basic blocks. */
DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
"slp-max-insns-in-bb",
===================================================================
@@ -1,3 +1,10 @@
+2014-07-16 Xinliang David Li <davidxl@google.com>
+
+ * params.def: New parameter.
+ * coverage.c (get_coverage_counts): Check new flag.
+ (coverage_compute_profile_id): Check new flag.
+ (coverage_begin_function): Check new flag.
+
2014-07-16 Dodji Seketeli <dodji@redhat.com>
Support location tracking for built-in macro tokens
===================================================================
@@ -1,3 +1,11 @@
+2014-07-16 Xinliang David Li <davidxl@google.com>
+
+ * g++.dg/tree-prof/tree-prof.exp: Define macros.
+ * g++.dg/tree-prof/reorder_class1.h: New file.
+ * g++.dg/tree-prof/reorder_class2.h: New file.
+ * g++.dg/tree-prof/reorder.C: New test.
+ * g++.dg/tree-prof/morefunc.C: New test.
+
2014-07-16 Arnaud Charlet <charlet@adacore.com>
* gnat.db/specs/alignment2.ads, gnat.db/specs/size_clause1.ads,
===================================================================
@@ -0,0 +1,48 @@
+/* { dg-options "-O2 -fno-devirtualize --param=profile-func-internal-id=0 -fdump-ipa-profile -Wno-coverage-mismatch -Wno-attributes" } */
+
+#ifdef _PROFILE_USE
+#include "reorder_class1.h"
+#include "reorder_class2.h"
+#else
+#include "reorder_class2.h"
+#include "reorder_class1.h"
+#endif
+
+int g;
+static __attribute__((always_inline))
+void test1 (A *tc)
+{
+ int i;
+ for (i = 0; i < 1000; i++)
+ g += tc->foo();
+ if (g<100) g++;
+}
+
+static __attribute__((always_inline))
+void test2 (B *tc)
+{
+ int i;
+ for (i = 0; i < 1000; i++)
+ g += tc->foo();
+}
+
+
+#ifdef _PROFILE_USE
+__attribute__((noinline)) void test_a(A *ap) { test1 (ap); }
+__attribute__((noinline)) void test_b(B *bp) { test2 (bp); }
+#else
+__attribute__((noinline)) void test_b(B *bp) { test2 (bp); }
+__attribute__((noinline)) void test_a(A *ap) { test1 (ap); }
+#endif
+
+int main()
+{
+ A* ap = new A();
+ B* bp = new B();
+
+ test_a(ap);
+ test_b(bp);
+}
+
+/* { dg-final-use { scan-ipa-dump-times "Indirect call -> direct call" 2 "profile" } } */
+
===================================================================
@@ -42,8 +42,8 @@ set PROFOPT_OPTIONS [list {}]
# 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"
-set feedback_option "-fprofile-use"
+set profile_option "-fprofile-generate -D_PROFILE_GENERATE"
+set feedback_option "-fprofile-use -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.
===================================================================
@@ -0,0 +1,11 @@
+struct A {
+ virtual int foo();
+};
+
+int A::foo()
+{
+ return 1;
+}
+
+
+
===================================================================
@@ -0,0 +1,12 @@
+
+struct B {
+ virtual int foo();
+};
+
+int B::foo()
+{
+ return 2;
+}
+
+
+
===================================================================
@@ -0,0 +1,55 @@
+/* { dg-options "-O2 -fno-devirtualize --param=profile-func-internal-id=0 -fdump-ipa-profile -Wno-attributes -Wno-coverage-mismatch" } */
+#include "reorder_class1.h"
+#include "reorder_class2.h"
+
+int g;
+
+#ifdef _PROFILE_USE
+/* Another function not existing
+ * in profile-gen */
+
+__attribute__((noinline)) void
+new_func (int i)
+{
+ g += i;
+}
+#endif
+
+static __attribute__((always_inline))
+void test1 (A *tc)
+{
+ int i;
+ for (i = 0; i < 1000; i++)
+ g += tc->foo();
+ if (g<100) g++;
+}
+
+static __attribute__((always_inline))
+void test2 (B *tc)
+{
+ int i;
+ for (i = 0; i < 1000; i++)
+ g += tc->foo();
+}
+
+
+__attribute__((noinline)) void test_a(A *ap) { test1 (ap); }
+__attribute__((noinline)) void test_b(B *bp) { test2 (bp); }
+
+
+int main()
+{
+ A* ap = new A();
+ B* bp = new B();
+
+ test_a(ap);
+ test_b(bp);
+
+#ifdef _PROFILE_USE
+ new_func(10);
+#endif
+
+}
+
+/* { dg-final-use { scan-ipa-dump-times "Indirect call -> direct call" 2 "profile" } } */
+
===================================================================
@@ -1210,7 +1210,17 @@ gimple_mod_subtract_transform (gimple_st
return true;
}
-static pointer_map_t *cgraph_node_map;
+static pointer_map_t *cgraph_node_map = 0;
+
+/* Returns true if node graph is initialized. This
+ is used to test if profile_id has been created
+ for cgraph_nodes. */
+
+bool
+coverage_node_map_initialized_p (void)
+{
+ return cgraph_node_map != 0;
+}
/* Initialize map from PROFILE_ID to CGRAPH_NODE.
When LOCAL is true, the PROFILE_IDs are computed. when it is false we assume
@@ -1223,8 +1233,7 @@ init_node_map (bool local)
cgraph_node_map = pointer_map_create ();
FOR_EACH_DEFINED_FUNCTION (n)
- if (cgraph_function_with_gimple_body_p (n)
- && !cgraph_only_called_directly_p (n))
+ if (cgraph_function_with_gimple_body_p (n))
{
void **val;
if (local)
===================================================================
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.
#include "intl.h"
#include "filenames.h"
#include "target.h"
+#include "params.h"
#include "gcov-io.h"
#include "gcov-io.c"
@@ -369,8 +370,13 @@ get_coverage_counts (unsigned counter, u
da_file_name);
return NULL;
}
-
- elt.ident = current_function_funcdef_no + 1;
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ elt.ident = current_function_funcdef_no + 1;
+ else
+ {
+ gcc_assert (coverage_node_map_initialized_p ());
+ elt.ident = cgraph_get_node (cfun->decl)->profile_id;
+ }
elt.ctr = counter;
entry = counts_hash->find (&elt);
if (!entry || !entry->summary.num)
@@ -416,7 +422,8 @@ get_coverage_counts (unsigned counter, u
}
else if (entry->lineno_checksum != lineno_checksum)
{
- warning (0, "source locations for function %qE have changed,"
+ warning (OPT_Wcoverage_mismatch,
+ "source locations for function %qE have changed,"
" the profile data may be out of date",
DECL_ASSEMBLER_NAME (current_function_decl));
}
@@ -581,12 +588,13 @@ coverage_compute_profile_id (struct cgra
{
expanded_location xloc
= expand_location (DECL_SOURCE_LOCATION (n->decl));
+ bool use_name_only = (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID) == 0);
- chksum = xloc.line;
+ chksum = (use_name_only ? 0 : xloc.line);
chksum = coverage_checksum_string (chksum, xloc.file);
chksum = coverage_checksum_string
(chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
- if (first_global_object_name)
+ if (!use_name_only && first_global_object_name)
chksum = coverage_checksum_string
(chksum, first_global_object_name);
chksum = coverage_checksum_string
@@ -645,7 +653,15 @@ coverage_begin_function (unsigned lineno
/* Announce function */
offset = gcov_write_tag (GCOV_TAG_FUNCTION);
- gcov_write_unsigned (current_function_funcdef_no + 1);
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ gcov_write_unsigned (current_function_funcdef_no + 1);
+ else
+ {
+ gcc_assert (coverage_node_map_initialized_p ());
+ gcov_write_unsigned (
+ cgraph_get_node (current_function_decl)->profile_id);
+ }
+
gcov_write_unsigned (lineno_checksum);
gcov_write_unsigned (cfg_checksum);
gcov_write_string (IDENTIFIER_POINTER
@@ -682,8 +698,15 @@ coverage_end_function (unsigned lineno_c
if (!DECL_EXTERNAL (current_function_decl))
{
item = ggc_alloc<coverage_data> ();
-
- item->ident = current_function_funcdef_no + 1;
+
+ if (PARAM_VALUE (PARAM_PROFILE_FUNC_INTERNAL_ID))
+ item->ident = current_function_funcdef_no + 1;
+ else
+ {
+ gcc_assert (coverage_node_map_initialized_p ());
+ item->ident = cgraph_get_node (cfun->decl)->profile_id;
+ }
+
item->lineno_checksum = lineno_checksum;
item->cfg_checksum = cfg_checksum;
===================================================================
@@ -56,5 +56,6 @@ extern gcov_type *get_coverage_counts (u
const struct gcov_ctr_summary **);
extern tree get_gcov_type (void);
+extern bool coverage_node_map_initialized_p (void);
#endif