mips-protos.h (mips16_gp_pseudo_reg): Remove.
authorRichard Sandiford <rsandifo@redhat.com>
Sun, 28 Sep 2003 07:38:14 +0000 (07:38 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 28 Sep 2003 07:38:14 +0000 (07:38 +0000)
* config/mips/mips-protos.h (mips16_gp_pseudo_reg): Remove.
* config/mips/mips.h (LEGITIMATE_CONSTANT_P): Remove orphaned comment.
* config/mips/mips.c (mips_reloc_offset_ok_p): New function.
(mips_classify_constant): Use it.
(mips_splittable_symbol_p): Add an offset argument.
(mips_classify_address): Adjust call accordingly.
(mips_legitimize_symbol): Handle sdata references with LO_SUM rather
than a relocation unspec.  Update call to mips_splittable_symbol_p.
Generalize the code that copes with symbols + invalid offsets.
(print_operand): Allow '%R' to be applied to small data addresses.
(mips_reloc_string): Remove RELOC_GPREL16.
(mips_sdata_pointer): Renamed from mips16_gp_pseudo_reg.  Return $gp
for TARGET_EXPLICIT_RELOCS.  Return null if we can't use gp-relative
relocation operators.
* config/mips/mips.md (RELOC_GPREL16): Remove.  Shuffle other reloc
constants accordingly.

From-SVN: r71876

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20030928-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/mips-sdata-1.c

index dccdbdab2f4a8faef74c32c4e953a28e2dd0ecec..85be8b51eb7b710aec72658292f57ea0cb962d2b 100644 (file)
@@ -1,3 +1,22 @@
+2003-09-28  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/mips/mips-protos.h (mips16_gp_pseudo_reg): Remove.
+       * config/mips/mips.h (LEGITIMATE_CONSTANT_P): Remove orphaned comment.
+       * config/mips/mips.c (mips_reloc_offset_ok_p): New function.
+       (mips_classify_constant): Use it.
+       (mips_splittable_symbol_p): Add an offset argument.
+       (mips_classify_address): Adjust call accordingly.
+       (mips_legitimize_symbol): Handle sdata references with LO_SUM rather
+       than a relocation unspec.  Update call to mips_splittable_symbol_p.
+       Generalize the code that copes with symbols + invalid offsets.
+       (print_operand): Allow '%R' to be applied to small data addresses.
+       (mips_reloc_string): Remove RELOC_GPREL16.
+       (mips_sdata_pointer): Renamed from mips16_gp_pseudo_reg.  Return $gp
+       for TARGET_EXPLICIT_RELOCS.  Return null if we can't use gp-relative
+       relocation operators.
+       * config/mips/mips.md (RELOC_GPREL16): Remove.  Shuffle other reloc
+       constants accordingly.
+
 2003-09-27  Roger Sayle  <roger@eyesopen.com>
 
        * toplev.c (flag_evaluation_order): New global variable.
index d215a7fe6bca22bbb6c89dd793b641699e6122d0..d057d17111a150265b69b0c43a2243c2123187e5 100644 (file)
@@ -128,7 +128,6 @@ extern enum reg_class mips_secondary_reload_class (enum reg_class,
                                                   rtx, int);
 extern int mips_class_max_nregs (enum reg_class, enum machine_mode);
 extern bool mips_valid_pointer_mode (enum machine_mode);
-extern struct rtx_def *mips16_gp_pseudo_reg (void);
 extern int build_mips16_call_stub (rtx, rtx, rtx, int);
 extern int mips_register_move_cost (enum machine_mode, enum reg_class,
                                    enum reg_class);
index 19cc43949c954a72875cd0c6e41bebc4e88498e0..fe6510b087d872c587e61bc0b01a69e15f2e657f 100644 (file)
@@ -170,6 +170,8 @@ struct mips_arg_info;
 struct mips_constant_info;
 struct mips_address_info;
 struct mips_integer_op;
+
+static bool mips_reloc_offset_ok_p (int, HOST_WIDE_INT);
 static enum mips_constant_type
   mips_classify_constant (struct mips_constant_info *, rtx);
 static enum mips_symbol_type mips_classify_symbol (rtx);
@@ -179,7 +181,7 @@ static bool mips_symbolic_address_p (rtx, HOST_WIDE_INT,
 static enum mips_address_type
   mips_classify_address (struct mips_address_info *, rtx,
                         enum machine_mode, int, int);
-static bool mips_splittable_symbol_p (enum mips_symbol_type);
+static bool mips_splittable_symbol_p (enum mips_symbol_type, HOST_WIDE_INT);
 static int mips_symbol_insns (enum mips_symbol_type);
 static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
 static rtx mips_reloc (rtx, int);
@@ -235,6 +237,7 @@ static void mips_select_section (tree, int, unsigned HOST_WIDE_INT)
                                  ATTRIBUTE_UNUSED;
 static bool mips_in_small_data_p (tree);
 static void mips_encode_section_info (tree, rtx, int);
+static rtx mips_sdata_pointer (void);
 static void mips16_fp_args (FILE *, int, int);
 static void build_mips16_function_stub (FILE *);
 static void mips16_optimize_gp (void);
@@ -785,6 +788,40 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
+/* Return true if RELOC is a valid relocation number and OFFSET can be
+   added to the relocation symbol.
+
+   Note that OFFSET might not refer to part of the object.   For example,
+   in an expression like x[i - 0x12345], we might try to take the address
+   of "x - 0x12345".  */
+
+static bool
+mips_reloc_offset_ok_p (int reloc, HOST_WIDE_INT offset)
+{
+  switch (reloc)
+    {
+    case RELOC_GOT_PAGE:
+      /* The linker should provide enough page entries to cope with
+        16-bit offsets from a valid segment address.  */
+      return SMALL_OPERAND (offset);
+
+    case RELOC_GOT_HI:
+    case RELOC_GOT_LO:
+    case RELOC_GOT_DISP:
+    case RELOC_CALL16:
+    case RELOC_CALL_HI:
+    case RELOC_CALL_LO:
+    case RELOC_LOADGP_HI:
+    case RELOC_LOADGP_LO:
+      /* These relocations should be applied to bare symbols only.  */
+      return offset == 0;
+
+    default:
+      return false;
+    }
+}
+
+
 /* If X is one of the constants described by mips_constant_type,
    store its components in INFO and return its type.  */
 
@@ -806,25 +843,10 @@ mips_classify_constant (struct mips_constant_info *info, rtx x)
          x = XEXP (x, 0);
        }
       info->symbol = x;
-      if (GET_CODE (x) == UNSPEC)
-       switch (XINT (x, 1))
-         {
-         case RELOC_GPREL16:
-         case RELOC_GOT_PAGE:
-           /* These relocations can be applied to symbols with offsets.  */
-           return CONSTANT_RELOC;
-
-         case RELOC_GOT_HI:
-         case RELOC_GOT_LO:
-         case RELOC_GOT_DISP:
-         case RELOC_CALL16:
-         case RELOC_CALL_HI:
-         case RELOC_CALL_LO:
-         case RELOC_LOADGP_HI:
-         case RELOC_LOADGP_LO:
-           /* These relocations should be applied to bare symbols only.  */
-           return (info->offset == 0 ? CONSTANT_RELOC : CONSTANT_NONE);
-         }
+
+      if (GET_CODE (x) == UNSPEC
+         && mips_reloc_offset_ok_p (XINT (x, 1), info->offset))
+       return CONSTANT_RELOC;
     }
   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
     return CONSTANT_SYMBOLIC;
@@ -997,7 +1019,8 @@ mips_classify_address (struct mips_address_info *info, rtx x,
          && mips_valid_base_register_p (XEXP (x, 0), mode, strict)
          && (mips_classify_constant (&info->c, XEXP (x, 1))
              == CONSTANT_SYMBOLIC)
-         && mips_splittable_symbol_p (mips_classify_symbol (info->c.symbol)))
+         && mips_splittable_symbol_p (mips_classify_symbol (info->c.symbol),
+                                      info->c.offset))
        {
          info->reg = XEXP (x, 0);
          info->offset = XEXP (x, 1);
@@ -1027,16 +1050,28 @@ mips_classify_address (struct mips_address_info *info, rtx x,
 }
 \f
 /* Return true if symbols of the given type can be split into a
-   HIGH/LO_SUM pair.  */
+   high part and a LO_SUM.  In the case of small data symbols,
+   the high part will be $gp.  */
 
 static bool
-mips_splittable_symbol_p (enum mips_symbol_type type)
+mips_splittable_symbol_p (enum mips_symbol_type type, HOST_WIDE_INT offset)
 {
-  if (TARGET_EXPLICIT_RELOCS)
-    return (type == SYMBOL_GENERAL || type == SYMBOL_GOT_LOCAL);
-  if (mips_split_addresses)
-    return (type == SYMBOL_GENERAL);
-  return false;
+  switch (type)
+    {
+    case SYMBOL_GENERAL:
+      return TARGET_EXPLICIT_RELOCS || mips_split_addresses;
+
+    case SYMBOL_GOT_LOCAL:
+      return TARGET_EXPLICIT_RELOCS && SMALL_OPERAND (offset);
+
+    case SYMBOL_SMALL_DATA:
+      return ((TARGET_EXPLICIT_RELOCS || TARGET_MIPS16)
+             && (offset == 0
+                 || (offset > 0 && offset <= mips_section_threshold)));
+
+    default:
+      return false;
+    }
 }
 
 
@@ -1642,6 +1677,7 @@ mips_emit_high (rtx dest, rtx addr)
   return x;
 }
 
+
 /* See if *XLOC is a symbolic constant that can be reduced in some way.
    If it is, set *XLOC to the reduced expression and return true.
    The new expression will be both a legitimate address and a legitimate
@@ -1663,46 +1699,27 @@ mips_legitimize_symbol (rtx dest, rtx *xloc, int offsetable_p)
 
   symbol_type = mips_classify_symbol (c.symbol);
 
-  /* Convert a mips16 reference to the small data section into
-     an address of the form:
-
-       (plus BASE (const (plus (unspec [SYMBOL] UNSPEC_GPREL) OFFSET)))
-
-     BASE is the pseudo created by mips16_gp_pseudo_reg.
-     The (const ...) may include an offset.  */
-  if (TARGET_MIPS16
-      && symbol_type == SYMBOL_SMALL_DATA
-      && !no_new_pseudos)
-    {
-      *xloc = gen_rtx_PLUS (Pmode, mips16_gp_pseudo_reg (),
-                           mips_reloc (*xloc, RELOC_GPREL16));
-      return true;
-    }
-
-  /* Likewise for normal-mode code.  In this case we can use $gp
-     as a base register.  */
-  if (!TARGET_MIPS16
-      && TARGET_EXPLICIT_RELOCS
-      && symbol_type == SYMBOL_SMALL_DATA)
+  /* If a non-offsetable address is OK, try splitting it into a
+     high part and a LO_SUM.  */
+  if (!offsetable_p && mips_splittable_symbol_p (symbol_type, c.offset))
     {
-      *xloc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
-                           mips_reloc (*xloc, RELOC_GPREL16));
-      return true;
+      if (symbol_type == SYMBOL_SMALL_DATA)
+       x = mips_sdata_pointer ();
+      else
+       x = mips_emit_high (dest, *xloc);
+      if (x != 0)
+       {
+         *xloc = gen_rtx_LO_SUM (Pmode, x, copy_rtx (*xloc));
+         return true;
+       }
     }
 
-  /* If a non-offsetable address is OK, convert general symbols into
-     a HIGH/LO_SUM pair.  */
-  if (!offsetable_p && mips_splittable_symbol_p (symbol_type))
-    {
-      x = mips_emit_high (dest, *xloc);
-      *xloc = gen_rtx_LO_SUM (Pmode, x, copy_rtx (*xloc));
-      return true;
-    }
+  /* If the offset is nonzero, move the symbol into a register (always valid)
+     and add the constant in afterwards.  This requires an extra temporary if
+     the offset isn't a signed 16-bit number.
 
-  /* If generating PIC, and ADDR is a global symbol with an offset,
-     load the symbol into a register and apply the offset separately.
-     We need a temporary when adding large offsets.  */
-  if (symbol_type == SYMBOL_GOT_GLOBAL
+     For mips16, it's better to force the constant into memory instead.  */
+  if (!TARGET_MIPS16
       && c.offset != 0
       && (SMALL_OPERAND (c.offset) || dest == 0))
     {
@@ -5257,17 +5274,7 @@ print_operand (FILE *file, rtx op, int letter)
 
   code = GET_CODE (op);
 
-  if (letter == 'R')
-    {
-      if (TARGET_ABICALLS && TARGET_NEWABI)
-       fputs ("%got_ofst(", file);
-      else
-       fputs ("%lo(", file);
-      output_addr_const (file, op);
-      fputc (')', file);
-    }
-
-  else if (letter == 'h')
+  if (letter == 'h')
     {
       if (GET_CODE (op) != HIGH)
        abort ();
@@ -5403,8 +5410,22 @@ print_operand (FILE *file, rtx op, int letter)
   else
     switch (mips_classify_constant (&c, op))
       {
-      case CONSTANT_NONE:
       case CONSTANT_SYMBOLIC:
+       if (letter == 'R')
+         {
+           if (mips_classify_symbol (c.symbol) == SYMBOL_SMALL_DATA)
+             fputs (TARGET_MIPS16 ? "%gprel(" : "%gp_rel(", file);
+           else if (TARGET_ABICALLS && TARGET_NEWABI)
+             fputs ("%got_ofst(", file);
+           else
+             fputs ("%lo(", file);
+           output_addr_const (file, op);
+           fputc (')', file);
+           break;
+         }
+       /* ... fall through ... */
+
+      case CONSTANT_NONE:
        output_addr_const (file, op);
        break;
 
@@ -5430,7 +5451,6 @@ mips_reloc_string (int reloc)
 {
   switch (reloc)
     {
-    case RELOC_GPREL16:          return (TARGET_MIPS16 ? "%gprel(" : "%gp_rel(");
     case RELOC_GOT_HI:   return "%got_hi(";
     case RELOC_GOT_LO:   return "%got_lo(";
     case RELOC_GOT_PAGE:  return (TARGET_NEWABI ? "%got_page(" : "%got(");
@@ -7768,13 +7788,22 @@ mips_valid_pointer_mode (enum machine_mode mode)
 }
 
 \f
-/* For each mips16 function which refers to GP relative symbols, we
+/* If we can access small data directly (using gp-relative relocation
+   operators) return the small data pointer, otherwise return null.
+
+   For each mips16 function which refers to GP relative symbols, we
    use a pseudo register, initialized at the start of the function, to
    hold the $gp value.  */
 
-rtx
-mips16_gp_pseudo_reg (void)
+static rtx
+mips_sdata_pointer (void)
 {
+  if (TARGET_EXPLICIT_RELOCS)
+    return pic_offset_table_rtx;
+
+  if (!TARGET_MIPS16 || no_new_pseudos)
+    return 0;
+
   if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
     {
       rtx const_gp;
index 6adeadb1f991f542cef0c1083e78e7354ba369e4..30ddcc41d1505f3d24314fb895bc9ee2e7b46d0d 100644 (file)
@@ -2605,20 +2605,6 @@ typedef struct mips_args {
 #define CONSTANT_ADDRESS_P(X) \
   (CONSTANT_P (X) && mips_legitimate_address_p (SImode, X, 0))
 
-
-/* Nonzero if the constant value X is a legitimate general operand.
-   It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
-
-   At present, GAS doesn't understand li.[sd], so don't allow it
-   to be generated at present.  Also, the MIPS assembler does not
-   grok li.d Infinity.  */
-
-/* ??? SGI Irix 6 assembler fails for CONST address, so reject them.
-   Note that the Irix 6 assembler problem may already be fixed.
-   Note also that the GET_CODE (X) == CONST test catches the mips16
-   gp pseudo reg (see mips16_gp_pseudo_reg) deciding it is not
-   a LEGITIMATE_CONSTANT.  If we ever want mips16 and ABI_N32 or
-   ABI_64 to work together, we'll need to fix this.  */
 #define LEGITIMATE_CONSTANT_P(X) (mips_const_insns (X) > 0)
 
 #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                    \
index f8df0900e3b49a75b4cb3763ecc83cbd310e85a8..61aeead6eb6bf4bb331ccd0d479cc8abaae2593e 100644 (file)
    ;; are really only available for n32 and n64.  However, it is convenient
    ;; to reuse them for SVR4 PIC, where they represent the local and global
    ;; forms of R_MIPS_GOT16.
-   (RELOC_GPREL16              100)
-   (RELOC_GOT_HI               101)
-   (RELOC_GOT_LO               102)
-   (RELOC_GOT_PAGE             103)
-   (RELOC_GOT_DISP             104)
-   (RELOC_CALL16               105)
-   (RELOC_CALL_HI              106)
-   (RELOC_CALL_LO              107)
-   (RELOC_LOADGP_HI            108)
-   (RELOC_LOADGP_LO            109)])
+   (RELOC_GOT_HI               100)
+   (RELOC_GOT_LO               101)
+   (RELOC_GOT_PAGE             102)
+   (RELOC_GOT_DISP             103)
+   (RELOC_CALL16               104)
+   (RELOC_CALL_HI              105)
+   (RELOC_CALL_LO              106)
+   (RELOC_LOADGP_HI            107)
+   (RELOC_LOADGP_LO            108)])
 \f
 ;; ....................
 ;;
index 143877566619b9a5f0927ef28de7a452545783e9..59be14fb8f014c31a4e239c33bf35886b23362d8 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-28  Richard Sandiford  <rsandifo@redhat.com>
+
+       * gcc.c-torture/execute/20030928-1.c: New test.
+       * gcc.dg/torture/mips-sdata-1.c (f): Refer to x[0] rather than x[3].
+
 2003-09-27  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * g++.dg/opt/unroll1.C: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030928-1.c b/gcc/testsuite/gcc.c-torture/execute/20030928-1.c
new file mode 100644 (file)
index 0000000..77216c9
--- /dev/null
@@ -0,0 +1,32 @@
+#include <limits.h>
+
+#if INT_MAX <= 32767
+int main () { exit (0); }
+#else
+void get_addrs (const char**x, int *y)
+{
+  x[0] = "a1111" + (y[0] - 0x10000) * 2;
+  x[1] = "a1112" + (y[1] - 0x20000) * 2;
+  x[2] = "a1113" + (y[2] - 0x30000) * 2;
+  x[3] = "a1114" + (y[3] - 0x40000) * 2;
+  x[4] = "a1115" + (y[4] - 0x50000) * 2;
+  x[5] = "a1116" + (y[5] - 0x60000) * 2;
+  x[6] = "a1117" + (y[6] - 0x70000) * 2;
+  x[7] = "a1118" + (y[7] - 0x80000) * 2;
+}
+
+int main ()
+{
+  const char *x[8];
+  int y[8];
+  int i;
+
+  for (i = 0; i < 8; i++)
+    y[i] = 0x10000 * (i + 1);
+  get_addrs (x, y);
+  for (i = 0; i < 8; i++)
+    if (*x[i] != 'a')
+      abort ();
+  exit (0);
+}
+#endif
index ad8836bb66f0040a70acad303385258eee7e4263..b665d96cd560f4d09343321557342bc9afe1466c 100644 (file)
@@ -5,6 +5,6 @@
 struct s { int x[4]; };
 struct s my_struct __attribute__((__section__(".sdata")));
 
-int f() { return my_struct.x[3]; }
+int f() { return my_struct.x[0]; }
 
 /* { dg-final { scan-assembler {gp_?rel\(my_struct} } } */