On Fri, 17 Apr 2020, Jakub Jelinek wrote: > Hi! > > 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. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Thanks, Richard. > 2020-04-17 Jakub Jelinek <ja...@redhat.com> > > 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. > > --- gcc/cfgrtl.c.jj 2020-01-12 11:54:36.218416351 +0100 > +++ gcc/cfgrtl.c 2020-04-16 17:28:00.792849169 +0200 > @@ -230,10 +230,20 @@ delete_insn_and_edges (rtx_insn *insn) > { > bool purge = false; > > - if (INSN_P (insn) > - && BLOCK_FOR_INSN (insn) > - && BB_END (BLOCK_FOR_INSN (insn)) == insn) > - purge = true; > + if (INSN_P (insn) && BLOCK_FOR_INSN (insn)) > + { > + basic_block bb = BLOCK_FOR_INSN (insn); > + if (BB_END (bb) == insn) > + purge = true; > + else if (DEBUG_INSN_P (BB_END (bb))) > + for (rtx_insn *dinsn = NEXT_INSN (insn); > + DEBUG_INSN_P (dinsn); dinsn = NEXT_INSN (dinsn)) > + if (BB_END (bb) == dinsn) > + { > + purge = true; > + break; > + } > + } > delete_insn (insn); > if (purge) > return purge_dead_edges (BLOCK_FOR_INSN (insn)); > --- gcc/testsuite/g++.dg/opt/pr94618.C.jj 2020-04-16 17:32:45.891637523 > +0200 > +++ gcc/testsuite/g++.dg/opt/pr94618.C 2020-04-16 17:32:22.715979882 > +0200 > @@ -0,0 +1,25 @@ > +// PR rtl-optimization/94618 > +// { dg-do compile { target c++11 } } > +// { dg-options "-O2 -fnon-call-exceptions -fcompare-debug" } > + > +struct S > +{ > + int a, b, c; > + int foo () noexcept { return a; } > + int bar () noexcept { return b; } > + void baz (int); > + void qux () { if (c) for (int x = foo (); x != bar (); ) baz (x); } > +}; > + > +struct T > +{ > + S s; > + void foo (); > +}; > + > +void > +T::foo () > +{ > + s.qux (); > + s.qux (); > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)