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; }")
Created attachment 18632 [details] Expanded RTL Expanded RTL dump
Created attachment 18641 [details] cleanup_cfg dump
Created attachment 18642 [details] ssa dump
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.
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)
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 {
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.
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.
Checked earlier version. They all insert on edge before RTL is expanded. Making this 4.5 regression.
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
Fixed.
Setting target milestone.