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; }") -- Summary: SEG FAULT in CSE.C caused by bad RTL expansion Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: hutchinsonandy at gcc dot gnu dot org GCC host triplet: i686-pc-linux-gnu GCC target triplet: avr-unknown-none http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41440