This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.4 PATCH] Fix miscompilation of Ada compiler on Alpha
- From: Eric Botcazou <ebotcazou at act-europe dot fr>
- To: Richard Henderson <rth at redhat dot com>,Mark Mitchell <mark at codesourcery dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Oct 2004 18:41:27 +0200
- Subject: [3.4 PATCH] Fix miscompilation of Ada compiler on Alpha
Hello Richard and Mark,
We very recently discovered that the 3.4.x Ada compiler is miscompiled on
Alpha (alphaev56-dec-osf5.1 but probably present on alpha-*-*), more
precisely the RTL inliner. The problem pertains to the use of (void *)-1 as
the return value of try_to_integrate. I've attached a C testcase that fails
at -O2 because of the bug.
The fix is very safe but it was only tested through a C,C++,Ada bootstrap with
our 3.4.x-based compiler and verifying that the inliner doesn't segfault
anymore, so Richard might want to give it a whirl on a full testing cycle.
OK for 3.4 branch?
2004-10-29 ?Eric Botcazou ?<ebotcazou@act-europe.fr>
Backport from mainline:
2004-02-25 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (alpha_emit_conditional_branch): Don't
use (op0-op1) == 0 if op0 is a pointer.
2004-10-29 ?Eric Botcazou ?<ebotcazou@act-europe.fr>
* gcc.c-torture/execute/20041029-1.c: New test.
--
Eric Botcazou
Index: config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.342.4.12
diff -u -p -r1.342.4.12 alpha.c
--- config/alpha/alpha.c 30 Sep 2004 17:45:48 -0000 1.342.4.12
+++ config/alpha/alpha.c 29 Oct 2004 12:49:09 -0000
@@ -3197,7 +3197,13 @@ alpha_emit_conditional_branch (enum rtx_
/* If the constants doesn't fit into an immediate, but can
be generated by lda/ldah, we adjust the argument and
compare against zero, so we can use beq/bne directly. */
- else if (GET_CODE (op1) == CONST_INT && (code == EQ || code == NE))
+ /* ??? Don't do this when comparing against symbols, otherwise
+ we'll reduce (&x == 0x1234) to (&x-0x1234 == 0), which will
+ be declared false out of hand (at least for non-weak). */
+ else if (GET_CODE (op1) == CONST_INT
+ && (code == EQ || code == NE)
+ && !(symbolic_operand (op0, VOIDmode)
+ || (GET_CODE (op0) == REG && REG_POINTER (op0))))
{
HOST_WIDE_INT v = INTVAL (op1), n = -v;
/* This was failing on Alpha because the comparison (p != -1) was rewritten
as (p+1 != 0) and p+1 isn't allowed to wrap for pointers. */
extern void abort(void);
typedef __SIZE_TYPE__ size_t;
int global;
static void *foo(int p)
{
if (p == 0)
{
global++;
return &global;
}
return (void *)(size_t)-1;
}
int bar(void)
{
void *p;
p = foo(global);
if (p != (void *)(size_t)-1)
return 1;
global++;
return 0;
}
int main(void)
{
global = 1;
if (bar () != 0)
abort();
return 0;
}