On Sat, Jan 09, 2016 at 12:27:02AM +0100, Bernd Schmidt wrote: > Well, I checked a bit more. Most callers of merge_blocks seem to already > look for barriers if they are a concern and remove them. This occurs > multiple times in ifcvt.c and cfgcleanup.c. Oddly, > merge_blocks_move_predecessor_nojumps uses next_nonnote_insn to find the > barrier, while merge_blocks_move_successor_nojumps uses just NEXT_INSN. That > should probably be fixed too. > > So the situation is a bit odd in that most callers remove the barrier but > merge_blocks tries to handle an isolated barrier as well. The area could > probably cleaned up a little, but on the whole I still lean towards > requiring the caller to remove an isolated barrier. That leaves the RTL in a > more consistent state before the call to merge_blocks.
So is the following ok for trunk? Bootstrapped/regtested on x86_64-linux and i686-linux, and Kyrill has kindly bootstrapped/regtested it on arm too. 2016-01-12 Jakub Jelinek <ja...@redhat.com> PR target/69175 * ifcvt.c (cond_exec_process_if_block): When removing the last insn from then_bb, remove also any possible barriers that follow it. * g++.dg/opt/pr69175.C: New test. --- gcc/ifcvt.c.jj 2016-01-04 14:55:53.000000000 +0100 +++ gcc/ifcvt.c 2016-01-11 16:13:22.833174933 +0100 @@ -739,7 +739,7 @@ cond_exec_process_if_block (ce_if_block rtx_insn *from = then_first_tail; if (!INSN_P (from)) from = find_active_insn_after (then_bb, from); - delete_insn_chain (from, BB_END (then_bb), false); + delete_insn_chain (from, get_last_bb_insn (then_bb), false); } if (else_last_head) delete_insn_chain (first_active_insn (else_bb), else_last_head, false); --- gcc/testsuite/g++.dg/opt/pr69175.C.jj 2016-01-08 13:04:04.084805432 +0100 +++ gcc/testsuite/g++.dg/opt/pr69175.C 2016-01-08 13:03:47.000000000 +0100 @@ -0,0 +1,29 @@ +// PR target/69175 +// { dg-do compile } +// { dg-options "-O2" } +// { dg-additional-options "-march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb" { target { arm_hard_vfp_ok && arm_thumb2_ok } } } + +struct A { A *c, *d; } a; +struct B { A *e; A *f; void foo (); }; +void *b; + +void +B::foo () +{ + if (b) + { + A *n = (A *) b; + if (b == e) + if (n == f) + e = __null; + else + e->c = __null; + else + n->d->c = &a; + n->d = e; + if (e == __null) + e = f = n; + else + e = n; + } +} Jakub