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]

gcc.c2.95.3 coding error in loop.c?


Hello,

 The following code compiled '-c -fno-inline-functions -O3' with gcc.c2.95.3 causes GCC to seg-fault.

 void bar(int *a, int n) {

         int i, *p, *q;

         p = a;
         q = a + 1;

         for(i = 0; i < n; i++) {

                 p = p + 1;
                 if(i) *q = 0;
                 q = q + 1;

         }
 }

 The stack-trace is:

 reg_used_between_p  rtlanal.c:356
 strength_reduce     loop.c:4092
 scan_loop           loop.c:1178
 loop_optimize       loop.c:579
 rest_of_compilation toplev.c:3969
 finish_function     c-decl.c:7344
 yyparse             c-parse.y:313
 compile_file        toplev.c:3280
 main                toplev.c:5488

 This seems to be due to the following coding error in loop.c:4092



 	In loop.c/strength_reduce() (line 4092), reg_used_between_p() is being invoked
 	with the foot and the head of the insn-chain rather than the head and the foot.
 	The chain is to be traversed left (head) to right (foot) from from_insn to to_insn.



 Here's the snippet of code around the reg_used_between_p() invocation:
 ------------------------------------------------------------------------------
          if (bl2
              && bl2->biv_count == 1
              && rtx_equal_p (increment,
                              biv_total_increment (bl2, loop_start, loop_end))
              /* init_insn is only set to insns that are before loop_start
                 without any intervening labels.  */
              && ! reg_set_between_p (bl2->biv->src_reg,
                                      PREV_INSN (bl->init_insn), loop_start)
              /* The register from BL2 must be set before the register from
                 BL is set, or we must be able to move the latter set after
                 the former set.  Currently there can't be any labels
                 in-between when biv_toal_increment returns nonzero both times
                 but we test it here in case some day some real cfg analysis
                 gets used to set always_computable.  */
              && ((loop_insn_first_p (bl2->biv->insn, bl->biv->insn)
                   && no_labels_between_p (bl2->biv->insn, bl->biv->insn))
                  || (! reg_used_between_p (bl->biv->src_reg, bl->biv->insn,
                                            bl2->biv->insn)
                      && no_jumps_between_p (bl->biv->insn, bl2->biv->insn)))
              && validate_change (bl->biv->insn,
                                  &SET_SRC (single_set (bl->biv->insn)),
                                  copy_rtx (src), 0))
------------------------------------------------------------------------------


 Now, let's look at the invocation of reg_used_between_p() (which also
 traverses the insn-chain left to right from beg to end) @ line 4092 in loop.c:


------------------------------------------------------------------------------
Breakpoint 2, no_labels_between_p (beg=0x2dcc10, end=0x2dcd40)
at ../../src/gcc/rtlanal.c:324
324       for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
(cisco-5.0.7-gdb) c
Continuing.

Breakpoint 3, reg_used_between_p (reg=0x2c57f0, from_insn=0x2dcd40,
to_insn=0x2dcc10) at ../../src/gcc/rtlanal.c:353
353       if (from_insn == to_insn)
(cisco-5.0.7-gdb)  p reg -> fld[2].rtx
$9 = (struct rtx_def *) 0x0
(cisco-5.0.7-gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x988cc in reg_used_between_p (reg=0x2c57f0, from_insn=0x0, to_insn=0x2dcc10)
at ../../src/gcc/rtlanal.c:356
356       for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN
(insn))
------------------------------------------------------------------------------

 Observe the invocations:

                    no_labels_between_p (beg=0x2dcc10, end=0x2dcd40)

 reg_used_between_p (reg=0x2c57f0, from_insn=0x2dcd40, to_insn=0x2dcc10)

 no_labels_between_p() has been invoked correctly just before; then, reg_used_between_p()'s
 being invoked with the bounds of the insn-chain REVERSED!!! That's not correct!

 Note: The no_jumps_between_p() call has been incorrectly invoked too.

 Request you to fix this in the mainline GCC sources.

Thanks & Regards,
Anmol P. Paralkar


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