gcc.c2.95.3 coding error in loop.c?
Anmol Paralkar
aparalka@cisco.com
Sat Mar 6 00:40:00 GMT 2004
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
More information about the Gcc-bugs
mailing list