re PR target/40971 (ICE in memory_address)
authorJakub Jelinek <jakub@redhat.com>
Tue, 18 Aug 2009 11:42:07 +0000 (13:42 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 18 Aug 2009 11:42:07 +0000 (13:42 +0200)
PR target/40971
* config/rs6000/rs6000.c (rs6000_legitimize_address): For
[DT][FDI]mode ensure the offset isn't 4/8/12 bytes below 0x8000.

* gcc.dg/pr40971.c: New test.

From-SVN: r150869

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr40971.c [new file with mode: 0644]

index e684f7a..adbf70f 100644 (file)
@@ -3,6 +3,10 @@
        * bb-reorder.c (fix_up_fall_thru_edges): Only call invert_jump
        on jumps.
 
+       PR target/40971
+       * config/rs6000/rs6000.c (rs6000_legitimize_address): For
+       [DT][FDI]mode ensure the offset isn't 4/8/12 bytes below 0x8000.
+
 2009-08-17  DJ Delorie  <dj@redhat.com>
 
        * config/m32c/m32c.md (UNS_FSETB, UNS_FREIT): New.
index 8c0feb5..b4a0592 100644 (file)
@@ -4857,6 +4857,8 @@ static rtx
 rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
                           enum machine_mode mode)
 {
+  unsigned int extra = 0;
+
   if (!reg_offset_addressing_ok_p (mode))
     {
       if (virtual_stack_registers_memory_p (x))
@@ -4881,10 +4883,33 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       if (model != 0)
        return rs6000_legitimize_tls_address (x, model);
     }
+
+  switch (mode)
+    {
+    case DFmode:
+    case DDmode:
+      extra = 4;
+      break;
+    case DImode:
+      if (!TARGET_POWERPC64)
+       extra = 4;
+      break;
+    case TFmode:
+    case TDmode:
+      extra = 12;
+      break;
+    case TImode:
+      extra = TARGET_POWERPC64 ? 8 : 12;
+      break;
+    default:
+      break;
+    }
+
   if (GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 0)) == REG
       && GET_CODE (XEXP (x, 1)) == CONST_INT
-      && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000
+      && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
+         >= 0x10000 - extra)
       && !((TARGET_POWERPC64
            && (mode == DImode || mode == TImode)
            && (INTVAL (XEXP (x, 1)) & 3) != 0)
@@ -4896,10 +4921,12 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       HOST_WIDE_INT high_int, low_int;
       rtx sum;
       low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;
+      if (low_int >= 0x8000 - extra)
+       low_int = 0;
       high_int = INTVAL (XEXP (x, 1)) - low_int;
       sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
                                         GEN_INT (high_int)), 0);
-      return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
+      return plus_constant (sum, low_int);
     }
   else if (GET_CODE (x) == PLUS
           && GET_CODE (XEXP (x, 0)) == REG
index 8a05c84..e1c0885 100644 (file)
@@ -1,3 +1,8 @@
+2009-08-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/40971
+       * gcc.dg/pr40971.c: New test.
+
 2008-08-17  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/41062
diff --git a/gcc/testsuite/gcc.dg/pr40971.c b/gcc/testsuite/gcc.dg/pr40971.c
new file mode 100644 (file)
index 0000000..31dfd5e
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR target/40971 */
+/* { dg-do compile } */
+/* { dg-options "-O -fstack-protector -fno-strict-aliasing" } */
+/* { dg-require-effective-target fstack_protector } */
+
+extern void bar (char *);
+
+void
+foo (int f, long a)
+{
+  {
+    char d[32768];
+    bar (d);
+  }
+  double b = f;
+  while (a)
+    {
+      char c[sizeof (double)];
+      __builtin_memcpy (c, &b, sizeof (c));
+      if (*(double *) c != 2.0)
+       break;
+    }
+}