This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/41440] New: SEG FAULT in CSE.C caused by bad RTL expansion


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]