970904 signal 6 in compile
Jeffrey A Law
law@cygnus.com
Sun Sep 14 10:12:00 GMT 1997
In message <19970907213107.61474@inetnebr.com>you write:
> Trying to compile mutt-0.81's rfc1524.c, I get signal 6 with 970904 and
> also whichever was 2.90.01. Compiles fine with 2.7.2.1.
Thanks.
This is a bug in the new regmove pass.
The basic problem is regmove is losing a REG_UNUSED note, which
later causes local-alloc.c to crash because it was unable to find
the death of a register that was supposed to be local to a particular
basic block.
Tege -- there's a testcase attached, it should probably be
added to c-torture/compile.
Jim/Joern -- note egcs has the regmove before Joern revamped it; the
new regmove code may not trip over this testcase, but I believe it
has the same problem.
This particular instance of the problem will show up with the latest
egcs snapshot on an x86 with -O2.
I also believe the same problem crops up in unsorted/udivmod4.c
on the H8. I analyzed it a few months back and never followed
through to a fix.
In .combine we have:
(insn 45 44 47 (parallel[
(set (reg:SI 31)
(unspec:SI[
(mem:BLK (reg/v:SI 23))
(const_int 1)
(reg:SI 32)
] 0))
(clobber (reg:SI 32))
] ) 384 {strlensi_unroll5} (insn_list 42 (nil))
(expr_list:REG_UNUSED (reg:SI 32)
(nil)))
[ ... ]
(insn 49 47 51 (set (reg:SI 34)
(reg/v:SI 23)) 52 {movsi+1} (nil)
(nil))
[ ... ]
(insn 64 60 66 (set (mem:QI (plus:SI (plus:SI (reg:SI 31)
(reg:SI 35))
(const_int -1)))
(const_int 0)) 64 {movqi+1} (insn_list 56 (insn_list 45 (nil)))
(expr_list:REG_DEAD (reg:SI 35)
(expr_list:REG_DEAD (reg:SI 31)
(nil))))
Note the REG_UNUSED note on insn 45. We're going to lose that note.
regmove decides to replace reg31 with reg23 in insn 45 to satisfy
a matching constraint.
The next use of reg31 is insn 64. Reg23 is used between insn 45 and
insn 64. So we fall into the following code to move insn 45 to
just before insn 64.
{
emit_insn_after_with_line_notes
(pat, PREV_INSN (p), insn);
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
/* emit_insn_after_with_line_notes
has no return value, so search
for the new insn. */
for (insn = p; PATTERN (insn) != pat; )
insn = PREV_INSN (insn);
}
We take the pattern for insn45, reemit it as a new insn (70) just
before insn 64. Note that we don't bother restoring any remaining
REG_NOTES from insn 45.
[ ... after regmove ... ]
(insn 70 60 64 (parallel[
(set (reg/v:SI 23)
(unspec:SI[
(mem:BLK (reg/v:SI 23))
(const_int 1)
(reg:SI 32)
] 0))
(clobber (reg:SI 32))
] ) 384 {strlensi_unroll5} (nil)
(nil))
(insn 64 70 66 (set (mem:QI (plus:SI (plus:SI (reg/v:SI 23)
(reg/v:SI 24))
(const_int -1)))
(const_int 0)) 64 {movqi+1} (insn_list 56 (insn_list 45 (nil)))
(expr_list:REG_DEAD (reg/v:SI 24)
(expr_list:REG_DEAD (reg/v:SI 23)
(nil))))
This causes local-alloc.c not to find the death of reg32 (insn 70),
which in turn causes local-alloc.c to abort.
I'm not too familiar with regmove's note handling, but I _think_ all
we need to do is to make sure to copy any remaining notes from the
original insn to the new insn.
Here's the testcase:
int rfc1524_expand_filename (char *nametemplate,
char *oldfile,
char *newfile,
int nflen)
{
strncpy( newfile + strlen(newfile) ,
nametemplate , nflen - strlen(newfile) ), *( newfile + strlen(newfile) +( nflen - strlen(newfile) )-1)=0 ;
}
Any my fix:
* regmove.c (regmove_optimize): If we end up moving the
original insn due to lifetime overlaps, make sure to move
REG_NOTES too.
Index: regmove.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/regmove.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 regmove.c
*** regmove.c 1997/09/08 16:06:17 1.2
--- regmove.c 1997/09/14 17:04:29
*************** regmove_optimize (f, nregs, regmove_dump
*** 515,520 ****
--- 515,522 ----
else
#endif
{
+ rtx notes = REG_NOTES (insn);
+
emit_insn_after_with_line_notes
(pat, PREV_INSN (p), insn);
PUT_CODE (insn, NOTE);
*************** regmove_optimize (f, nregs, regmove_dump
*** 525,530 ****
--- 527,534 ----
for the new insn. */
for (insn = p; PATTERN (insn) != pat; )
insn = PREV_INSN (insn);
+
+ REG_NOTES (insn) = notes;
}
}
/* Sometimes we'd generate src = const; src += n;
More information about the Gcc-bugs
mailing list