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.