From patchwork Thu Nov 15 19:34:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix PR middle-end/55321 Date: Thu, 15 Nov 2012 09:34:38 -0000 From: Eric Botcazou X-Patchwork-Id: 199389 Message-Id: <1847684.pGViGHtxfN@polaris> To: gcc-patches@gcc.gnu.org Cc: Richard Henderson Hi, this is the build failure of the Ada runtime on the ARM: +===========================GNAT BUG DETECTED==============================+ | 4.8.0 20121111 (experimental) (armv5tel-unknown-linux-gnueabi) GCC error:| | in merge_latch_edges, at cfgloop.c:678 | | Error detected around s-stposu.adb:565:8 | | Please submit a bug report; see http://gcc.gnu.org/bugs.html. The problem is that get_loop_latch_edges finds no latch edges for a loop because the header of the loop doesn't dominate any of its predecessors. The reason is that a new edge is added during RTL expansion, which changes the dominance info. This edge is from a call to __sync_synchronize to a non-local label generated for a __builtin_setjmp_receiver. Fixed by marking the call as "nononlocal", tested on x86_64-suse-linux, OK for the mainline? 2012-11-15 Eric Botcazou PR middle-end/55321 * optabs.c (mark_nothrow_nononlocal): New function extracted from... (emit_libcall_block_1): ...here. Call it. (expand_mem_thread_fence): Call it for synchronize_libfunc. 2012-11-15 Eric Botcazou * loop_optimization14.ad[sb]: New test. * loop_optimization14_pkg.ads: New helper. Index: optabs.c =================================================================== --- optabs.c (revision 193528) +++ optabs.c (working copy) @@ -3838,6 +3838,23 @@ no_conflict_move_test (rtx dest, const_r } +/* Look for any CALL_INSNs in the insn chain starting at INSN and attach a + REG_EH_REGION reg note to indicate that this call cannot throw or execute + a nonlocal goto (unless there is already a REG_EH_REGION note, in which + case we update it). */ + +static void +mark_nothrow_nononlocal (rtx insn) +{ + while (insn) + { + if (CALL_P (insn)) + make_reg_eh_region_note_nothrow_nononlocal (insn); + + insn = NEXT_INSN (insn); + } +} + /* Emit code to make a call to a constant function or a library call. INSNS is a list containing all insns emitted in the call. @@ -3881,15 +3898,7 @@ emit_libcall_block_1 (rtx insns, rtx tar } } else - { - /* Look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION - reg note to indicate that this call cannot throw or execute a nonlocal - goto (unless there is already a REG_EH_REGION note, in which case - we update it). */ - for (insn = insns; insn; insn = NEXT_INSN (insn)) - if (CALL_P (insn)) - make_reg_eh_region_note_nothrow_nononlocal (insn); - } + mark_nothrow_nononlocal (insns); /* First emit all insns that set pseudos. Remove them from the list as we go. Avoid insns that set pseudos which were referenced in previous @@ -7404,7 +7413,15 @@ expand_mem_thread_fence (enum memmodel m if (HAVE_memory_barrier) emit_insn (gen_memory_barrier ()); else if (synchronize_libfunc != NULL_RTX) - emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0); + { + rtx insns; + start_sequence (); + emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0); + insns = get_insns (); + end_sequence (); + mark_nothrow_nononlocal (insns); + emit_insn (insns); + } else expand_asm_memory_barrier (); }