Bug 41440 - SEG FAULT in CSE.C caused by bad RTL expansion
Summary: SEG FAULT in CSE.C caused by bad RTL expansion
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.5.0
: P3 major
Target Milestone: 4.5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2009-09-23 02:39 UTC by Andy Hutchinson
Modified: 2010-01-29 16:33 UTC (History)
4 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: avr-unknown-none
Build:
Known to work: 4.4.2 4.3.2
Known to fail: 4.5.0
Last reconfirmed:


Attachments
Expanded RTL (1.55 KB, text/plain)
2009-09-23 02:49 UTC, Andy Hutchinson
Details
cleanup_cfg dump (480 bytes, text/plain)
2009-09-24 02:15 UTC, Andy Hutchinson
Details
ssa dump (1.28 KB, text/plain)
2009-09-24 02:15 UTC, Andy Hutchinson
Details
Patch to cfgrtl.c commit_one_edge_insertion() (331 bytes, patch)
2009-09-27 17:30 UTC, Andy Hutchinson
Details | Diff
Fix (446 bytes, patch)
2009-10-01 01:49 UTC, Andy Hutchinson
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andy Hutchinson 2009-09-23 02:39:38 UTC
Segmentation fault occurs on test gcc.c-torture/execute/memcpy-1.c and many other tests. 
I have created a reduced case that shows problem. This, dumps and backtrace are attached.

The cause seem to be that cse assumes previous instruction is CC0 setter. The expanded RTL show this is surprising not true. So CSE crashes with null rtx.
The problem occurs on memcpy() expansion.

The expansion of memcpy() uses RTL expander movemem which is a simple RTL do loop. This indeed correctly has compare directly before test and jump (see pattern attached). Yet when the RTL is expanded, part of the next block's "i=0" is inserted after compare and before jump. The tree dump looks right.

The next block RTL loop is not right either, it is supposed to be checking dst[i] != i  - but in reality is  dst[i] != 0.



Using built-in specs.
Target: avr
Configured with: ../../gccsvn/configure --prefix=/home/andy/local/avr --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2 --enable-checking
Thread model: single
gcc version 4.5.0 20090922 (experimental) (GCC) 



#include <string.h>

#define MEMCPY_SIZE (100)

main ()
{
  unsigned i;
  unsigned char src[MEMCPY_SIZE];
  unsigned char dst[MEMCPY_SIZE];

  for (i = 0; i < MEMCPY_SIZE; i++)
  {
    src[i] = (unsigned char) i;
    dst[i] = 0;
  }

  (void) memcpy (dst, src, MEMCPY_SIZE);

  for (i = 0; i < MEMCPY_SIZE; i++)
    if (dst[i] != (unsigned char) i)
      abort ();

  exit (0);
}


===================================================================
(gdb) run  -mmcu=atmega128 -Os -O2  -DSTACK_SIZE=1535 -fdump-rtl-all -fdump-tree-all  memcpy-1.c 

Starting program: /home/andy/local/avr/bin/avr-cc1 -mmcu=atmega128 -Os -O2  -DSTACK_SIZE=1535 -fdump-rtl-all -fdump-tree-all  memcpy-1.c
 main
memcpy-1.c: In function 'main':
memcpy-1.c:21:7: warning: incompatible implicit declaration of built-in function 'abort'
memcpy-1.c:23:3: warning: incompatible implicit declaration of built-in function 'exit'

Analyzing compilation unit
Performing interprocedural optimizations
 <visibility> <> <early_local_cleanups> <summary generate> <cp> <inline> <static-var> <pure-const>Assembling functions:
 main
Program received signal SIGSEGV, Segmentation fault.
equiv_constant (x=0x0) at ../../../gccsvn/gcc/cse.c:3809
3809	  if (REG_P (x)
(gdb) where
#0  equiv_constant (x=0x0) at ../../../gccsvn/gcc/cse.c:3809
#1  0x085f16e3 in fold_rtx (x=0xb7de5c18, insn=0xb7d8ea28) at ../../../gccsvn/gcc/cse.c:3277
#2  0x085f16da in fold_rtx (x=0xb7de66a0, insn=0xb7d8ea28) at ../../../gccsvn/gcc/cse.c:3276
#3  0x085f5af6 in cse_insn (insn=0xb7d8ea28) at ../../../gccsvn/gcc/cse.c:4496
#4  0x085f8a45 in cse_main (f=0xb7de9ba0, nregs=167) at ../../../gccsvn/gcc/cse.c:6269
#5  0x085f93da in rest_of_handle_cse () at ../../../gccsvn/gcc/cse.c:7158
#6  0x0833f3b2 in execute_one_pass (pass=0x87a1fa0) at ../../../gccsvn/gcc/passes.c:1295
#7  0x0833f62c in execute_pass_list (pass=0x87a1fa0) at ../../../gccsvn/gcc/passes.c:1344
#8  0x0833f63f in execute_pass_list (pass=0x879f200) at ../../../gccsvn/gcc/passes.c:1345
#9  0x08410110 in tree_rest_of_compilation (fndecl=0xb7dbda80) at ../../../gccsvn/gcc/tree-optimize.c:389
#10 0x0857399a in cgraph_expand_function (node=0xb7d34900) at ../../../gccsvn/gcc/cgraphunit.c:1158
#11 0x085763e5 in cgraph_finalize_compilation_unit () at ../../../gccsvn/gcc/cgraphunit.c:1217
#12 0x080b694b in c_write_global_declarations () at ../../../gccsvn/gcc/c-decl.c:9361
#13 0x083b518a in toplev_main (argc=8, argv=0xbfabb114) at ../../../gccsvn/gcc/toplev.c:1050
#14 0x0813abf2 in main (argc=Cannot access memory at address 0x10
) at ../../../gccsvn/gcc/main.c:35
(gdb) up
#1  0x085f16e3 in fold_rtx (x=0xb7de5c18, insn=0xb7d8ea28) at ../../../gccsvn/gcc/cse.c:3277
3277		    const_arg = equiv_constant (folded_arg);
(gdb) print folded_arg
$4 = (rtx) 0x0
(gdb) pr insn
(nil)
(gdb) print insn
$5 = (rtx) 0xb7d8ea28
(gdb) pr insn
(jump_insn 138 111 151 5 memcpy-1.c:17 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 131)
            (pc))) 110 {branch} (expr_list:REG_BR_PROB (const_int 9900 [0x26ac])
        (nil))
 -> 131)
(gdb) print folded_arg
$6 = (rtx) 0x0
(gdb) list
3272		    break;
3273	#endif
3274	
3275		  default:
3276		    folded_arg = fold_rtx (folded_arg, insn);
3277		    const_arg = equiv_constant (folded_arg);
3278		    break;
3279		  }
3280	
3281		/* For the first three operands, see if the operand
(gdb) 

=======================================================================
TREE DUMP - OPTIMIZED:

;; Function main (main)

main ()
{
  unsigned int src.33;
  unsigned int D.2132;
  unsigned char D.2128;
  unsigned char D.2130;
  unsigned int ivtmp.29;
  unsigned int ivtmp.24;
  unsigned char dst[100];
  unsigned char src[100];
  unsigned int i;
  unsigned char D.2091;
  unsigned char D.2090;

<bb 2>:
  ivtmp.24_23 = (unsigned int) &src[0];
  ivtmp.29_26 = (unsigned int) &dst[0];
  src.33_31 = (unsigned int) &src;
  D.2132_32 = src.33_31 + 100;

<bb 3>:
  # ivtmp.24_1 = PHI <ivtmp.24_16(3), ivtmp.24_23(2)>
  # ivtmp.29_24 = PHI <ivtmp.29_25(3), ivtmp.29_26(2)>
  D.2128_27 = (unsigned char) ivtmp.24_1;
  D.2130_29 = (unsigned char) ivtmp.24_23;
  D.2090_30 = D.2128_27 - D.2130_29;
  MEM[index: ivtmp.24_1] = D.2090_30;
  ivtmp.24_16 = ivtmp.24_1 + 1;
  MEM[index: ivtmp.29_24] = 0;
  ivtmp.29_25 = ivtmp.29_24 + 1;
  if (ivtmp.24_16 != D.2132_32)
    goto <bb 3>;
  else
    goto <bb 4>;

<bb 4>:
  dst = src;

<bb 5>:
  # i_19 = PHI <i_9(7), 0(4)>
  # ivtmp.29_17 = PHI <ivtmp.29_10(7), ivtmp.29_26(4)>
  D.2091_7 = MEM[index: ivtmp.29_17];
  ivtmp.29_10 = ivtmp.29_17 + 1;
  D.2090_22 = (unsigned char) i_19;
  if (D.2091_7 != D.2090_22)
    goto <bb 6>;
  else
    goto <bb 7>;

<bb 6>:
  abort ();

<bb 7>:
  i_9 = i_19 + 1;
  if (i_9 != 100)
    goto <bb 5>;
  else
    goto <bb 8>;

<bb 8>:
  exit (0);

}

=====================================================================
RTL EXPANDER FROM AVR.MD


(define_expand "movmemhi"
  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
          (match_operand:BLK 1 "memory_operand" ""))
          (use (match_operand:HI 2 "const_int_operand" ""))
          (use (match_operand:HI 3 "const_int_operand" ""))])]
  ""
  "{
  int prob;
  HOST_WIDE_INT count;
  enum machine_mode mode;
  rtx label = gen_label_rtx ();
  rtx loop_reg;
  rtx jump;

  /* Copy pointers into new psuedos - they will be changed.  */
  rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));

  /* Create rtx for tmp register - we use this as scratch.  */
  rtx tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);

  if (GET_CODE (operands[2]) != CONST_INT)
    FAIL;

  count = INTVAL (operands[2]);
  if (count <= 0)
    FAIL;

  /* Work out branch probability for latter use.  */
  prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;

  /* See if constant fit 8 bits.  */
  mode = (count < 0x100) ? QImode : HImode;
  /* Create loop counter register.  */
  loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));

  /* Now create RTL code for move loop.  */
  /* Label at top of loop.  */
  emit_label (label);

  /* Move one byte into scratch and inc pointer.  */
  emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
  emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));

  /* Move to mem and inc pointer.  */
  emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
  emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));

  /* Decrement count.  */
  emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));

  /* Compare with zero and jump if not equal. */
  emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
                           label);
  /* Set jump probability based on loop count.  */
  jump = get_last_insn ();
  add_reg_note (jump, REG_BR_PROB, GEN_INT (prob));
  DONE;
}")
Comment 1 Andy Hutchinson 2009-09-23 02:49:54 UTC
Created attachment 18632 [details]
Expanded RTL

Expanded RTL dump
Comment 2 Andy Hutchinson 2009-09-24 02:15:05 UTC
Created attachment 18641 [details]
cleanup_cfg dump
Comment 3 Andy Hutchinson 2009-09-24 02:15:40 UTC
Created attachment 18642 [details]
ssa dump
Comment 4 Andy Hutchinson 2009-09-24 02:21:19 UTC
Problem is located in ssa pass. It seems to name initialization of loop index to something other than the loop index increment and tested in the last for loop. This "dead"initialization is deleted in latter passes  but the damage is done and the data flow is obviously meesed up.




Comment 5 Andy Hutchinson 2009-09-24 03:30:03 UTC
Forget previous post, I misunderstood PHI node. However, I was close

The PHI in block 5 has incoming ZERO constant. With "detailed" expansion dump file , it can be seen that this constant value copy is inserted on BB edge 4-5 but the RTL shows it is actually added one instruction before end of block 4. The edge 4->5 falls through and insertion should be after jump that is last insn of BB 4 (and the end of memcpy do loop  expansion)

Hopefully, I right this time.


;; Function main (main)


Pass statistics:
----------------


CFG Statistics for main

---------------------------------------------------------
                                Number of        Memory
                                instances         used 
---------------------------------------------------------
Basic blocks                              9        576b
Edges                                     8        352b
---------------------------------------------------------
Total memory used by CFG data                      928b
---------------------------------------------------------

Coalesced label blocks: 0 (Max so far: 0)

main ()
{
  unsigned intD.3 src.29D.2127;
  unsigned intD.3 D.2128;
  unsigned charD.10 D.2124;
  unsigned charD.10 D.2126;
  unsigned intD.3 ivtmp.25D.2120;
  unsigned intD.3 ivtmp.20D.2115;
  unsigned charD.10 dstD.1321[100];
  unsigned charD.10 srcD.1320[100];
  unsigned intD.3 iD.1319;
  unsigned charD.10 D.2091;
  unsigned charD.10 D.2090;

  # BLOCK 2 freq:100
  # PRED: ENTRY [100.0%]  (fallthru,exec)
  ivtmp.20D.2115_23 = (unsigned intD.3) &srcD.1320[0];
  ivtmp.25D.2120_26 = (unsigned intD.3) &dstD.1321[0];
  src.29D.2127_31 = (unsigned intD.3) &srcD.1320;
  D.2128_32 = src.29D.2127_31 + 100;
  # SUCC: 3 [100.0%]  (fallthru,exec)

  # BLOCK 3 freq:9900
  # PRED: 3 [99.0%]  (true,exec) 2 [100.0%]  (fallthru,exec)
  # ivtmp.20D.2115_2 = PHI <ivtmp.20D.2115_16(3), ivtmp.20D.2115_23(2)>
  # ivtmp.25D.2120_24 = PHI <ivtmp.25D.2120_25(3), ivtmp.25D.2120_26(2)>
  D.2124_27 = (unsigned charD.10) ivtmp.20D.2115_2;
  D.2126_29 = (unsigned charD.10) ivtmp.20D.2115_23;
  D.2090_30 = D.2124_27 - D.2126_29;
  # .MEMD.2094_12 = VDEF <.MEMD.2094_20>
  MEM[index: ivtmp.20D.2115_2] = D.2090_30;
  ivtmp.20D.2115_16 = ivtmp.20D.2115_2 + 1;
  # .MEMD.2094_13 = VDEF <.MEMD.2094_12>
  MEM[index: ivtmp.25D.2120_24] = 0;
  ivtmp.25D.2120_25 = ivtmp.25D.2120_24 + 1;
  if (ivtmp.20D.2115_16 != D.2128_32)
    goto <bb 3>;
  else
    goto <bb 4>;
  # SUCC: 3 [99.0%]  (true,exec) 4 [1.0%]  (false,exec)

  # BLOCK 4 freq:100
  # PRED: 3 [1.0%]  (false,exec)
  # .MEMD.2094_14 = VDEF <.MEMD.2094_13>
  dstD.1321 = srcD.1320;
  # SUCC: 5 [100.0%]  (fallthru,exec)

  # BLOCK 5 freq:1815
  # PRED: 7 [98.9%]  (true,exec) 4 [100.0%]  (fallthru,exec)
  # iD.1319_19 = PHI <iD.1319_9(7), 0(4)>
  # ivtmp.25D.2120_17 = PHI <ivtmp.25D.2120_10(7), ivtmp.25D.2120_26(4)>
  # VUSE <.MEMD.2094_14>
  D.2091_7 = MEM[index: ivtmp.25D.2120_17];
  ivtmp.25D.2120_10 = ivtmp.25D.2120_17 + 1;
  D.2090_22 = (unsigned charD.10) iD.1319_19;
  if (D.2091_7 != D.2090_22)
    goto <bb 6>;
  else
    goto <bb 7>;
  # SUCC: 6 [4.5%]  (true,exec) 7 [95.5%]  (false,exec)

  # BLOCK 6 freq:82
  # PRED: 5 [4.5%]  (true,exec)
  # VUSE <.MEMD.2094_14>
  abortD.823 ();
  # SUCC:

  # BLOCK 7 freq:1733
  # PRED: 5 [95.5%]  (false,exec)
  iD.1319_9 = iD.1319_19 + 1;
  if (iD.1319_9 != 100)
    goto <bb 5>;
  else
    goto <bb 8>;
  # SUCC: 5 [98.9%]  (true,exec) 8 [1.1%]  (false,exec)

  # BLOCK 8 freq:18
  # PRED: 7 [1.1%]  (false,exec)
  # VUSE <.MEMD.2094_14>
  exitD.869 (0);
  # SUCC:

}



Partition map 

Partition 2 (ivtmp.20_2 - 2 )
Partition 7 (D.2091_7 - 7 )
Partition 9 (i_9 - 9 )
Partition 10 (ivtmp.25_10 - 10 )
Partition 11 (.MEM_11(D) - 11 )
Partition 12 (.MEM_12 - 12 )
Partition 13 (.MEM_13 - 13 )
Partition 14 (.MEM_14 - 14 )
Partition 16 (ivtmp.20_16 - 16 )
Partition 17 (ivtmp.25_17 - 17 )
Partition 19 (i_19 - 19 )
Partition 22 (D.2090_22 - 22 )
Partition 23 (ivtmp.20_23 - 23 )
Partition 24 (ivtmp.25_24 - 24 )
Partition 25 (ivtmp.25_25 - 25 )
Partition 26 (ivtmp.25_26 - 26 )
Partition 27 (D.2124_27 - 27 )
Partition 29 (D.2126_29 - 29 )
Partition 30 (D.2090_30 - 30 )
Partition 31 (src.29_31 - 31 )
Partition 32 (D.2128_32 - 32 )


Partition map 

Partition 0 (ivtmp.20_2 - 2 )
Partition 1 (i_9 - 9 )
Partition 2 (ivtmp.25_10 - 10 )
Partition 3 (ivtmp.20_16 - 16 )
Partition 4 (ivtmp.25_17 - 17 )
Partition 5 (i_19 - 19 )
Partition 6 (ivtmp.20_23 - 23 )
Partition 7 (ivtmp.25_24 - 24 )
Partition 8 (ivtmp.25_25 - 25 )
Partition 9 (ivtmp.25_26 - 26 )


Live on entry to BB2 : 

Live on entry to BB3 : ivtmp.20_23  ivtmp.25_26  

Live on entry to BB4 : ivtmp.25_26  

Live on entry to BB5 : 

Live on entry to BB6 : 

Live on entry to BB7 : ivtmp.25_10  i_19  

Live on entry to BB8 : 

Conflict graph:
0: 6
3: 6
6: 0, 3
7: 9
8: 9
9: 7, 8

After sorting:
Sorted Coalesce list:
(2) ivtmp.20_2 <-> ivtmp.20_16
(2) i_9 <-> i_19
(2) ivtmp.25_10 <-> ivtmp.25_17
(2) ivtmp.25_24 <-> ivtmp.25_25
(1) ivtmp.20_2 <-> ivtmp.20_23
(1) ivtmp.25_17 <-> ivtmp.25_26
(1) ivtmp.25_24 <-> ivtmp.25_26

Partition map 

Partition 0 (ivtmp.20_2 - 2 )
Partition 1 (i_9 - 9 )
Partition 2 (ivtmp.25_10 - 10 )
Partition 3 (ivtmp.20_16 - 16 )
Partition 4 (ivtmp.25_17 - 17 )
Partition 5 (i_19 - 19 )
Partition 6 (ivtmp.20_23 - 23 )
Partition 7 (ivtmp.25_24 - 24 )
Partition 8 (ivtmp.25_25 - 25 )
Partition 9 (ivtmp.25_26 - 26 )

Coalesce list: (2)ivtmp.20_2 & (16)ivtmp.20_16 [map: 0, 3] : Success -> 0
Coalesce list: (9)i_9 & (19)i_19 [map: 1, 5] : Success -> 1
Coalesce list: (10)ivtmp.25_10 & (17)ivtmp.25_17 [map: 2, 4] : Success -> 2
Coalesce list: (24)ivtmp.25_24 & (25)ivtmp.25_25 [map: 7, 8] : Success -> 7
Coalesce list: (2)ivtmp.20_2 & (23)ivtmp.20_23 [map: 0, 6] : Fail due to conflict
Coalesce list: (17)ivtmp.25_10 & (26)ivtmp.25_26 [map: 2, 9] : Success -> 2
Coalesce list: (24)ivtmp.25_24 & (26)ivtmp.25_10 [map: 7, 2] : Fail due to conflict
After Coalescing:

Partition map 

Partition 0 (ivtmp.20_2 - 2 16 )
Partition 1 (D.2091_7 - 7 )
Partition 2 (i_9 - 9 19 )
Partition 3 (ivtmp.25_10 - 10 17 26 )
Partition 4 (D.2090_22 - 22 )
Partition 5 (ivtmp.20_23 - 23 )
Partition 6 (ivtmp.25_24 - 24 25 )
Partition 7 (D.2124_27 - 27 )
Partition 8 (D.2126_29 - 29 )
Partition 9 (D.2090_30 - 30 )
Partition 10 (src.29_31 - 31 )
Partition 11 (D.2128_32 - 32 )


Replacing Expressions
D.2090_22 replace with --> D.2090_22 = (unsigned char) i_19;

D.2124_27 replace with --> D.2124_27 = (unsigned char) ivtmp.20_2;

D.2126_29 replace with --> D.2126_29 = (unsigned char) ivtmp.20_23;

D.2090_30 replace with --> D.2090_30 = D.2124_27 - D.2126_29;

src.29_31 replace with --> src.29_31 = (unsigned int) &src;



CFG Statistics for main

---------------------------------------------------------
                                Number of        Memory
                                instances         used 
---------------------------------------------------------
Basic blocks                              9        576b
Edges                                     8        352b
---------------------------------------------------------
Total memory used by CFG data                      928b
---------------------------------------------------------

Coalesced label blocks: 0 (Max so far: 0)

main ()
{
  unsigned intD.3 src.29D.2127;
  unsigned intD.3 D.2128;
  unsigned charD.10 D.2124;
  unsigned charD.10 D.2126;
  unsigned intD.3 ivtmp.25D.2120;
  unsigned intD.3 ivtmp.20D.2115;
  unsigned charD.10 dstD.1321[100];
  unsigned charD.10 srcD.1320[100];
  unsigned intD.3 iD.1319;
  unsigned charD.10 D.2091;
  unsigned charD.10 D.2090;

  # BLOCK 2 freq:100
  # PRED: ENTRY [100.0%]  (fallthru,exec)
  ivtmp.20D.2115_23 = (unsigned intD.3) &srcD.1320[0];
  ivtmp.25D.2120_26 = (unsigned intD.3) &dstD.1321[0];
  src.29D.2127_31 = (unsigned intD.3) &srcD.1320;
  D.2128_32 = src.29D.2127_31 + 100;
  # SUCC: 3 [100.0%]  (fallthru,exec)

  # BLOCK 3 freq:9900
  # PRED: 3 [99.0%]  (true,exec) 2 [100.0%]  (fallthru,exec)
  # ivtmp.20D.2115_2 = PHI <ivtmp.20D.2115_16(3), ivtmp.20D.2115_23(2)>
  # ivtmp.25D.2120_24 = PHI <ivtmp.25D.2120_25(3), ivtmp.25D.2120_26(2)>
  D.2124_27 = (unsigned charD.10) ivtmp.20D.2115_2;
  D.2126_29 = (unsigned charD.10) ivtmp.20D.2115_23;
  D.2090_30 = D.2124_27 - D.2126_29;
  # .MEMD.2094_12 = VDEF <.MEMD.2094_20>
  MEM[index: ivtmp.20D.2115_2] = D.2090_30;
  ivtmp.20D.2115_16 = ivtmp.20D.2115_2 + 1;
  # .MEMD.2094_13 = VDEF <.MEMD.2094_12>
  MEM[index: ivtmp.25D.2120_24] = 0;
  ivtmp.25D.2120_25 = ivtmp.25D.2120_24 + 1;
  if (ivtmp.20D.2115_16 != D.2128_32)
    goto <bb 3>;
  else
    goto <bb 4>;
  # SUCC: 3 [99.0%]  (true,exec) 4 [1.0%]  (false,exec)

  # BLOCK 4 freq:100
  # PRED: 3 [1.0%]  (false,exec)
  # .MEMD.2094_14 = VDEF <.MEMD.2094_13>
  dstD.1321 = srcD.1320;
  # SUCC: 5 [100.0%]  (fallthru,exec)

  # BLOCK 5 freq:1815
  # PRED: 7 [98.9%]  (true,exec) 4 [100.0%]  (fallthru,exec)
  # iD.1319_19 = PHI <iD.1319_9(7), 0(4)>
  # ivtmp.25D.2120_17 = PHI <ivtmp.25D.2120_10(7), ivtmp.25D.2120_26(4)>
  # VUSE <.MEMD.2094_14>
  D.2091_7 = MEM[index: ivtmp.25D.2120_17];
  ivtmp.25D.2120_10 = ivtmp.25D.2120_17 + 1;
  D.2090_22 = (unsigned charD.10) iD.1319_19;
  if (D.2091_7 != D.2090_22)
    goto <bb 6>;
  else
    goto <bb 7>;
  # SUCC: 6 [4.5%]  (true,exec) 7 [95.5%]  (false,exec)

  # BLOCK 6 freq:82
  # PRED: 5 [4.5%]  (true,exec)
  # VUSE <.MEMD.2094_14>
  abortD.823 ();
  # SUCC:

  # BLOCK 7 freq:1733
  # PRED: 5 [95.5%]  (false,exec)
  iD.1319_9 = iD.1319_19 + 1;
  if (iD.1319_9 != 100)
    goto <bb 5>;
  else
    goto <bb 8>;
  # SUCC: 5 [98.9%]  (true,exec) 8 [1.1%]  (false,exec)

  # BLOCK 8 freq:18
  # PRED: 7 [1.1%]  (false,exec)
  # VUSE <.MEMD.2094_14>
  exitD.869 (0);
  # SUCC:

}


Partition 0: size 100 align 1
	srcD.1320, offset 0
Partition 1: size 100 align 1
	dstD.1321, offset 0
Inserting a partition copy on edge BB2->BB3 :PART.6 = PART.3
Inserting a partition copy on edge BB2->BB3 :PART.0 = PART.5
Inserting a value copy on edge BB4->BB5 : PART.2 = 0

;; Generating RTL for gimple basic block 2

;; ivtmp.20_23 = (unsigned int) &src[0];

(insn 114 113 0 memcpy-1.c:19 (set (reg:HI 152 [ ivtmp.20 ])
        (reg/f:HI 37 virtual-stack-vars)) -1 (nil))

;; ivtmp.25_26 = (unsigned int) &dst[0];

(insn 115 114 0 memcpy-1.c:19 (set (reg:HI 150 [ ivtmp.25 ])
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

;; D.2128_32 = src.29_31 + 100;

(insn 116 115 0 memcpy-1.c:5 (set (reg:HI 158 [ D.2128 ])
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

;; Generating RTL for gimple basic block 3

;; MEM[index: ivtmp.20_2] = D.2090_30;

(insn 118 117 119 memcpy-1.c:13 (set (reg:QI 160)
        (minus:QI (subreg:QI (reg:HI 147 [ ivtmp.20 ]) 0)
            (subreg:QI (reg:HI 152 [ ivtmp.20 ]) 0))) -1 (nil))

(insn 119 118 0 memcpy-1.c:13 (set (mem/s/j:QI (reg:HI 147 [ ivtmp.20 ]) [0 src S1 A8])
        (reg:QI 160)) -1 (nil))

;; ivtmp.20_16 = ivtmp.20_2 + 1;

(insn 120 119 0 memcpy-1.c:13 (set (reg:HI 147 [ ivtmp.20 ])
        (plus:HI (reg:HI 147 [ ivtmp.20 ])
            (const_int 1 [0x1]))) -1 (nil))

;; MEM[index: ivtmp.25_24] = 0;

(insn 121 120 0 memcpy-1.c:14 (set (mem/s/j:QI (reg:HI 153 [ ivtmp.25 ]) [0 dst S1 A8])
        (const_int 0 [0x0])) -1 (nil))

;; ivtmp.25_25 = ivtmp.25_24 + 1;

(insn 122 121 0 memcpy-1.c:14 (set (reg:HI 153 [ ivtmp.25 ])
        (plus:HI (reg:HI 153 [ ivtmp.25 ])
            (const_int 1 [0x1]))) -1 (nil))

;; if (ivtmp.20_16 != D.2128_32)

(insn 124 122 125 memcpy-1.c:11 (parallel [
            (set (cc0)
                (compare (reg:HI 147 [ ivtmp.20 ])
                    (reg:HI 158 [ D.2128 ])))
            (clobber (scratch:QI))
        ]) -1 (nil))

(jump_insn 125 124 0 memcpy-1.c:11 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 123)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9899 [0x26ab])
        (nil)))

;; Generating RTL for gimple basic block 4

;; dst = src;

(insn 127 126 128 memcpy-1.c:17 (set (reg/f:HI 161)
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

(insn 128 127 129 memcpy-1.c:17 (set (reg:HI 162)
        (reg/f:HI 161)) -1 (nil))

(insn 129 128 130 memcpy-1.c:17 (set (reg:HI 163)
        (reg/f:HI 37 virtual-stack-vars)) -1 (nil))

(insn 130 129 131 memcpy-1.c:17 (set (reg:QI 164)
        (const_int 100 [0x64])) -1 (nil))

(code_label 131 130 132 3 "" [0 uses])

(insn 132 131 133 memcpy-1.c:17 (set (reg:QI 0 r0)
        (mem:QI (reg:HI 163) [0 S1 A8])) -1 (nil))

(insn 133 132 134 memcpy-1.c:17 (set (reg:HI 163)
        (plus:HI (reg:HI 163)
            (const_int 1 [0x1]))) -1 (nil))

(insn 134 133 135 memcpy-1.c:17 (set (mem:QI (reg:HI 162) [0 S1 A8])
        (reg:QI 0 r0)) -1 (nil))

(insn 135 134 136 memcpy-1.c:17 (set (reg:HI 162)
        (plus:HI (reg:HI 162)
            (const_int 1 [0x1]))) -1 (nil))

(insn 136 135 137 memcpy-1.c:17 (set (reg:QI 164)
        (plus:QI (reg:QI 164)
            (const_int -1 [0xffffffff]))) -1 (nil))

(insn 137 136 138 memcpy-1.c:17 (set (cc0)
        (compare (reg:QI 164)
            (const_int 0 [0x0]))) -1 (nil))

(jump_insn 138 137 0 memcpy-1.c:17 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 131)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9900 [0x26ac])
        (nil)))

;; Generating RTL for gimple basic block 5

;; D.2091_7 = MEM[index: ivtmp.25_17];

(insn 140 139 0 memcpy-1.c:20 (set (reg:QI 148 [ D.2091 ])
        (mem/s/j:QI (reg:HI 150 [ ivtmp.25 ]) [0 dst S1 A8])) -1 (nil))

;; ivtmp.25_10 = ivtmp.25_17 + 1;

(insn 141 140 0 memcpy-1.c:20 (set (reg:HI 150 [ ivtmp.25 ])
        (plus:HI (reg:HI 150 [ ivtmp.25 ])
            (const_int 1 [0x1]))) -1 (nil))

;; if (D.2091_7 != D.2090_22)

(insn 142 141 143 memcpy-1.c:20 (set (cc0)
        (compare (reg:QI 148 [ D.2091 ])
            (subreg:QI (reg/v:HI 149 [ i ]) 0))) -1 (nil))

(jump_insn 143 142 0 memcpy-1.c:20 (set (pc)
        (if_then_else (eq (cc0)
                (const_int 0 [0x0]))
            (label_ref 0)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil)))

;; Generating RTL for gimple basic block 6

;; abort ();

(insn 145 144 146 memcpy-1.c:21 (set (reg:HI 165)
        (reg/f:HI 39 virtual-outgoing-args)) -1 (nil))

(call_insn 146 145 147 memcpy-1.c:21 (call (mem:HI (symbol_ref:HI ("abort") [flags 0x41] <function_decl 0xb7d3ee00 abort>) [0 S2 A8])
        (const_int 0 [0x0])) -1 (expr_list:REG_NORETURN (const_int 0 [0x0])
        (expr_list:REG_EH_REGION (const_int 0 [0x0])
            (nil)))
    (nil))

(barrier 147 146 0)

;; Generating RTL for gimple basic block 7

;; 

(code_label 148 147 149 4 "" [0 uses])

(note 149 148 0 NOTE_INSN_BASIC_BLOCK)

;; i_9 = i_19 + 1;

(insn 150 149 0 memcpy-1.c:19 (set (reg/v:HI 149 [ i ])
        (plus:HI (reg/v:HI 149 [ i ])
            (const_int 1 [0x1]))) -1 (nil))

;; if (i_9 != 100)

(insn 152 150 153 memcpy-1.c:19 (parallel [
            (set (cc0)
                (compare (reg/v:HI 149 [ i ])
                    (const_int 100 [0x64])))
            (clobber (scratch:QI))
        ]) -1 (nil))

(jump_insn 153 152 0 memcpy-1.c:19 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 151)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9894 [0x26a6])
        (nil)))

;; Generating RTL for gimple basic block 8

;; exit (0);

(insn 155 154 156 memcpy-1.c:23 (set (reg:HI 166)
        (reg/f:HI 39 virtual-outgoing-args)) -1 (nil))

(insn 156 155 157 memcpy-1.c:23 (set (reg:HI 24 r24)
        (const_int 0 [0x0])) -1 (nil))

(call_insn 157 156 158 memcpy-1.c:23 (call (mem:HI (symbol_ref:HI ("exit") [flags 0x41] <function_decl 0xb7d43500 exit>) [0 S2 A8])
        (const_int 0 [0x0])) -1 (expr_list:REG_NORETURN (const_int 0 [0x0])
        (expr_list:REG_EH_REGION (const_int 0 [0x0])
            (nil)))
    (expr_list:REG_DEP_TRUE (use (reg:HI 24 r24))
        (nil)))

(barrier 158 157 0)


;;
;; Full RTL generated for this function:
;;

Pass statistics:
----------------

(note 107 0 112 NOTE_INSN_DELETED)

;; Start of basic block ( 0) -> 2
;; Pred edge  ENTRY [100.0%]  (fallthru)
(note 112 107 108 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(note 108 112 113 2 NOTE_INSN_FUNCTION_BEG)
;; End of basic block 2 -> ( 3)

;; Succ edge  3 [100.0%]  (fallthru)

;; Start of basic block ( 2) -> 3
;; Pred edge  2 [100.0%]  (fallthru)
(note 113 108 114 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(insn 114 113 115 3 memcpy-1.c:19 (set (reg:HI 152 [ ivtmp.20 ])
        (reg/f:HI 37 virtual-stack-vars)) -1 (nil))

(insn 115 114 116 3 memcpy-1.c:19 (set (reg:HI 150 [ ivtmp.25 ])
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

(insn 116 115 109 3 memcpy-1.c:5 (set (reg:HI 158 [ D.2128 ])
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

(insn 109 116 110 3 memcpy-1.c:5 (set (reg:HI 153 [ ivtmp.25 ])
        (reg:HI 150 [ ivtmp.25 ])) -1 (nil))

(insn 110 109 123 3 memcpy-1.c:5 (set (reg:HI 147 [ ivtmp.20 ])
        (reg:HI 152 [ ivtmp.20 ])) -1 (nil))
;; End of basic block 3 -> ( 4)

;; Succ edge  4 [100.0%]  (fallthru)

;; Start of basic block ( 4 3) -> 4
;; Pred edge  4 [99.0%] 
;; Pred edge  3 [100.0%]  (fallthru)
(code_label 123 110 117 4 2 "" [1 uses])

(note 117 123 118 4 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 118 117 119 4 memcpy-1.c:13 (set (reg:QI 160)
        (minus:QI (subreg:QI (reg:HI 147 [ ivtmp.20 ]) 0)
            (subreg:QI (reg:HI 152 [ ivtmp.20 ]) 0))) -1 (nil))

(insn 119 118 120 4 memcpy-1.c:13 (set (mem/s/j:QI (reg:HI 147 [ ivtmp.20 ]) [0 src S1 A8])
        (reg:QI 160)) -1 (nil))

(insn 120 119 121 4 memcpy-1.c:13 (set (reg:HI 147 [ ivtmp.20 ])
        (plus:HI (reg:HI 147 [ ivtmp.20 ])
            (const_int 1 [0x1]))) -1 (nil))

(insn 121 120 122 4 memcpy-1.c:14 (set (mem/s/j:QI (reg:HI 153 [ ivtmp.25 ]) [0 dst S1 A8])
        (const_int 0 [0x0])) -1 (nil))

(insn 122 121 124 4 memcpy-1.c:14 (set (reg:HI 153 [ ivtmp.25 ])
        (plus:HI (reg:HI 153 [ ivtmp.25 ])
            (const_int 1 [0x1]))) -1 (nil))

(insn 124 122 125 4 memcpy-1.c:11 (parallel [
            (set (cc0)
                (compare (reg:HI 147 [ ivtmp.20 ])
                    (reg:HI 158 [ D.2128 ])))
            (clobber (scratch:QI))
        ]) -1 (nil))

(jump_insn 125 124 126 4 memcpy-1.c:11 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 123)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9899 [0x26ab])
        (nil))
 -> 123)
;; End of basic block 4 -> ( 4 5)

;; Succ edge  4 [99.0%] 
;; Succ edge  5 [1.0%]  (fallthru)

;; Start of basic block ( 4) -> 5
;; Pred edge  4 [1.0%]  (fallthru)
(note 126 125 127 5 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 127 126 128 5 memcpy-1.c:17 (set (reg/f:HI 161)
        (plus:HI (reg/f:HI 37 virtual-stack-vars)
            (const_int 100 [0x64]))) -1 (nil))

(insn 128 127 129 5 memcpy-1.c:17 (set (reg:HI 162)
        (reg/f:HI 161)) -1 (nil))

(insn 129 128 130 5 memcpy-1.c:17 (set (reg:HI 163)
        (reg/f:HI 37 virtual-stack-vars)) -1 (nil))

(insn 130 129 131 5 memcpy-1.c:17 (set (reg:QI 164)
        (const_int 100 [0x64])) -1 (nil))
;; End of basic block 5 -> ( 6)

;; Succ edge  6 [100.0%]  (fallthru)

;; Start of basic block ( 5 6) -> 6
;; Pred edge  5 [100.0%]  (fallthru)
;; Pred edge  6 [99.0%] 
(code_label 131 130 165 6 3 "" [1 uses])

(note 165 131 132 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

(insn 132 165 133 6 memcpy-1.c:17 (set (reg:QI 0 r0)
        (mem:QI (reg:HI 163) [0 S1 A8])) -1 (nil))

(insn 133 132 134 6 memcpy-1.c:17 (set (reg:HI 163)
        (plus:HI (reg:HI 163)
            (const_int 1 [0x1]))) -1 (nil))

(insn 134 133 135 6 memcpy-1.c:17 (set (mem:QI (reg:HI 162) [0 S1 A8])
        (reg:QI 0 r0)) -1 (nil))

(insn 135 134 136 6 memcpy-1.c:17 (set (reg:HI 162)
        (plus:HI (reg:HI 162)
            (const_int 1 [0x1]))) -1 (nil))

(insn 136 135 137 6 memcpy-1.c:17 (set (reg:QI 164)
        (plus:QI (reg:QI 164)
            (const_int -1 [0xffffffff]))) -1 (nil))

(insn 137 136 111 6 memcpy-1.c:17 (set (cc0)
        (compare (reg:QI 164)
            (const_int 0 [0x0]))) -1 (nil))

(insn 111 137 138 6 memcpy-1.c:19 (set (reg/v:HI 149 [ i ])
        (const_int 0 [0x0])) -1 (nil))

(jump_insn 138 111 151 6 memcpy-1.c:17 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 131)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9900 [0x26ac])
        (nil))
 -> 131)
;; End of basic block 6 -> ( 7 6)

;; Succ edge  7 [1.0%]  (fallthru)
;; Succ edge  6 [99.0%] 

;; Start of basic block ( 9 6) -> 7
;; Pred edge  9 [98.9%] 
;; Pred edge  6 [1.0%]  (fallthru)
(code_label 151 138 139 7 5 "" [1 uses])

(note 139 151 140 7 [bb 7] NOTE_INSN_BASIC_BLOCK)

(insn 140 139 141 7 memcpy-1.c:20 (set (reg:QI 148 [ D.2091 ])
        (mem/s/j:QI (reg:HI 150 [ ivtmp.25 ]) [0 dst S1 A8])) -1 (nil))

(insn 141 140 142 7 memcpy-1.c:20 (set (reg:HI 150 [ ivtmp.25 ])
        (plus:HI (reg:HI 150 [ ivtmp.25 ])
            (const_int 1 [0x1]))) -1 (nil))

(insn 142 141 143 7 memcpy-1.c:20 (set (cc0)
        (compare (reg:QI 148 [ D.2091 ])
            (subreg:QI (reg/v:HI 149 [ i ]) 0))) -1 (nil))

(jump_insn 143 142 144 7 memcpy-1.c:20 (set (pc)
        (if_then_else (eq (cc0)
                (const_int 0 [0x0]))
            (label_ref 148)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9550 [0x254e])
        (nil))
 -> 148)
;; End of basic block 7 -> ( 8 9)

;; Succ edge  8 [4.5%]  (fallthru)
;; Succ edge  9 [95.5%] 

;; Start of basic block ( 7) -> 8
;; Pred edge  7 [4.5%]  (fallthru)
(note 144 143 145 8 [bb 8] NOTE_INSN_BASIC_BLOCK)

(insn 145 144 146 8 memcpy-1.c:21 (set (reg:HI 165)
        (reg/f:HI 39 virtual-outgoing-args)) -1 (nil))

(call_insn 146 145 147 8 memcpy-1.c:21 (call (mem:HI (symbol_ref:HI ("abort") [flags 0x41] <function_decl 0xb7d3ee00 abort>) [0 S2 A8])
        (const_int 0 [0x0])) -1 (expr_list:REG_NORETURN (const_int 0 [0x0])
        (expr_list:REG_EH_REGION (const_int 0 [0x0])
            (nil)))
    (nil))
;; End of basic block 8 -> ()


(barrier 147 146 148)

;; Start of basic block ( 7) -> 9
;; Pred edge  7 [95.5%] 
(code_label 148 147 149 9 4 "" [1 uses])

(note 149 148 150 9 [bb 9] NOTE_INSN_BASIC_BLOCK)

(insn 150 149 152 9 memcpy-1.c:19 (set (reg/v:HI 149 [ i ])
        (plus:HI (reg/v:HI 149 [ i ])
            (const_int 1 [0x1]))) -1 (nil))

(insn 152 150 153 9 memcpy-1.c:19 (parallel [
            (set (cc0)
                (compare (reg/v:HI 149 [ i ])
                    (const_int 100 [0x64])))
            (clobber (scratch:QI))
        ]) -1 (nil))

(jump_insn 153 152 154 9 memcpy-1.c:19 (set (pc)
        (if_then_else (ne (cc0)
                (const_int 0 [0x0]))
            (label_ref 151)
            (pc))) -1 (expr_list:REG_BR_PROB (const_int 9894 [0x26a6])
        (nil))
 -> 151)
;; End of basic block 9 -> ( 7 10)

;; Succ edge  7 [98.9%] 
;; Succ edge  10 [1.1%]  (fallthru)

;; Start of basic block ( 9) -> 10
;; Pred edge  9 [1.1%]  (fallthru)
(note 154 153 155 10 [bb 10] NOTE_INSN_BASIC_BLOCK)

(insn 155 154 156 10 memcpy-1.c:23 (set (reg:HI 166)
        (reg/f:HI 39 virtual-outgoing-args)) -1 (nil))

(insn 156 155 157 10 memcpy-1.c:23 (set (reg:HI 24 r24)
        (const_int 0 [0x0])) -1 (nil))

(call_insn 157 156 158 10 memcpy-1.c:23 (call (mem:HI (symbol_ref:HI ("exit") [flags 0x41] <function_decl 0xb7d43500 exit>) [0 S2 A8])
        (const_int 0 [0x0])) -1 (expr_list:REG_NORETURN (const_int 0 [0x0])
        (expr_list:REG_EH_REGION (const_int 0 [0x0])
            (nil)))
    (expr_list:REG_DEP_TRUE (use (reg:HI 24 r24))
        (nil)))
;; End of basic block 10 -> ()


(barrier 158 157 164)

;; Start of basic block () -> 11
(note 164 158 161 11 [bb 11] NOTE_INSN_BASIC_BLOCK)

(insn 161 164 162 11 memcpy-1.c:24 (clobber (reg/i:HI 24 r24)) -1 (nil))

(insn 162 161 159 11 memcpy-1.c:24 (clobber (reg:HI 159 [ <retval> ])) -1 (nil))
;; End of basic block 11 -> ( 12)

;; Succ edge  12 [100.0%]  (fallthru)

;; Start of basic block ( 11) -> 12
;; Pred edge  11 [100.0%]  (fallthru)
(code_label 159 162 166 12 1 "" [0 uses])

(note 166 159 160 12 [bb 12] NOTE_INSN_BASIC_BLOCK)

(insn 160 166 163 12 memcpy-1.c:24 (set (reg/i:HI 24 r24)
        (reg:HI 159 [ <retval> ])) -1 (nil))

(insn 163 160 0 12 memcpy-1.c:24 (use (reg/i:HI 24 r24)) -1 (nil))
;; End of basic block 12 -> ( 1)

;; Succ edge  EXIT [100.0%]  (fallthru)
Comment 6 Andy Hutchinson 2009-09-27 17:30:19 UTC
Created attachment 18663 [details]
Patch to cfgrtl.c  commit_one_edge_insertion()

The problem is in cfgrtl.c function commit_one_edge_insertion()

It does copy value for phi nodes to previous edge. If it find jump on edge it  places copy before it. It assumes that edge is fall thru edge.
For a fall thru edge, the last instruction can be anything - specifically a jump just created by RTL expander.

The bug has been present since Rev 146817

I have attached patch that correct the problem.


Index: cfgrtl.c
===================================================================
--- cfgrtl.c	(revision 152217)
+++ cfgrtl.c	(working copy)
@@ -1482,8 +1482,9 @@
 	     happens on the fr30 for example.
 
 	     We know this block has a single successor, so we can just emit
-	     the queued insns before the jump.  */
-	  if (JUMP_P (BB_END (bb)))
+	     the queued insns before the jump. Fallthru edges can have
+ 	     jumps created by RTL expander, so ignore these.  */
+	  if (!(e->flags & EDGE_FALLTHRU) && JUMP_P (BB_END (bb)))
 	    before = BB_END (bb);
 	  else
 	    {
Comment 7 Michael Matz 2009-09-27 21:19:19 UTC
As per private communication, you can't do it this way.  You'd loose the
effect of the inserted insn, as the jump jumps over it.  You need to search
backward from the jump to the cc0 setter and insert it in front of that one.
Look at insert_insn_end_bb_new for an example.
Comment 8 Andy Hutchinson 2009-10-01 01:49:48 UTC
Created attachment 18681 [details]
Fix

After lengthy and productive correspondence with Michael Matz, we have arrived at a conclusion.

The patch above is ok but it is preferred to fix the problem at the point of RTL expansion. A block that ends with a jump created by RTL expander on an otherwise fallthru edge, is padded with mov(r,r) NOP. Thus commit_one_edge_insertion() will no longer find and interpret this as a jump to successor causing the insertion point to be wrong.
The problem breaks cc0 targets during CSE. Non cc0 targets can equally get erroneous insertion made inside RTL expander loop pattern. These may or may not break.

Regression tested on Rev15226 (20090927)
Native configuration  i686-pc-linux-gnu with no regression on C tests (G++ still running) 
Also
Target is avr-unknown-none
Host   is i686-pc-linux-gnu
Producing 28 less failure on C testsuite, no regressions.

2009-09-30  Andy Hutchinson <hutchinsonandy@gcc.gnu.org>

	PR middle-end/41440
	* cfgexpand.c (expand_gimple_basic_block): Append NOP to a fallthru,
	single successor block, ending with jump created by RTL expander.
Comment 9 Andy Hutchinson 2009-10-02 00:30:12 UTC
Checked earlier version. They all insert on edge before RTL is expanded.
Making this 4.5 regression.
Comment 10 Andy Hutchinson 2009-11-12 02:36:07 UTC
Subject: Bug 41440

Author: hutchinsonandy
Date: Thu Nov 12 02:35:49 2009
New Revision: 154112

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=154112
Log:
PR middle-end/41440
* cfgexpand.c (expand_gimple_basic_block): Append NOP to a fallthru,
single successor block, ending with jump created by RTL expander.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cfgexpand.c

Comment 11 Andy Hutchinson 2009-11-22 18:59:47 UTC
Fixed.
Comment 12 Eric Weddington 2010-01-29 16:33:54 UTC
Setting target milestone.