> Well, there's a call at the tree level for __sync_synchronize as well.
>
> So the question is: why does __s_s ICE but memcmp doesn't? I suppose
> it's the mere rarity with which HAVE_cmpmemsi is defined, and expansion
> of gen_cmpmemsi fails.
>
> There are plenty of other calls to emit_library_call_value that are
> not subsequently protected by emit_libcall_block_1, but they are probably
> sufficiently rare on common platforms that they'd be difficult to trigger.
You're right, here's a patch that marks all no-throw libcalls as no-nonlocal.
Tested on x86_64-suse-linux, OK for the mainline?
2012-11-29 Eric Botcazou <ebotca...@adacore.com>
PR middle-end/55321
* calls.c (emit_library_call_value_1): Mark as no-nonlocal if no-throw.
--
Eric Botcazou
Index: calls.c
===================================================================
--- calls.c (revision 193921)
+++ calls.c (working copy)
@@ -4196,13 +4196,11 @@ emit_library_call_value_1 (int retval, r
that it should complain if nonvolatile values are live. For
functions that cannot return, inform flow that control does not
fall through. */
-
if (flags & ECF_NORETURN)
{
/* The barrier note must be emitted
immediately after the CALL_INSN. Some ports emit more than
just a CALL_INSN above, so we must search for it here. */
-
rtx last = get_last_insn ();
while (!CALL_P (last))
{
@@ -4214,6 +4212,21 @@ emit_library_call_value_1 (int retval, r
emit_barrier_after (last);
}
+ /* Consider that "regular" libcalls, i.e. all of them except for LCT_THROW
+ and LCT_RETURNS_TWICE, cannot perform non-local gotos. */
+ if (flags & ECF_NOTHROW)
+ {
+ rtx last = get_last_insn ();
+ while (!CALL_P (last))
+ {
+ last = PREV_INSN (last);
+ /* There was no CALL_INSN? */
+ gcc_assert (last != before_call);
+ }
+
+ make_reg_eh_region_note_nothrow_nononlocal (last);
+ }
+
/* Now restore inhibit_defer_pop to its actual original value. */
OK_DEFER_POP;