On 1/29/20 12:46 PM, Jan Hubicka wrote:
Hi,
this fixes indirect call speculation ICE Martin (Liska) reduced from
spec GCC. The problem here was in resolve_speculation that if called to
resolve the second edge in multi-target speculative call resolved first
on instead. This is bug I did not catch during the API change.
Other problem is that redirect_call_stmt_to_callee if called from
inliner is called on direct part of speculative call while it expects
indirect. This is checking only failure but rahter than removing sanity
check I switch to indirect edge.
profiled-lto-bootstrapped x86_64-linux and comitted.
Thanks for the patch ...
Honza
2020-01-29 Jan Hubicka <hubi...@ucw.cz>
* cgraph.c (cgraph_edge::resolve_speculation): Only lookup direct edge
if called on indirect edge.
(cgraph_edge::redirect_call_stmt_to_callee): Lookup indirect edge of
speculative call if needed.
gcc/testsuite/ChangeLog:
2020-01-29 Jan Hubicka <hubi...@ucw.cz>
* gcc.dg/tree-prof/indir-call-prof-2.c: New testcase.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 3e50b0bc380..294b2d392fd 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1189,7 +1189,10 @@ cgraph_edge::resolve_speculation (cgraph_edge *edge,
tree callee_decl)
ipa_ref *ref;
gcc_assert (edge->speculative && (!callee_decl || edge->callee));
- e2 = edge->first_speculative_call_target ();
+ if (!edge->callee)
+ e2 = edge->first_speculative_call_target ();
+ else
+ e2 = edge;
ref = e2->speculative_call_target_ref ();
edge = edge->speculative_call_indirect_edge ();
if (!callee_decl
@@ -1364,7 +1367,8 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
/* If there already is an direct call (i.e. as a result of inliner's
substitution), forget about speculating. */
if (decl)
- e = make_direct (e, cgraph_node::get (decl));
+ e = make_direct (e->speculative_call_indirect_edge (),
+ cgraph_node::get (decl));
else
{
/* Be sure we redirect all speculative targets before poking
diff --git a/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-2.c
b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-2.c
index 61612b5b628..bbba0521018 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/indir-call-prof-2.c
This should be a new file.
@@ -1,25 +1,28 @@
/* { dg-options "-O2 -fno-early-inlining -fdump-ipa-profile-optimized
-fdump-ipa-afdo" } */
volatile int one;
-static
-int add1 (int val)
+static int
+add1 (int val)
{
- return val+=one;
+ return val += one;
}
-static
-int sub1 (int val)
+
+static int
+sub1 (int val)
{
- return val-=one;
+ return val -= one;
}
-static
-int do_op (int val, int (*fnptr) (int))
+
+static int
+do_op (int val, int (*fnptr) (int))
{
return fnptr (val);
}
+
int
-main(void)
+main (void)
{
- int i,val;
- for (i=0;i<100000;i++)
+ int i, val = 0;
+ for (i = 0; i < 100000; i++)
{
val = do_op (val, add1);
val = do_op (val, sub1);
diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c
... and this should not be installed.
Martin
index 19b8ee72ae9..801037d0d64 100644
--- a/libgcc/libgcov-merge.c
+++ b/libgcc/libgcov-merge.c
@@ -115,7 +115,7 @@ merge_topn_values_set (gcov_type *counters)
continue;
unsigned j;
- int slot = -1;
+ int slot = 0;
for (j = 0; j < GCOV_TOPN_VALUES; j++)
{
@@ -124,24 +124,15 @@ merge_topn_values_set (gcov_type *counters)
counters[2 * j + 1] += read_counters[2 * i + 1];
break;
}
- else if (counters[2 * j + 1] == 0)
+ if (counters[2 * j + 1] < counters[2 * slot + 1])
slot = j;
}
- if (j == GCOV_TOPN_VALUES)
+ if (j == GCOV_TOPN_VALUES
+ && counters[2 * slot + 1] < read_counters[2 * i + 1])
{
- if (slot > 0)
- {
- /* If we found empty slot, add the value. */
- counters[2 * slot] = read_counters[2 * i];
- counters[2 * slot + 1] = read_counters[2 * i + 1];
- }
- else
- {
- /* We haven't found a slot, bail out. */
- counters[1] = -1;
- return;
- }
+ counters[2 * slot] = read_counters[2 * i];
+ counters[2 * slot + 1] = read_counters[2 * i + 1];
}
}
}