diff mbox

Fix normal -> noreturn call transformation in PRE (PR tree-optimization/46165)

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

Commit Message

Jakub Jelinek Nov. 2, 2010, 11:36 p.m. UTC
Hi!

When FRE or PRE transforms a call through fn pointer into a noreturn call,
if it doesn't TODO_cleanup_cfg, we ICE in checking, because the noreturn
call hasn't been fixed up.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2010-11-02  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46165
	* tree-ssa-pre.c (eliminate): Return TODO_cleanup_cfg if changing
	a normal call into noreturn call.

	* gcc.dg/pr46165.c: New test.


	Jakub

Comments

Richard Biener Nov. 3, 2010, 10:31 a.m. UTC | #1
On Wed, Nov 3, 2010 at 12:36 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> When FRE or PRE transforms a call through fn pointer into a noreturn call,
> if it doesn't TODO_cleanup_cfg, we ICE in checking, because the noreturn
> call hasn't been fixed up.
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?

Ok.

Thanks,
Richard.

> 2010-11-02  Jakub Jelinek  <jakub@redhat.com>
>
>        PR tree-optimization/46165
>        * tree-ssa-pre.c (eliminate): Return TODO_cleanup_cfg if changing
>        a normal call into noreturn call.
>
>        * gcc.dg/pr46165.c: New test.
>
> --- gcc/tree-ssa-pre.c.jj       2010-11-01 09:07:23.000000000 +0100
> +++ gcc/tree-ssa-pre.c  2010-11-02 14:27:58.000000000 +0100
> @@ -4364,6 +4364,7 @@ eliminate (void)
>                {
>                  bool can_make_abnormal_goto
>                    = stmt_can_make_abnormal_goto (stmt);
> +                 bool was_noreturn = gimple_call_noreturn_p (stmt);
>
>                  if (dump_file && (dump_flags & TDF_DETAILS))
>                    {
> @@ -4376,6 +4377,11 @@ eliminate (void)
>                  gimple_call_set_fn (stmt, fn);
>                  update_stmt (stmt);
>
> +                 /* When changing a call into a noreturn call, cfg cleanup
> +                    is needed to fix up the noreturn call.  */
> +                 if (!was_noreturn && gimple_call_noreturn_p (stmt))
> +                   todo |= TODO_cleanup_cfg;
> +
>                  /* If we removed EH side-effects from the statement, clean
>                     its EH information.  */
>                  if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
> --- gcc/testsuite/gcc.dg/pr46165.c.jj   2010-11-02 14:47:51.000000000 +0100
> +++ gcc/testsuite/gcc.dg/pr46165.c      2010-11-02 14:47:16.000000000 +0100
> @@ -0,0 +1,11 @@
> +/* PR tree-optimization/46165 */
> +/* { dg-do compile } */
> +/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-dce" } */
> +
> +extern void foo (void) __attribute__((noreturn));
> +void
> +g (void)
> +{
> +  void (*f) (void) = foo;
> +  f ();
> +}
>
>        Jakub
>
diff mbox

Patch

--- gcc/tree-ssa-pre.c.jj	2010-11-01 09:07:23.000000000 +0100
+++ gcc/tree-ssa-pre.c	2010-11-02 14:27:58.000000000 +0100
@@ -4364,6 +4364,7 @@  eliminate (void)
 		{
 		  bool can_make_abnormal_goto
 		    = stmt_can_make_abnormal_goto (stmt);
+		  bool was_noreturn = gimple_call_noreturn_p (stmt);
 
 		  if (dump_file && (dump_flags & TDF_DETAILS))
 		    {
@@ -4376,6 +4377,11 @@  eliminate (void)
 		  gimple_call_set_fn (stmt, fn);
 		  update_stmt (stmt);
 
+		  /* When changing a call into a noreturn call, cfg cleanup
+		     is needed to fix up the noreturn call.  */
+		  if (!was_noreturn && gimple_call_noreturn_p (stmt))
+		    todo |= TODO_cleanup_cfg;
+
 		  /* If we removed EH side-effects from the statement, clean
 		     its EH information.  */
 		  if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
--- gcc/testsuite/gcc.dg/pr46165.c.jj	2010-11-02 14:47:51.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr46165.c	2010-11-02 14:47:16.000000000 +0100
@@ -0,0 +1,11 @@ 
+/* PR tree-optimization/46165 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-dce" } */
+
+extern void foo (void) __attribute__((noreturn));
+void
+g (void)
+{
+  void (*f) (void) = foo;
+  f ();
+}