[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 --- Comment #9 from CVS Commits --- The master branch has been updated by Jakub Jelinek : https://gcc.gnu.org/g:c41884a09206be0e21cad7eea71b9754daa969d4 commit r10-7769-gc41884a09206be0e21cad7eea71b9754daa969d4 Author: Jakub Jelinek Date: Fri Apr 17 10:33:27 2020 +0200 Fix -fcompare-debug issue in delete_insn_and_edges [PR94618] delete_insn_and_edges calls purge_dead_edges whenever deleting the last insn in a bb, whatever it is. If it called it only for mandatory last insns in the basic block (that may not be followed by DEBUG_INSNs, dunno if that is control_flow_insn_p or something more complex), that wouldn't be a problem, but as it calls it on any last insn and can actually do something in the bb, if such an insn is followed by one more more DEBUG_INSNs and nothing else in the same bb, we don't call purge_dead_edges with -g and do call it with -g0. On the testcase, there are two reg-to-reg moves with REG_EH_REGION notes (previously memory accesses but simplified and yet not optimized), and the second is followed by DEBUG_INSNs; the second move is delete_insn_and_edges and after removing it, for -g0 purge_dead_edges removes the REG_EH_REGION from the now last insn in the bb (the first reg-to-reg move), while for -g it isn't called and things diverge from that quickly on. Fixed by calling purdge_dead_edges even if we remove the last real insn followed only by DEBUG_INSNs in the same bb. 2020-04-17 Jakub Jelinek PR rtl-optimization/94618 * cfgrtl.c (delete_insn_and_edges): Set purge not just when insn is the BB_END of its block, but also when it is only followed by DEBUG_INSNs in its block. * g++.dg/opt/pr94618.C: New test.
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 --- Comment #8 from Jakub Jelinek --- Though, a slight advantage of the patch as is is that it will do any insn walk only if two conditions are met, BB_END is a DEBUG_INSN and insn is followed by a DEBUG_INSN. My thoughs were that there could be a large bb with hundreds of DEBUG_INSNs at the end and if we e.g. started deleting insn from the start, even if they aren't really followed by any DEBUG_INSNs, we'd still walk all of them each time.
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 --- Comment #7 from Jakub Jelinek --- Perhaps if we checked DEBUG_INSN_P on BB_END, we could then use prev_nondebug_insn, so like: if (INSN_P (insn) && BLOCK_FOR_INSN (insn)) { basic_block bb = BLOCK_FOR_INSN (insn); if (BB_END (bb) == insn || (DEBUG_INSN_P (BB_END (bb)) && prev_nondebug_insn (BB_END (bb)) == insn)) purge = true; } ?
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 --- Comment #6 from Richard Biener --- (In reply to Jakub Jelinek from comment #5) > Created attachment 48293 [details] > gcc10-pr94618.patch > > Untested fix. Looks logically correct - but are there no helpers for this on the RTL side? Like LAST_NONDEBUG_INSN (BB) or so? Or skip_debug_insns_until_bb_end? Possibly this is the only such case of course ...
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 Jakub Jelinek changed: What|Removed |Added Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |jakub at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- Created attachment 48293 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48293=edit gcc10-pr94618.patch Untested fix.
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 --- Comment #4 from Jakub Jelinek --- I think the difference is much earlier, in cse_local dump there is (with additional --param=min-nondebug-insn-uid=1): deferring deletion of insn with uid = 10060. -deferring deletion of insn with uid = 10059. -Deleted 2 trivially dead insns +Deleted 1 trivially dead insns where the RA then removes the trivially dead insn when cse_local didn't.
[Bug rtl-optimization/94618] [8/9/10 Regression] '-fcompare-debug' failure (length) with -O2 -fnon-call-exceptions since r8-565-g7581ce9a1ad6df9c
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94618 Richard Biener changed: What|Removed |Added CC||vmakarov at gcc dot gnu.org Keywords||ra Component|debug |rtl-optimization --- Comment #3 from Richard Biener --- diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index e99fb9ff5d1..e508d736de8 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -9019,7 +9019,7 @@ split_critical_edges (bool for_edge_insertion_p /* = false */) { gimple_stmt_iterator gsi; - gsi = gsi_last_bb (e->src); + gsi = gsi_last_nondebug_bb (e->src); if (!gsi_end_p (gsi) && stmt_ends_bb_p (gsi_stmt (gsi)) && (gimple_code (gsi_stmt (gsi)) != GIMPLE_RETURN Doesn't fix it, disabling tail merging doesn't either. The difference is --- t.gkd 2020-04-16 16:15:15.906645135 +0200 +++ t.gk.gkd2020-04-16 16:15:16.082647662 +0200 @@ -29,7 +29,7 @@ (pc))) "t.C":17:5# {*jcc} (expr_list:REG_DEAD (reg:CCZ 17 flags) (int_list:REG_BR_PROB 536870916 (nil))) - -> 13) + -> 14) (note # 0 0 [bb 3] NOTE_INSN_BASIC_BLOCK) (note # 0 0 NOTE_INSN_DELETED) (insn/f:TI # 0 0 3 (set (mem:DI (pre_dec:DI (reg/f:DI 7 sp)) [ S8 A8]) @@ -74,13 +74,13 @@ (const_int 8 [0x8])) [ MEM[(struct S *)this_2(D) + 8B].ae+0 S4 A32])) "t.C":8:12# {*movsi_internal} (expr_list:REG_EH_REGION (const_int -5 [0xfffb]) (nil))) +(note # 0 0 # NOTE_INSN_EH_REGION_BEG) (insn # 0 0 3 (set (reg:CCZ 17 flags) (compare:CCZ (mem:SI (plus:DI (reg/f:DI 5 di [orig:93 this ] [93]) (const_int 12 [0xc])) [ MEM[(struct S *)this_2(D) + 8B].af+0 S4 A32]) (reg:SI 6 bp [orig:87 _10 ] [87]))) "t.C":18:28# {*cmpsi_1} (expr_list:REG_DEAD (reg/f:DI 5 di [orig:93 this ] [93]) -(expr_list:REG_EH_REGION (const_int -6 [0xfffa]) -(nil +(nil))) (jump_insn # 0 0 3 (set (pc) (if_then_else (eq (reg:CCZ 17 flags) (const_int 0 [0])) @@ -98,7 +98,6 @@ (insn # 0 0 4 (set (reg:DI 5 di) (reg/f:DI 41 r13 [orig:82 _1 ] [82])) "t.C":19:4# {*movdi_internal} (nil)) -(note # 0 0 # NOTE_INSN_EH_REGION_BEG) (call_insn:TI # 0 0 4 (call (mem:QI (symbol_ref:DI ("_ZN1S1iEi") [flags 0x41] ) [ i S1 A8]) (const_int 0 [0])) "t.C":19:4# {*call} (expr_list:REG_DEAD (reg:DI 5 di) @@ -246,7 +245,7 @@ -> simple_return) (barrier # 0 0) (note # 0 0 NOTE_INSN_DELETED) -(code_label # 0 0 9 13 (nil) [1 uses]) +(code_label # 0 0 9 14 (nil) [1 uses]) (note # 0 0 [bb 9] NOTE_INSN_BASIC_BLOCK) (insn:TI # 0 0 9 (unspec_volatile [ (const_int 0 [0]) but on GIMPLE I cannot see any difference in EH info. Starting with LRA I see the disconnect with REG_EH_REGION notes on insn 17 / 41: (insn 17 16 18 3 (set (reg:CCZ 17 flags) (compare:CCZ (mem:SI (plus:DI (reg/f:DI 3 bx [orig:93 this ] [93]) (const_int 12 [0xc])) [1 MEM[(struct S *)this_2(D) + 8B].af+0 S4 A32]) (reg:SI 6 bp [orig:87 _10 ] [87]))) "t.C":18:28 11 {*cmpsi_1} (expr_list:REG_EH_REGION (const_int -6 [0xfffa]) (nil))) vs. (insn 41 40 42 3 (set (reg:CCZ 17 flags) (compare:CCZ (mem:SI (plus:DI (reg/f:DI 3 bx [orig:93 this ] [93]) (const_int 12 [0xc])) [1 MEM[(struct S *)this_2(D) + 8B].af+0 S4 A32]) (reg:SI 6 bp [orig:87 _10 ] [87]))) "t.C":18:28 11 {*cmpsi_1} (nil))