http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60280

--- Comment #1 from bin.cheng <amker.cheng at gmail dot com> ---
It's caused by patch at (revision r198333):
http://gcc.gnu.org/ml/gcc-patches/2013-04/msg01530.html

After patching, forwarder basic block 6 in below dump didn't get removed:
tr4 (short int * array, int n)
{
  int x;
  unsigned int x.0;
  unsigned int _7;
  short int * _9;

  <bb 2>:
  if (n_4(D) > 0)
    goto <bb 6>;
  else
    goto <bb 5>;

  <bb 3>:

  <bb 4>:
  # x_14 = PHI <x_11(3), 0(6)>
  x.0_6 = (unsigned int) x_14;
  _7 = x.0_6 * 2;
  _9 = array_8(D) + _7;
  foo2 (_9);
  x_11 = x_14 + 1;
  if (x_11 < n_4(D))
    goto <bb 3>;
  else
    goto <bb 5>;

  <bb 5>:
  return;

  <bb 6>:
  goto <bb 4>;
}

After expanding, pre-header is filled with pre-loop initialization instructions
and the problem turns into a cfglayout problem:
    5: NOTE_INSN_BASIC_BLOCK 2
    2: r115:SI=r0:SI
      REG_DEAD r0:SI
    3: NOTE_INSN_DELETED
    4: NOTE_INSN_FUNCTION_BEG
    7: {cc:CC=cmp(r1:SI,0);r116:SI=r1:SI;}
      REG_DEAD r1:SI
    8: pc={(cc:CC>0)?L24:pc}
      REG_DEAD cc:CC
      REG_BR_PROB 0x1f98
;;  succ:       4
;;              5
   29: L29:
   13: NOTE_INSN_BASIC_BLOCK 3
   14: r0:SI=r110:SI
   15: call [`foo2'] argc:0
      REG_DEAD r0:SI
   16: r110:SI=r110:SI+0x2
   18: cc:CC=cmp(r110:SI,r114:SI)
   19: pc={(cc:CC!=0)?L29:pc}
      REG_DEAD cc:CC
      REG_BR_PROB 0x2333
;;  succ:       3
;;              5
   24: L24:
   25: NOTE_INSN_BASIC_BLOCK 4
   26: r110:SI=r115:SI
      REG_DEAD r115:SI
   27: NOTE_INSN_DELETED
   28: r114:SI=r116:SI*0x2+r110:SI
      REG_DEAD r116:SI
;;  succ:       3
   32: L32:
   33: NOTE_INSN_BASIC_BLOCK 5
;;  succ:       EXIT


After outof_cfglayout, a jump (in bb3) to exit block is introduced:
    5: NOTE_INSN_BASIC_BLOCK 2
    3: NOTE_INSN_DELETED
    4: NOTE_INSN_FUNCTION_BEG
    7: {cc:CC=cmp(r1:SI,0);r1:SI=r1:SI;}
    8: pc={(cc:CC>0)?L24:pc}
      REG_BR_PROB 0x1f98
;;  succ:       6
;;              3
   55: NOTE_INSN_BASIC_BLOCK 3
   56: pc=L32
;;  succ:       7
   29: L29:
   13: NOTE_INSN_BASIC_BLOCK 4
   14: r0:SI=r4:SI
   15: call [`foo2'] argc:0
   16: r4:SI=r4:SI+0x2
   18: cc:CC=cmp(r4:SI,r5:SI)
   19: pc={(cc:CC!=0)?L29:pc}
      REG_BR_PROB 0x2333
;;  succ:       4
;;              5
   58: NOTE_INSN_BASIC_BLOCK 5
   59: pc=L32
;;  succ:       7
   24: L24:
   25: NOTE_INSN_BASIC_BLOCK 6
   26: r4:SI=r0:SI
   27: NOTE_INSN_DELETED
   28: r5:SI=r1:SI*0x2+r4:SI
   61: pc=L29
;;  succ:       4
   32: L32:
   33: NOTE_INSN_BASIC_BLOCK 7
;;  succ:       EXIT

Ideally, basic block reordering could fix this, but before that, pass
pro_and_epilogue threads jump in bb3 to a direct return instruction and bb
reordering can do nothing any more.

So:
1) Unless we can teach passes before pro_and_epilogue to do some bb reordering
work, it's inappropriate to fix it on RTL.
2) It's natural to be fixed on GIMPLE, but it's disruptive because the cfg
stuff are shared by all GIMPLE(even RTL) optimizers. Yet this method makes more
sense than 1).

I am trying to work out a less intrusive patch for stage 4.

Reply via email to