From patchwork Thu Nov 29 14:29:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix PR middle-end/55321 From: Eric Botcazou X-Patchwork-Id: 202759 Message-Id: <3518611.zZ98rW8iyM@polaris> To: Richard Henderson Cc: gcc-patches@gcc.gnu.org Date: Thu, 29 Nov 2012 15:29:28 +0100 > 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 PR middle-end/55321 * calls.c (emit_library_call_value_1): Mark as no-nonlocal if no-throw. 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;