------- 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

Reply via email to