diff mbox

Fix gimple_ic if adding a noreturn direct call variant to an indirect not noreturn call (PR tree-optimization/51719)

Message ID 20120102221403.GT18937@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 2, 2012, 10:14 p.m. UTC
Hi!

When gimple_ic is changing an indirect call into
if (cond)
  direct_call ();
else
  (*indirect_call) ()
and the indirect_call is not noreturn, but direct_call is
noreturn, we ICE during checking after profile, because the noreturn
call still has lhs set and edges that it shouldn't have.

The following patch fixes, it, bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk?

2012-01-02  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/51719
	* value-prof.c (gimple_ic): When indirect call isn't noreturn,
	but direct call is, clear direct call's lhs and don't add fallthrough
	edge from dcall_bb to join_bb and PHIs.

	* g++.dg/tree-prof/pr51719.C: New test.


	Jakub

Comments

Richard Biener Jan. 3, 2012, 8:54 a.m. UTC | #1
On Mon, 2 Jan 2012, Jakub Jelinek wrote:

> Hi!
> 
> When gimple_ic is changing an indirect call into
> if (cond)
>   direct_call ();
> else
>   (*indirect_call) ()
> and the indirect_call is not noreturn, but direct_call is
> noreturn, we ICE during checking after profile, because the noreturn
> call still has lhs set and edges that it shouldn't have.
> 
> The following patch fixes, it, bootstrapped/regtested on x86_64-linux
> and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2012-01-02  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/51719
> 	* value-prof.c (gimple_ic): When indirect call isn't noreturn,
> 	but direct call is, clear direct call's lhs and don't add fallthrough
> 	edge from dcall_bb to join_bb and PHIs.
> 
> 	* g++.dg/tree-prof/pr51719.C: New test.
> 
> --- gcc/value-prof.c.jj	2011-08-18 08:36:00.000000000 +0200
> +++ gcc/value-prof.c	2012-01-02 19:01:33.760867971 +0100
> @@ -1149,7 +1149,7 @@ gimple_ic (gimple icall_stmt, struct cgr
>    tree optype = build_pointer_type (void_type_node);
>    edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
>    gimple_stmt_iterator gsi;
> -  int lp_nr;
> +  int lp_nr, dflags;
>  
>    cond_bb = gimple_bb (icall_stmt);
>    gsi = gsi_for_stmt (icall_stmt);
> @@ -1176,6 +1176,9 @@ gimple_ic (gimple icall_stmt, struct cgr
>    update_stmt (icall_stmt);
>    dcall_stmt = gimple_copy (icall_stmt);
>    gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
> +  dflags = flags_from_decl_or_type (direct_call->decl);
> +  if ((dflags & ECF_NORETURN) != 0)
> +    gimple_call_set_lhs (dcall_stmt, NULL_TREE);
>    gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
>  
>    /* Fix CFG. */
> @@ -1220,17 +1223,23 @@ gimple_ic (gimple icall_stmt, struct cgr
>  
>    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;
> +      if ((dflags & ECF_NORETURN) != 0)
> +	e_ij->count = all;
> +      else
> +	{
> +	  e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
> +	  e_dj->probability = REG_BR_PROB_BASE;
> +	  e_dj->count = count;
>  
> +	  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)
> -      && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME)
> +      && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME
> +      && (dflags & ECF_NORETURN) == 0)
>      {
>        tree result = gimple_call_lhs (icall_stmt);
>        gimple phi = create_phi_node (result, join_bb);
> --- gcc/testsuite/g++.dg/tree-prof/pr51719.C.jj	2012-01-02 19:11:27.633358952 +0100
> +++ gcc/testsuite/g++.dg/tree-prof/pr51719.C	2012-01-02 19:12:27.797004399 +0100
> @@ -0,0 +1,27 @@
> +// PR tree-optimization/51719
> +// { dg-options "-O -fpartial-inlining" }
> +
> +int
> +bar (void)
> +{
> +  throw 1;
> +}
> +
> +int __attribute__ ((noinline, noclone))
> +foo (int (*f) (void))
> +{
> +  try
> +  {
> +    return (*f) ();
> +  }
> +  catch (...)
> +  {
> +  }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  return foo (bar);
> +}
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/value-prof.c.jj	2011-08-18 08:36:00.000000000 +0200
+++ gcc/value-prof.c	2012-01-02 19:01:33.760867971 +0100
@@ -1149,7 +1149,7 @@  gimple_ic (gimple icall_stmt, struct cgr
   tree optype = build_pointer_type (void_type_node);
   edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
   gimple_stmt_iterator gsi;
-  int lp_nr;
+  int lp_nr, dflags;
 
   cond_bb = gimple_bb (icall_stmt);
   gsi = gsi_for_stmt (icall_stmt);
@@ -1176,6 +1176,9 @@  gimple_ic (gimple icall_stmt, struct cgr
   update_stmt (icall_stmt);
   dcall_stmt = gimple_copy (icall_stmt);
   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
+  dflags = flags_from_decl_or_type (direct_call->decl);
+  if ((dflags & ECF_NORETURN) != 0)
+    gimple_call_set_lhs (dcall_stmt, NULL_TREE);
   gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
 
   /* Fix CFG. */
@@ -1220,17 +1223,23 @@  gimple_ic (gimple icall_stmt, struct cgr
 
   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;
+      if ((dflags & ECF_NORETURN) != 0)
+	e_ij->count = all;
+      else
+	{
+	  e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
+	  e_dj->probability = REG_BR_PROB_BASE;
+	  e_dj->count = count;
 
+	  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)
-      && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME)
+      && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME
+      && (dflags & ECF_NORETURN) == 0)
     {
       tree result = gimple_call_lhs (icall_stmt);
       gimple phi = create_phi_node (result, join_bb);
--- gcc/testsuite/g++.dg/tree-prof/pr51719.C.jj	2012-01-02 19:11:27.633358952 +0100
+++ gcc/testsuite/g++.dg/tree-prof/pr51719.C	2012-01-02 19:12:27.797004399 +0100
@@ -0,0 +1,27 @@ 
+// PR tree-optimization/51719
+// { dg-options "-O -fpartial-inlining" }
+
+int
+bar (void)
+{
+  throw 1;
+}
+
+int __attribute__ ((noinline, noclone))
+foo (int (*f) (void))
+{
+  try
+  {
+    return (*f) ();
+  }
+  catch (...)
+  {
+  }
+  return 0;
+}
+
+int
+main ()
+{
+  return foo (bar);
+}