Summary: | Missing control flow edges for setjmp/longjmp | ||
---|---|---|---|
Product: | gcc | Reporter: | Andreas Krebbel <krebbel> |
Component: | rtl-optimization | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | NEW --- | ||
Severity: | normal | CC: | dimhen, fxue, matz, qinzhao, rguenth, sjames |
Priority: | P3 | Keywords: | wrong-code |
Version: | 4.9.0 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2013-04-25 00:00:00 | |
Bug Depends on: | 56982 | ||
Bug Blocks: | 96672 | ||
Attachments: | testcase |
Description
Andreas Krebbel
2013-04-25 08:23:49 UTC
I suppose more selectively removing edges would be best. Eventually this is done to cater for expansions of builtin calls to non-calls? Then maybe those edges should be removed later, _after_ builtin expansion and find_many_sub_basic_blocks? (In reply to comment #1) > I suppose more selectively removing edges would be best. Eventually this is > done to cater for expansions of builtin calls to non-calls? Then maybe > those edges should be removed later, _after_ builtin expansion and > find_many_sub_basic_blocks? Wouldn't it be better to keep all the edges and fix the fallout from the RTL passes? Do you remember any example where this currently fails? I've verified with GCC 4.4 that dropping the edge removal code from cfgexpand.c together with a backport of the PR56982 patch fixes the actual problem. On Thu, 25 Apr 2013, krebbel at gcc dot gnu.org wrote: > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57067 > > --- Comment #2 from Andreas Krebbel <krebbel at gcc dot gnu.org> 2013-04-25 14:46:09 UTC --- > (In reply to comment #1) > > I suppose more selectively removing edges would be best. Eventually this is > > done to cater for expansions of builtin calls to non-calls? Then maybe > > those edges should be removed later, _after_ builtin expansion and > > find_many_sub_basic_blocks? > > Wouldn't it be better to keep all the edges and fix the fallout from the RTL > passes? Yes, we should be able to prune them when expansion sees that is necessary. > Do you remember any example where this currently fails? Not sure. Run bootstrap & testing? Created attachment 29974 [details] testcase The attached test case fails for arm-none-eabi on trunk, caused by r198096 (the fix for PR56982). It seems related to this PR because the control flow edge after testing the return value of malloc disappears and it is sensitive to the setjmp() call placement. Compile with: /work/apr-builds/r198096/install/bin/arm-none-eabi-gcc -O1 -mcpu=cortex-a15 pr57067.c -o bad.elf The test case should print PASS, but it prints FAIL. The RTL except.c:can_nonlocal_goto () function does not consider setjmp. Does Index: gcc/except.c =================================================================== --- gcc/except.c (revision 198867) +++ gcc/except.c (working copy) @@ -1936,7 +1936,9 @@ insn_nothrow_p (const_rtx insn) bool can_nonlocal_goto (const_rtx insn) { - if (nonlocal_goto_handler_labels && CALL_P (insn)) + if ((nonlocal_goto_handler_labels + || cfun->calls_stjmp) + && CALL_P (insn)) { rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); if (!note || INTVAL (XEXP (note, 0)) != INT_MIN) fix it? For retaining edges we have to teach find_many_sub_basic_blocks to treat abnormal outgoing edges similar to EH outgoing edges - they have to be re-directed from the block ending in the actual call (and made EDGE_ABNORMAL_CALL which doesn't exist on the GIMPLE CFG). Also if ((e->flags & EDGE_ABNORMAL) && !(e->flags & EDGE_SIBCALL)) remove_edge (e); will happily remove an EDGE_FALLTHRU|EDGE_ABNORMAL edge. I tried the proposed patch (after fixing a typo: calls_setjmp / calls_stjmp). It causes an ICE on the attached testcase (and some regressions): $ /work/apr-builds/pr57067/install/bin/arm-none-eabi-gcc -O1 -mcpu=cortex-a15 pr57067.c -o pr57067.elf pr57067.c: In function 'main': pr57067.c:18:7: warning: incompatible implicit declaration of built-in function 'malloc' [enabled by default] p = malloc (0x1000); ^ pr57067.c:22:7: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default] printf ("\nFAIL\n"); ^ pr57067.c:23:7: warning: incompatible implicit declaration of built-in function 'exit' [enabled by default] exit (1); ^ pr57067.c:32:3: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default] printf ("\nPASS\n"); ^ pr57067.c:34:1: error: in basic block 2: } ^ pr57067.c:34:1: error: flow control insn inside a basic block (call_insn 8 7 9 2 (parallel [ (set (reg:SI 0 r0) (call (mem:SI (symbol_ref:SI ("malloc") [flags 0x41] <function_decl 0x7f0cc7362900 malloc>) [0 __builtin_malloc S4 A32]) (const_int 0 [0]))) (use (const_int 0 [0])) (clobber (reg:SI 14 lr)) ]) pr57067.c:18 -1 (expr_list:REG_EH_REGION (const_int 0 [0]) (nil)) (expr_list:REG_CFA_WINDOW_SAVE (use (reg:SI 0 r0)) (nil))) pr57067.c:34:1: internal compiler error: in rtl_verify_flow_info_1, at cfgrtl.c:2321 0x7cc383 _fatal_insn(char const*, rtx_def const*, char const*, int, char const*) /work/local-checkouts/gcc-fsf/gcc/rtl-error.c:109 0x52ed65 rtl_verify_flow_info_1 /work/local-checkouts/gcc-fsf/gcc/cfgrtl.c:2321 0x52efb2 rtl_verify_flow_info /work/local-checkouts/gcc-fsf/gcc/cfgrtl.c:2345 0x51ef49 verify_flow_info() /work/local-checkouts/gcc-fsf/gcc/cfghooks.c:258 0xc02464 try_optimize_cfg /work/local-checkouts/gcc-fsf/gcc/cfgcleanup.c:2812 0xc02464 cleanup_cfg(int) /work/local-checkouts/gcc-fsf/gcc/cfgcleanup.c:2974 0x51c7dd gimple_expand_cfg /work/local-checkouts/gcc-fsf/gcc/cfgexpand.c:4781 *** Bug 108132 has been marked as a duplicate of this bug. *** *** Bug 108117 has been marked as a duplicate of this bug. *** *** Bug 108117 has been marked as a duplicate of this bug. *** *** Bug 108132 has been marked as a duplicate of this bug. *** |