This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Segfault in rtx_varies_p
- From: Paul Brook <paul at nowt dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Tue, 17 Feb 2004 14:20:03 +0000
- Subject: [PATCH] Segfault in rtx_varies_p
When complied with -O2 on arm-none-elf, the following testcase causes a
segfault.
static const char digs[] = "0123456789ABCDEF";
int __attribute__((pure)) bar();
int foo (int i)
{
int len;
if (i)
return 0;
len = bar();
return digs[len];
}
For the call to bar() we generate a libcall sequence. This includes a
REG_EQUAL note containing a EXPR_LIST of the parameters of the libcall (and
symbol for bar).
(insn (set (reg 101) (...))
(insn_list:REG_RETVAL ...
(expr_list:REG_EQUAL (expr_list (use (mem:blk scratch))
(expr_list (symbol_ref "bar")
(nil)))))
(nil))
(insn (set (reg 102) (symbol_ref "digs)))
(insn (set (reg 103) (mem (plus (reg 101) (reg 102))))
(expr_list:REG_EQUAL (plus (reg 101) (symbol_ref "bar")))
(nil))
During the gcse pass we then propagate the equality for reg101 from the first
REG_EQUAL note into the second REG_EQUAL note (the code for for digs[len]).
In a later pass rtx_varies_p falls over on the NULL terminator of the
EXPR_LIST.
I've reproduced this problem on 3.4 and mainline. I haven't managed to
reproduce on 3.3 or on other architectures.
Solution A is to prevent the substitution of an EXPR_LIST from a REG_EQUAL
note in cases where it may cause problems. Ignoring these altogether inhibits
cse of libcalls, so is not desirable.
Solution B is to make rtx_varies_p return 0 when it encounters a NULL rtx.
I don't know enought about the operation of cse to tell which is best, or to
easily implement A. Patch implementing B is appended.
Tested with cross-compiler to arm-non-elf and boostrap in i686-linux.
Ok for mainline, 3.4 branch and csl-arm-branch?
Paul
2004-02-17 Paul Brook <paul@codesourcery.com>
* rtlanal.c (rtx_varies_p): Return 0 for NULL_RTX
Index: rtlanal.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/rtlanal.c,v
retrieving revision 1.177
diff -u -p -r1.177 rtlanal.c
--- a/rtlanal.c 6 Feb 2004 04:28:46 -0000 1.177
+++ b/rtlanal.c 17 Feb 2004 00:42:12 -0000
@@ -134,10 +134,14 @@ rtx_unstable_p (rtx x)
int
rtx_varies_p (rtx x, int for_alias)
{
- RTX_CODE code = GET_CODE (x);
+ RTX_CODE code;
int i;
const char *fmt;
+ if (!x)
+ return 0;
+
+ code = GET_CODE (x);
switch (code)
{
case MEM: