On January 31, 2014 10:24:22 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote: >Hi! > >As described in the PR, __builtin_setjmp_receiver isn't declared to >returns_twice, and thus after dce cfun->calls_setjmp might be no longer >true. >At RTL __builtin_setjmp_receiver is handled as non-local label, so this >patch just forces cfun->has_nonlocal_label already in GIMPLE, so that >e.g. the inliner still sees stmt_can_make_nonlocal_goto. > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. >2014-01-31 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/60003 > * gimple-low.c (lower_builtin_setjmp): Set cfun->has_nonlocal_label. > * profile.c (branch_prob): Use gimple_call_builtin_p > to check for BUILT_IN_SETJMP_RECEIVER. > * tree-inline.c (copy_bb): Call notice_special_calls. > > * gcc.c-torture/execute/pr60003.c: New test. > >--- gcc/gimple-low.c.jj 2014-01-29 12:43:25.000000000 +0100 >+++ gcc/gimple-low.c 2014-01-31 10:02:38.843026680 +0100 >@@ -709,6 +709,12 @@ lower_builtin_setjmp (gimple_stmt_iterat > tree dest, t, arg; > gimple g; > >+ /* __builtin_setjmp_{setup,receiver} aren't ECF_RETURNS_TWICE and >for RTL >+ these builtins are modelled as non-local label jumps to the label >+ that is passed to these two builtins, so pretend we have a >non-local >+ label during GIMPLE passes too. See PR60003. */ >+ cfun->has_nonlocal_label = true; >+ >/* NEXT_LABEL is the label __builtin_longjmp will jump to. Its address >is >passed to both __builtin_setjmp_setup and __builtin_setjmp_receiver. >*/ > FORCED_LABEL (next_label) = 1; >--- gcc/profile.c.jj 2014-01-29 12:43:25.000000000 +0100 >+++ gcc/profile.c 2014-01-31 10:18:00.450198256 +0100 >@@ -1104,7 +1104,6 @@ branch_prob (void) > { > gimple_stmt_iterator gsi; > gimple first; >- tree fndecl; > > gsi = gsi_start_nondebug_after_labels_bb (bb); > gcc_checking_assert (!gsi_end_p (gsi)); >@@ -1114,10 +1113,7 @@ branch_prob (void) > special and don't expect anything to be inserted before > them. */ > if (is_gimple_call (first) >- && (((fndecl = gimple_call_fndecl (first)) != NULL >- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL >- && (DECL_FUNCTION_CODE (fndecl) >- == BUILT_IN_SETJMP_RECEIVER)) >+ && (gimple_call_builtin_p (first, BUILT_IN_SETJMP_RECEIVER) > || (gimple_call_flags (first) & ECF_RETURNS_TWICE) > || (gimple_call_internal_p (first) > && (gimple_call_internal_fn (first) >--- gcc/tree-inline.c.jj 2014-01-29 12:43:24.000000000 +0100 >+++ gcc/tree-inline.c 2014-01-31 10:19:13.849815593 +0100 >@@ -1745,7 +1745,6 @@ copy_bb (copy_body_data *id, basic_block > if (is_gimple_call (stmt)) > { > struct cgraph_edge *edge; >- int flags; > > switch (id->transform_call_graph_edges) > { >@@ -1868,11 +1867,7 @@ copy_bb (copy_body_data *id, basic_block > } > } > >- flags = gimple_call_flags (stmt); >- if (flags & ECF_MAY_BE_ALLOCA) >- cfun->calls_alloca = true; >- if (flags & ECF_RETURNS_TWICE) >- cfun->calls_setjmp = true; >+ notice_special_calls (stmt); > } > > maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt, >--- gcc/testsuite/gcc.c-torture/execute/pr60003.c.jj 2014-01-31 >10:05:15.095205547 +0100 >+++ gcc/testsuite/gcc.c-torture/execute/pr60003.c 2014-01-31 >10:04:59.000000000 +0100 >@@ -0,0 +1,48 @@ >+/* PR tree-optimization/60003 */ >+ >+extern void abort (void); >+ >+unsigned long long jmp_buf[5]; >+ >+__attribute__((noinline, noclone)) void >+baz (void) >+{ >+ __builtin_longjmp (&jmp_buf, 1); >+} >+ >+void >+bar (void) >+{ >+ baz (); >+} >+ >+__attribute__((noinline, noclone)) int >+foo (int x) >+{ >+ int a = 0; >+ >+ if (__builtin_setjmp (&jmp_buf) == 0) >+ { >+ while (1) >+ { >+ a = 1; >+ bar (); /* OK if baz () instead */ >+ } >+ } >+ else >+ { >+ if (a == 0) >+ return 0; >+ else >+ return x; >+ } >+} >+ >+int >+main () >+{ >+ if (foo (1) == 0) >+ abort (); >+ >+ return 0; >+} > > Jakub