re PR target/52698 (-maddress-mode=long doesn't work)
authorUros Bizjak <uros@gcc.gnu.org>
Tue, 27 Mar 2012 15:36:34 +0000 (17:36 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Tue, 27 Mar 2012 15:36:34 +0000 (17:36 +0200)
PR target/52698
* config/i386/i386-protos.h (ix86_legitimize_reload_address):
New prototype.
* config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): New define.
* config/i386/i386.c: Include reload.h.
(ix86_legitimize_reload_address): New function.

testsuite/ChangeLog:

PR target/52698
* gcc.target/i386/pr52698.c: New test.

From-SVN: r185883

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr52698.c [new file with mode: 0644]

index b7736fb..6cc1653 100644 (file)
@@ -1,9 +1,17 @@
+2012-03-27  Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/52698
+       * config/i386/i386-protos.h (ix86_legitimize_reload_address):
+       New prototype.
+       * config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): New define.
+       * config/i386/i386.c: Include reload.h.
+       (ix86_legitimize_reload_address): New function.
+
 2012-03-27  H.J. Lu  <hongjiu.lu@intel.com>
 
        * opth-gen.awk: Allocated a bit for Mask and InverseMask if it
        hasn't been allocated.  Define a target macro for Mask and
-       InverseMask if it hasn't been defined.  Remove MaskExists
-       handling.
+       InverseMask if it hasn't been defined.  Remove MaskExists handling.
 
        * doc/options.texi: Remove MaskNeeded.
 
index 630112f..f300a56 100644 (file)
@@ -65,7 +65,8 @@ extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx);
 extern bool constant_address_p (rtx);
 extern bool legitimate_pic_operand_p (rtx);
 extern bool legitimate_pic_address_disp_p (rtx);
-
+extern bool ix86_legitimize_reload_address (rtx, enum machine_mode,
+                                           int, int, int);
 extern void print_reg (rtx, int, FILE*);
 extern void ix86_print_operand (FILE *, rtx, int);
 
index a21f2da..18172a1 100644 (file)
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target-def.h"
 #include "common/common-target.h"
 #include "langhooks.h"
+#include "reload.h"
 #include "cgraph.h"
 #include "gimple.h"
 #include "dwarf2.h"
@@ -12010,6 +12011,64 @@ legitimate_pic_address_disp_p (rtx disp)
   return false;
 }
 
+/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS.  Returns a value to
+   replace the input X, or the original X if no replacement is called for.
+   The output parameter *WIN is 1 if the calling macro should goto WIN,
+   0 if it should not.  */
+
+bool
+ix86_legitimize_reload_address (rtx x,
+                               enum machine_mode mode ATTRIBUTE_UNUSED,
+                               int opnum, int type,
+                               int ind_levels ATTRIBUTE_UNUSED)
+{
+  /* Reload can generate:
+
+     (plus:DI (plus:DI (unspec:DI [(const_int 0 [0])] UNSPEC_TP)
+                      (reg:DI 97))
+             (reg:DI 2 cx))
+
+     This RTX is rejected from ix86_legitimate_address_p due to
+     non-strictness of base register 97.  Following this rejection, 
+     reload pushes all three components into separate registers,
+     creating invalid memory address RTX.
+
+     Following code reloads only the invalid part of the
+     memory address RTX.  */
+
+  if (GET_CODE (x) == PLUS
+      && REG_P (XEXP (x, 1))
+      && GET_CODE (XEXP (x, 0)) == PLUS
+      && REG_P (XEXP (XEXP (x, 0), 1)))
+    {
+      rtx base, index;
+      bool something_reloaded = false;
+
+      base = XEXP (XEXP (x, 0), 1);      
+      if (!REG_OK_FOR_BASE_STRICT_P (base))
+       {
+         push_reload (base, NULL_RTX, &XEXP (XEXP (x, 0), 1), NULL,
+                      BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+                      opnum, (enum reload_type) type);
+         something_reloaded = true;
+       }
+
+      index = XEXP (x, 1);
+      if (!REG_OK_FOR_INDEX_STRICT_P (index))
+       {
+         push_reload (index, NULL_RTX, &XEXP (x, 1), NULL,
+                      INDEX_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+                      opnum, (enum reload_type) type);
+         something_reloaded = true;
+       }
+
+      gcc_assert (something_reloaded);
+      return true;
+    }
+
+  return false;
+}
+
 /* Recognizes RTL expressions that are valid memory addresses for an
    instruction.  The MODE argument is the machine mode for the MEM
    expression that wants to use this address.
index 3fcd209..a53c70a 100644 (file)
@@ -1630,6 +1630,17 @@ typedef struct ix86_args {
 
 #define CONSTANT_ADDRESS_P(X)  constant_address_p (X)
 
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.  */
+
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN)     \
+do {                                                                   \
+  if (ix86_legitimize_reload_address ((X), (MODE), (OPNUM),            \
+                                     (int)(TYPE), (INDL)))             \
+    goto WIN;                                                          \
+} while (0)
+
 /* If defined, a C expression to determine the base term of address X.
    This macro is used in only one place: `find_base_term' in alias.c.
 
index 408184a..a9f0bc8 100644 (file)
@@ -1,3 +1,9 @@
+2012-03-27  Uros Bizjak  <ubizjak@gmail.com>
+           H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR target/52698
+       * gcc.target/i386/pr52698.c: New test.
+
 2012-03-27  Richard Guenther  <rguenther@suse.de>
 
        PR middle-end/52720
diff --git a/gcc/testsuite/gcc.target/i386/pr52698.c b/gcc/testsuite/gcc.target/i386/pr52698.c
new file mode 100644 (file)
index 0000000..d84685c
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
+
+extern void abort (void);
+static __thread unsigned char foo [32]
+__attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))));
+
+void
+test2 (void)
+{
+  unsigned int s;
+  for (s = 0; s < sizeof (foo); ++s)
+    {
+      if (foo [s] != s)
+       abort ();
+      foo [s] = sizeof (foo) - s;
+    }
+}