------- Comment #7 from matz at gcc dot gnu dot org 2009-05-05 15:32 ------- The problem is the expansion of this code: <bb 4>: ... D.1650_109 = D.1648_107 | 1; if (D.1650_109 != 0) goto <bb 6>; else goto <bb 5>;
plus the fact that we need to insert something on edge 4->6. Note how the condition here is always true (should have been cleaned up by some tree optimization, but isn't, and we shouldn't have to rely on this anyway). Now expand comes and wants to generate a jump sequence implementing this if (D.1648_107 | 1) jump true_label. do_jump has code for an IOR expression jump: case TRUTH_ORIF_EXPR: ... do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label); do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); bb 5 comes after bb 6 so the false edge is fallthrough, hence if_false_label here is NULL. Now we first emit a conditional jump to true_label for the left side: (jump_insn 32 31 0 pr40021.f:28 (set (pc) (if_then_else (ne (reg:CCZ 17 flags) (const_int 0 [0x0])) (label_ref 0) (pc))) -1 (nil)) and then for the right side. As this is a trivially true condition do_jump then decides to emit an unconditional jump plus barrier: (jump_insn 33 32 34 pr40021.f:28 (set (pc) (label_ref 0)) -1 (nil)) (barrier 34 33 0) Note how the first jump is useless now, it conditionally jumps to a label which when not taken will be jumped to anyway unconditionally. This all is fine so far, except that we need to remove fallthrough edges if expand_gimple_cond, if do_jump decided to emit a barrier. Unfortunately this removes one of the two edges, leaving only one. Now emitting on this edge doesn't need splitting anymore, the instruction is inserted at the end of the source block. But that insertion only expects one jump here and inserts before that, leaving the conditional jump before: (jump_insn 32 31 111 5 pr40021.f:28 (set (pc) (if_then_else (ne (reg:CCZ 17 flags) (const_int 0 [0x0])) (label_ref 48) (pc))) -1 (expr_list:REG_BR_PROB (const_int 5000 [0x1388]) (nil))) (insn 13 111 33 6 pr40021.f:20 (set (reg/v:SI 122 [ i ]) (const_int 1 [0x1])) -1 (nil)) (jump_insn 33 13 34 6 pr40021.f:28 (set (pc) (label_ref 48)) -1 (nil)) (barrier 34 33 35) (insn 13 is the inserted one). That's semantically not equivalent, if the conditional jump is taken the assignment i = 1 is left out, although it was supposed to be on exactly that edge. I'm going to fix this in expand_gimple_cond if this situation can happen by cleaning up the generated jump sequence. -- matz at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- AssignedTo|unassigned at gcc dot gnu |matz at gcc dot gnu dot org |dot org | Status|NEW |ASSIGNED Last reconfirmed|2009-05-05 12:41:15 |2009-05-05 15:32:53 date| | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40021