From patchwork Fri Jun 25 11:43:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Remove vdefs when changing a normal call into noreturn call (PR tree-optimization/44539) Date: Fri, 25 Jun 2010 01:43:55 -0000 From: Jakub Jelinek X-Patchwork-Id: 56902 Message-Id: <20100625114355.GI12443@tyan-ft48-01.lab.bos.redhat.com> To: Richard Guenther Cc: gcc-patches@gcc.gnu.org Hi! When a call has VDEF, but doesn't have lhs and is through noreturn discovery changed into a noreturn call, we failed to remove the VDEF, which caused verification errors. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux. Ok for trunk? Calling update_stmt unconditionally there isn't possible, as update_stmt adds the stmt into MODIFIED_NORETURN_CALLS and thus split_bbs_on_noreturn_calls hangs. If it has lhs or vdef, the first update_stmt call changes it and the next one won't call update_stmt anymore. 2010-06-25 Jakub Jelinek PR tree-optimization/44539 * tree-cfgcleanup.c (fixup_noreturn_call): Call update_stmt even when the call doesn't have LHS, but has VDEF. * gcc.dg/pr44539.c: New test. Jakub --- gcc/tree-cfgcleanup.c.jj 2010-06-14 07:44:24.000000000 +0200 +++ gcc/tree-cfgcleanup.c 2010-06-24 11:44:59.000000000 +0200 @@ -591,6 +591,9 @@ fixup_noreturn_call (gimple stmt) update_stmt (stmt); changed = true; } + /* Similarly remove VDEF if there is any. */ + else if (gimple_vdef (stmt)) + update_stmt (stmt); return changed; } --- gcc/testsuite/gcc.dg/pr44539.c.jj 2010-06-24 11:45:16.000000000 +0200 +++ gcc/testsuite/gcc.dg/pr44539.c 2010-06-24 11:44:26.000000000 +0200 @@ -0,0 +1,29 @@ +/* PR tree-optimization/44539 */ +/* { dg-do compile } */ +/* { dg-options "-ftracer -freorder-blocks -O2" } */ + +void bar (int file); +extern int baz (void); + +void noret1 () +{ + bar (0); + __builtin_exit (0); +} + +void noret2 () +{ + __builtin_exit (0); +} + +void bar (int i) +{ + if (baz ()) + noret1 (i); +} + +void foo (int i) +{ + if (~i) bar (i); + i ? noret1 () : noret2 (); +}