Benchmark 176.gcc from SPEC CPU2000 fails with an ICE in verify_flow_info and a message about a missing barrier when compiled on powerpc-linux with "-Os -fno-forward-propagate -fno-guess-branch-probability -fno-move-loop-invariants -fno-tree-dominator-opts -fno-tree-loop-optimize". It's an odd set of options but the failure probably demonstrates some sort of dependency between the optimizations. All of the options are documented, none as experimental. A minimized test case (I'll attach it) fails with these options for a cross cc1 for any of power*-*-*, s390*-linux, cris-elf, frv-elf, or m32c-elf with the output: bug11.c: In function ‘find_reg’: bug11.c:32: error: missing barrier after block 4 bug11.c:32: internal compiler error: verify_flow_info failed Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. The failure starts with this patch: http://gcc.gnu.org/viewcvs?view=rev&rev=124786 r124786 | rakdver | 2007-05-17 08:10:24 +0000 (Thu, 17 May 2007)
Created attachment 14309 [details] minimized testcase
Even though the patch was for Tree level, the patch exposed a latent bug in the rtl optimizers (missing barrier after can only happen on the rtl level).
10 to 1 this is a problem with coming out of cfglayout mode somewhere.
If cprop_jump changes a conditional jump into unconditional, then it forgets to add a BARRIER after it. When not in cfglayout mode that's enough, but in cfglayout mode it is uglier, though I haven't found a cfg hook which would do what cprop_jump needs. --- gcc/gcse.c.jj 2007-10-03 21:33:54.000000000 +0200 +++ gcc/gcse.c 2007-10-11 18:13:45.000000000 +0200 @@ -2853,6 +2853,14 @@ cprop_jump (basic_block bb, rtx setcc, r /* Remove REG_EQUAL note after simplification. */ if (note_src) remove_note (jump, note); + + if (any_uncondjump_p (jump) + || (returnjump_p (jump) && !any_condjump_p (jump))) + { + rtx barrier = emit_barrier_after (jump); + if (current_ir_type () == IR_RTL_CFGLAYOUT) + bb->il.rtl->footer = unlink_insn_chain (barrier, barrier); + } } #ifdef HAVE_cc0 is ugly, but fixes this bug.
What do the edge flags look like after cprop changes the jump? EDGE_FALLTHRU should be set. Also, the unconditional JUMP_INSN should be removed. Unconditional jumps are removed when going into cfglayout mode, and when a conditional jump is turned into an unconditional jump, the whole JUMP_INSN can be removed.
The patch from comment #4 is wrong and should not be applied.
It calls purge_dead_edges after changing the jump, so if it changed that into an unconditional jump, purge_dead_edges will purge the EDGE_FALLTHRU edge and keep the other edge. If cfglayout mode is supposed to avoid unconditional jumps, then that needs to be changed, so that the old non-fallthrough edge becomes EDGE_FALLTHRU and old EDGE_FALLTHRU is removed. I believe in other cases cprop_jump could e.g. only simplify an conditional jump (then what it does ATM is probably ok) or could e.g. change a conditional returnjump_p into unconditional one (how are those supposed to be expressed in cfglayout mode)? Anyway, it seems both pass_gcse and pass_bypass are both always in cfglayout mode, so no conditionalization on current_ir_type () is needed.
Updating the CFG as suggested in comment #7 is the appropriate thing to do. How about using delete_insn_and_edges() on the jump insn, and setting EDGE_FALLTHRU on the remaining edge?
Subject: Bug 33673 Author: jakub Date: Thu Nov 1 08:48:05 2007 New Revision: 129819 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129819 Log: PR rtl-optimization/33673 * gcse.c (cprop_jump): If a conditional jump has been optimized into unconditional jump, make the remaining normal edge fallthru and delete the jump insn. * gcc.dg/pr33673.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr33673.c Modified: trunk/gcc/ChangeLog trunk/gcc/gcse.c trunk/gcc/testsuite/ChangeLog
Fixed.