OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 Aug 2007 15:31:00 +0000 (15:31 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 Aug 2007 15:31:00 +0000 (15:31 +0000)
* config/mips/mips.c (mips_symbolic_address_p): Delete.
(mips_symbol_insns_1): New function, split out from...
(mips_symbol_insns): ...here.  Take a mode argument.  Treat loads
and stores separately from load addresses.
(mips_classify_address): Replace uses of mips_symbolic_address_p
with uses of mips_symbol_insns.
(mips_address_insns): Update calls to mips_symbol_insns.
(mips_const_insns): Likewise.
(mips_legitimize_address): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127297 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c

index ee858f4..a2e4f6a 100644 (file)
@@ -1,5 +1,17 @@
 2007-08-08  Richard Sandiford  <richard@codesourcery.com>
 
+       * config/mips/mips.c (mips_symbolic_address_p): Delete.
+       (mips_symbol_insns_1): New function, split out from...
+       (mips_symbol_insns): ...here.  Take a mode argument.  Treat loads
+       and stores separately from load addresses.
+       (mips_classify_address): Replace uses of mips_symbolic_address_p
+       with uses of mips_symbol_insns.
+       (mips_address_insns): Update calls to mips_symbol_insns.
+       (mips_const_insns): Likewise.
+       (mips_legitimize_address): Likewise.
+
+2007-08-08  Richard Sandiford  <richard@codesourcery.com>
+
        * config/mips/mips-protos.h (SYMBOL_FORCE_TO_MEM): New symbol type.
        * config/mips/mips.c (mips_classify_symbol): Skip TARGET_ABICALLS
        block for locally-binding symbols if TARGET_ABSOLUTE_ABICALLS.
index 75873d7..b8e013e 100644 (file)
@@ -288,12 +288,11 @@ struct mips_integer_op;
 struct mips_sim;
 
 static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
-static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
 static bool mips_classify_address (struct mips_address_info *, rtx,
                                   enum machine_mode, int);
 static bool mips_cannot_force_const_mem (rtx);
 static bool mips_use_blocks_for_constant_p (enum machine_mode, rtx);
-static int mips_symbol_insns (enum mips_symbol_type);
+static int mips_symbol_insns (enum mips_symbol_type, enum machine_mode);
 static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
 static rtx mips_force_temporary (rtx, rtx);
 static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type);
@@ -1673,52 +1672,6 @@ mips_valid_base_register_p (rtx x, enum machine_mode mode, int strict)
 }
 
 
-/* Return true if symbols of type SYMBOL_TYPE can directly address a value
-   with mode MODE.  This is used for both symbolic and LO_SUM addresses.  */
-
-static bool
-mips_symbolic_address_p (enum mips_symbol_type symbol_type,
-                        enum machine_mode mode)
-{
-  switch (symbol_type)
-    {
-    case SYMBOL_ABSOLUTE:
-    case SYMBOL_GP_RELATIVE:
-      return true;
-
-    case SYMBOL_PC_RELATIVE:
-      /* PC-relative addressing is only available for lw and ld.  */
-      return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
-
-    case SYMBOL_GOT_PAGE_OFST:
-      return true;
-
-    case SYMBOL_FORCE_TO_MEM:
-    case SYMBOL_GOT_DISP:
-      /* The address will have to be loaded from the constant pool
-        or GOT before it is used in an address.  */
-      return false;
-
-    case SYMBOL_GOTOFF_PAGE:
-    case SYMBOL_GOTOFF_DISP:
-    case SYMBOL_GOTOFF_CALL:
-    case SYMBOL_GOTOFF_LOADGP:
-    case SYMBOL_TLS:
-    case SYMBOL_TLSGD:
-    case SYMBOL_TLSLDM:
-    case SYMBOL_DTPREL:
-    case SYMBOL_GOTTPREL:
-    case SYMBOL_TPREL:
-    case SYMBOL_64_HIGH:
-    case SYMBOL_64_MID:
-    case SYMBOL_64_LOW:
-    case SYMBOL_HALF:
-      return true;
-    }
-  gcc_unreachable ();
-}
-
-
 /* Return true if X is a valid address for machine mode MODE.  If it is,
    fill in INFO appropriately.  STRICT is true if we should only accept
    hard base registers.  */
@@ -1750,7 +1703,7 @@ mips_classify_address (struct mips_address_info *info, rtx x,
       return (mips_valid_base_register_p (info->reg, mode, strict)
              && mips_symbolic_constant_p (info->offset, SYMBOL_CONTEXT_MEM,
                                           &info->symbol_type)
-             && mips_symbolic_address_p (info->symbol_type, mode)
+             && mips_symbol_insns (info->symbol_type, mode) > 0
              && mips_lo_relocs[info->symbol_type] != 0);
 
     case CONST_INT:
@@ -1765,7 +1718,7 @@ mips_classify_address (struct mips_address_info *info, rtx x,
       info->type = ADDRESS_SYMBOLIC;
       return (mips_symbolic_constant_p (x, SYMBOL_CONTEXT_MEM,
                                        &info->symbol_type)
-             && mips_symbolic_address_p (info->symbol_type, mode)
+             && mips_symbol_insns (info->symbol_type, mode) > 0
              && !mips_split_p[info->symbol_type]);
 
     default:
@@ -1831,13 +1784,13 @@ mips_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
   return !TARGET_MIPS16;
 }
 \f
-/* Return the number of instructions needed to load a symbol of the
-   given type into a register.  If valid in an address, the same number
-   of instructions are needed for loads and stores.  Treat extended
-   mips16 instructions as two instructions.  */
+/* Like mips_symbol_insns, but treat extended MIPS16 instructions as a
+   single instruction.  We rely on the fact that, in the worst case,
+   all instructions involved in a MIPS16 address calculation are usually
+   extended ones.  */
 
 static int
-mips_symbol_insns (enum mips_symbol_type type)
+mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
 {
   switch (type)
     {
@@ -1853,23 +1806,37 @@ mips_symbol_insns (enum mips_symbol_type type)
 
         The final address is then $at + %lo(symbol).  With 32-bit
         symbols we just need a preparatory lui.  */
-      return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2);
+      return ABI_HAS_64BIT_SYMBOLS ? 6 : 2;
 
     case SYMBOL_GP_RELATIVE:
-    case SYMBOL_HALF:
+      /* Treat GP-relative accesses as taking a single instruction on
+        MIPS16 too; the copy of $gp can often be shared.  */
       return 1;
 
     case SYMBOL_PC_RELATIVE:
-      /* This case is for mips16 only.  Assume we'll need an
-        extended instruction.  */
-      return 2;
+      /* PC-relative constants can be only be used with addiupc,
+        lwpc and ldpc.  */
+      if (mode == MAX_MACHINE_MODE
+         || GET_MODE_SIZE (mode) == 4
+         || GET_MODE_SIZE (mode) == 8)
+       return 1;
+
+      /* The constant must be loaded using addiupc first.  */
+      return 0;
 
     case SYMBOL_FORCE_TO_MEM:
       /* The constant must be loaded from the constant pool.  */
       return 0;
 
-    case SYMBOL_GOT_PAGE_OFST:
     case SYMBOL_GOT_DISP:
+      /* The constant will have to be loaded from the GOT before it
+        is used in an address.  */
+      if (mode != MAX_MACHINE_MODE)
+       return 0;
+
+      /* Fall through.  */
+
+    case SYMBOL_GOT_PAGE_OFST:
       /* Unless -funit-at-a-time is in effect, we can't be sure whether
         the local/global classification is accurate.  See override_options
         for details.
@@ -1904,7 +1871,10 @@ mips_symbol_insns (enum mips_symbol_type type)
     case SYMBOL_DTPREL:
     case SYMBOL_GOTTPREL:
     case SYMBOL_TPREL:
-      /* Check whether the offset is a 16- or 32-bit value.  */
+    case SYMBOL_HALF:
+      /* A 16-bit constant formed by a single relocation, or a 32-bit
+        constant formed from a high 16-bit relocation and a low 16-bit
+        relocation.  Use mips_split_p to determine which.  */
       return mips_split_p[type] ? 2 : 1;
 
     case SYMBOL_TLS:
@@ -1914,6 +1884,22 @@ mips_symbol_insns (enum mips_symbol_type type)
   gcc_unreachable ();
 }
 
+/* If MODE is MAX_MACHINE_MODE, return the number of instructions needed
+   to load symbols of type TYPE into a register.  Return 0 if the given
+   type of symbol cannot be used as an immediate operand.
+
+   Otherwise, return the number of instructions needed to load or store
+   values of mode MODE to or from addresses of type TYPE.  Return 0 if
+   the given type of symbol is not valid in addresses.
+
+   In both cases, treat extended MIPS16 instructions as two instructions.  */
+
+static int
+mips_symbol_insns (enum mips_symbol_type type, enum machine_mode mode)
+{
+  return mips_symbol_insns_1 (type, mode) * (TARGET_MIPS16 ? 2 : 1);
+}
+
 /* Return true if X is a legitimate $sp-based address for mode MDOE.  */
 
 bool
@@ -1985,7 +1971,7 @@ mips_address_insns (rtx x, enum machine_mode mode)
        return factor;
 
       case ADDRESS_SYMBOLIC:
-       return factor * mips_symbol_insns (addr.symbol_type);
+       return factor * mips_symbol_insns (addr.symbol_type, mode);
       }
   return 0;
 }
@@ -2035,7 +2021,7 @@ mips_const_insns (rtx x)
 
       /* See if we can refer to X directly.  */
       if (mips_symbolic_constant_p (x, SYMBOL_CONTEXT_LEA, &symbol_type))
-       return mips_symbol_insns (symbol_type);
+       return mips_symbol_insns (symbol_type, MAX_MACHINE_MODE);
 
       /* Otherwise try splitting the constant into a base and offset.
         16-bit offsets can be added using an extra addiu.  Larger offsets
@@ -2056,7 +2042,8 @@ mips_const_insns (rtx x)
 
     case SYMBOL_REF:
     case LABEL_REF:
-      return mips_symbol_insns (mips_classify_symbol (x, SYMBOL_CONTEXT_LEA));
+      return mips_symbol_insns (mips_classify_symbol (x, SYMBOL_CONTEXT_LEA),
+                               MAX_MACHINE_MODE);
 
     default:
       return 0;
@@ -2344,7 +2331,7 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode)
 
   /* See if the address can split into a high part and a LO_SUM.  */
   if (mips_symbolic_constant_p (*xloc, SYMBOL_CONTEXT_MEM, &symbol_type)
-      && mips_symbolic_address_p (symbol_type, mode)
+      && mips_symbol_insns (symbol_type, mode) > 0
       && mips_split_p[symbol_type])
     {
       *xloc = mips_split_symbol (0, *xloc);