This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix -fprofile-use optimization of a noreturn indirect call (PR gcov-profile/49299)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 6 Jun 2011 19:58:20 +0200
- Subject: [PATCH] Fix -fprofile-use optimization of a noreturn indirect call (PR gcov-profile/49299)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
When an indirect noreturn call has a likely call target, value-prof.c
ICEs on it, as there is no fallthru edge after the call (nor a join bb).
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk/4.6?
2011-06-06 Jakub Jelinek <jakub@redhat.com>
PR gcov-profile/49299
* value-prof.c (gimple_ic): Don't assume icall has
a fallthru edge.
* gcc.dg/tree-prof/pr49299-1.c: New test.
* gcc.dg/tree-prof/pr49299-2.c: New test.
--- gcc/value-prof.c.jj 2011-05-02 18:39:28.000000000 +0200
+++ gcc/value-prof.c 2011-06-06 12:37:30.000000000 +0200
@@ -1145,9 +1145,9 @@ gimple_ic (gimple icall_stmt, struct cgr
{
gimple dcall_stmt, load_stmt, cond_stmt;
tree tmp0, tmp1, tmpv, tmp;
- basic_block cond_bb, dcall_bb, icall_bb, join_bb;
+ basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL;
tree optype = build_pointer_type (void_type_node);
- edge e_cd, e_ci, e_di, e_dj, e_ij;
+ edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
gimple_stmt_iterator gsi;
int lp_nr;
@@ -1194,12 +1194,19 @@ gimple_ic (gimple icall_stmt, struct cgr
else
{
e_ij = find_fallthru_edge (icall_bb->succs);
- e_ij->probability = REG_BR_PROB_BASE;
- e_ij->count = all - count;
- e_ij = single_pred_edge (split_edge (e_ij));
+ /* The indirect call might be noreturn. */
+ if (e_ij != NULL)
+ {
+ e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->count = all - count;
+ e_ij = single_pred_edge (split_edge (e_ij));
+ }
+ }
+ if (e_ij != NULL)
+ {
+ join_bb = e_ij->dest;
+ join_bb->count = all;
}
- join_bb = e_ij->dest;
- join_bb->count = all;
e_cd->flags = (e_cd->flags & ~EDGE_FALLTHRU) | EDGE_TRUE_VALUE;
e_cd->probability = prob;
@@ -1211,12 +1218,15 @@ gimple_ic (gimple icall_stmt, struct cgr
remove_edge (e_di);
- e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
- e_dj->probability = REG_BR_PROB_BASE;
- e_dj->count = count;
+ if (e_ij != NULL)
+ {
+ e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
+ e_dj->probability = REG_BR_PROB_BASE;
+ e_dj->count = count;
- e_ij->probability = REG_BR_PROB_BASE;
- e_ij->count = all - count;
+ e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->count = all - count;
+ }
/* Insert PHI node for the call result if necessary. */
if (gimple_call_lhs (icall_stmt)
--- gcc/testsuite/gcc.dg/tree-prof/pr49299-1.c.jj 2011-06-06 11:34:58.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-prof/pr49299-1.c 2011-06-06 11:34:51.000000000 +0200
@@ -0,0 +1,34 @@
+/* { dg-options "-O2" } */
+
+__attribute__((noreturn)) void (*fn) (void);
+
+volatile int v;
+
+__attribute__((noreturn)) void
+fn0 (void)
+{
+ __builtin_exit (0);
+}
+
+__attribute__((noreturn)) void
+fn1 (void)
+{
+ __builtin_exit (1);
+}
+
+__attribute__((noinline, noclone)) void
+setfn (__attribute__((noreturn)) void (*x) (void))
+{
+ fn = x;
+}
+
+int
+main ()
+{
+ int i;
+ if (v < 1)
+ setfn (fn0);
+ else
+ setfn (fn1);
+ fn ();
+}
--- gcc/testsuite/gcc.dg/tree-prof/pr49299-2.c.jj 2011-06-06 12:46:25.000000000 +0200
+++ gcc/testsuite/gcc.dg/tree-prof/pr49299-2.c 2011-06-06 12:39:15.000000000 +0200
@@ -0,0 +1,34 @@
+/* { dg-options "-O2" } */
+
+void (*fn) (void);
+
+volatile int v;
+
+__attribute__((noreturn)) void
+fn0 (void)
+{
+ __builtin_exit (0);
+}
+
+void
+fn1 (void)
+{
+}
+
+__attribute__((noinline, noclone)) void
+setfn (void (*x) (void))
+{
+ fn = x;
+}
+
+int
+main ()
+{
+ int i;
+ if (v < 1)
+ setfn (fn0);
+ else
+ setfn (fn1);
+ fn ();
+ return 0;
+}
Jakub