This is the mail archive of the gcc-patches@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]

[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;
}

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