alpha.c (small_symbolic_operand): New.
authorRichard Henderson <rth@redhat.com>
Thu, 13 Sep 2001 08:42:20 +0000 (01:42 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 13 Sep 2001 08:42:20 +0000 (01:42 -0700)
        * config/alpha/alpha.c (small_symbolic_operand): New.
        (override_options): Set MASK_SMALL_DATA based on pic/PIC.
        (some_operand, input_operand): Don't handle HIGH.
        (alpha_legitimize_address): Use it.  Emit HIGH with PLUS gp.
        (alpha_expand_mov): Likewise.
        (print_operand) [H]: Just print HIGH symbol.
        (print_operand_address): Handle small data.
        * config/alpha/alpha.h (MASK_SMALL_DATA, TARGET_SMALL_DATA): New.
        (TARGET_SWITCHES): Add -msmall-data/large-data.
        (PIC_OFFSET_TABLE_REGNUM): New.
        (PREFERRED_RELOAD_CLASS): Don't handle HIGH.
        (PREDICATE_COES): Update.
        * config/alpha/alpha.md (adddi_er_high): New.
        (adddi_er_low): Handle small data.
        * config/alpha/elf.h (DO_SELECT_SECTION): If SMALL_DATA,
        prefer .sdata to .rodata.
        (SELECT_RTX_SECTION): Likewise.

From-SVN: r45576

gcc/ChangeLog
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/elf.h

index cab40067a9c5a96fbedb3e3b7acce920b74ccb21..85e8c5b39fdd3a7e76e8bbbd7421871579390887 100644 (file)
@@ -1,3 +1,23 @@
+2001-09-13  Richard Henderson  <rth@redhat.com>
+
+       * config/alpha/alpha.c (small_symbolic_operand): New.
+       (override_options): Set MASK_SMALL_DATA based on pic/PIC.
+       (some_operand, input_operand): Don't handle HIGH.
+       (alpha_legitimize_address): Use it.  Emit HIGH with PLUS gp.
+       (alpha_expand_mov): Likewise.
+       (print_operand) [H]: Just print HIGH symbol.
+       (print_operand_address): Handle small data.
+       * config/alpha/alpha.h (MASK_SMALL_DATA, TARGET_SMALL_DATA): New.
+       (TARGET_SWITCHES): Add -msmall-data/large-data.
+       (PIC_OFFSET_TABLE_REGNUM): New.
+       (PREFERRED_RELOAD_CLASS): Don't handle HIGH.
+       (PREDICATE_COES): Update.
+       * config/alpha/alpha.md (adddi_er_high): New.
+       (adddi_er_low): Handle small data.
+       * config/alpha/elf.h (DO_SELECT_SECTION): If SMALL_DATA,
+       prefer .sdata to .rodata.
+       (SELECT_RTX_SECTION): Likewise.
+
 2001-09-12  Josh Martin  <josh.martin@abq.sc.philips.com>
 
        * fixinc/inclhack.def(hpux11_size_t): Keep HP-UX headers from
index 8ee718f29fd1554b233d32fa776ee3da08493ac9..9fd33a0ee717a8447a19a5b4acb27e526cd29f63 100644 (file)
@@ -448,6 +448,12 @@ override_options ()
   if (!g_switch_set)
     g_switch_value = 8;
 
+  /* Infer TARGET_SMALL_DATA from -fpic/-fPIC.  */
+  if (flag_pic == 1)
+    target_flags |= MASK_SMALL_DATA;
+  else if (flag_pic == 2)
+    target_flags &= ~MASK_SMALL_DATA;
+
   /* Align labels and loops for optimal branching.  */
   /* ??? Kludge these by not doing anything if we don't optimize and also if
      we are writing ECOFF symbols to work around a bug in DEC's assembler. */
@@ -742,7 +748,7 @@ some_operand (op, mode)
   switch (GET_CODE (op))
     {
     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
-    case SYMBOL_REF:  case CONST:  case HIGH:
+    case SYMBOL_REF:  case CONST:
       return 1;
 
     case SUBREG:
@@ -813,10 +819,6 @@ input_operand (op, mode)
     case CONSTANT_P_RTX:
       return 1;
 
-    case HIGH:
-      return (TARGET_EXPLICIT_RELOCS
-             && local_symbolic_operand (XEXP (op, 0), mode));
-
     default:
       break;
     }
@@ -876,6 +878,36 @@ local_symbolic_operand (op, mode)
          || (str[0] == '*' && str[1] == '$'));
 }
 
+/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
+   known to be defined in this file in the small data area.  */
+
+int
+small_symbolic_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  const char *str;
+
+  if (! TARGET_SMALL_DATA)
+    return 0;
+
+  if (GET_CODE (op) == CONST
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+    op = XEXP (XEXP (op, 0), 0);
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+
+  if (CONSTANT_POOL_ADDRESS_P (op))
+    return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+  else
+    {
+      str = XSTR (op, 0);
+      return str[0] == '@' && str[1] == 's';
+    }
+}
+
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
 
 int
@@ -1563,9 +1595,24 @@ alpha_legitimize_address (x, oldx, mode)
   /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
   if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, Pmode))
     {
-      rtx temp = gen_reg_rtx (Pmode);
-      emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (Pmode, x)));
-      return gen_rtx_LO_SUM (Pmode, temp, x);
+      rtx scratch;
+
+      if (small_symbolic_operand (x, Pmode))
+       scratch = pic_offset_table_rtx;
+      else
+       {
+         rtx insn, tmp;
+
+         scratch = gen_reg_rtx (Pmode);
+
+         tmp = gen_rtx_HIGH (Pmode, x);
+         tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
+          insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
+         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
+                                               REG_NOTES (insn));
+       }
+
+      return gen_rtx_LO_SUM (Pmode, scratch, x);
     }
 
   return NULL;
@@ -2127,9 +2174,23 @@ alpha_expand_mov (mode, operands)
 
   if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode))
     {
-      rtx scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
-      emit_insn (gen_rtx_SET (VOIDmode, scratch,
-                             gen_rtx_HIGH (Pmode, operands[1])));
+      rtx scratch;
+
+      if (small_symbolic_operand (operands[1], Pmode))
+       scratch = pic_offset_table_rtx;
+      else
+       {
+         rtx insn, tmp;
+
+         scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+
+         tmp = gen_rtx_HIGH (Pmode, operands[1]);
+         tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
+          insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
+         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
+                                               REG_NOTES (insn));
+       }
+
       operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
       return false;
     }
@@ -4773,10 +4834,7 @@ print_operand (file, x, code)
 
     case 'H':
       if (GET_CODE (x) == HIGH)
-       {
-         output_addr_const (file, XEXP (x, 0));
-         fputs ("($29)\t\t!gprelhigh", file);
-       }
+       output_addr_const (file, XEXP (x, 0));
       else
        output_operand_lossage ("invalid %%H value");
       break;
@@ -5056,7 +5114,9 @@ print_operand_address (file, addr)
        basereg = subreg_regno (addr);
       else
        abort ();
-      fprintf (file, "($%d)\t\t!gprellow", basereg);
+
+      fprintf (file, "($%d)\t\t!%s", basereg,
+              (basereg == 29 ? "gprel" : "gprellow"));
       return;
     }
 
index 3b030b27002885e03ff145660256daacd746a88d..b8db8d743527c91586cb072a4e428eec7b3f791a 100644 (file)
@@ -162,6 +162,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
 #define MASK_EXPLICIT_RELOCS (1 << 12)
 #define TARGET_EXPLICIT_RELOCS (target_flags & MASK_EXPLICIT_RELOCS)
 
+/* This means use 16-bit relocations to .sdata/.sbss.  */
+#define MASK_SMALL_DATA (1 << 13)
+#define TARGET_SMALL_DATA (target_flags & MASK_SMALL_DATA)
+
 /* This means that the processor is an EV5, EV56, or PCA56.
    Unlike alpha_cpu this is not affected by -mtune= setting.  */
 #define MASK_CPU_EV5   (1 << 28)
@@ -240,6 +244,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
     {"explicit-relocs", MASK_EXPLICIT_RELOCS,                          \
      N_("Emit code using explicit relocation directives")},            \
     {"no-explicit-relocs", -MASK_EXPLICIT_RELOCS, ""},                 \
+    {"small-data", MASK_SMALL_DATA,                                    \
+     N_("Emit 16-bit relocations to the small data areas")},           \
+    {"large-data", -MASK_SMALL_DATA,                                   \
+     N_("Emit 32-bit relocations to the small data areas")},           \
     {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} }
 
 #define TARGET_DEFAULT MASK_FP|MASK_FPREGS
@@ -684,6 +692,18 @@ extern const char *alpha_mlat_string;      /* For -mmemory-latency= */
    doesn't seem to specify this.  */
 #define STATIC_CHAIN_REGNUM 1
 
+/* The register number of the register used to address a table of
+   static data addresses in memory.  */
+#define PIC_OFFSET_TABLE_REGNUM 29
+
+/* Define this macro if the register defined by `PIC_OFFSET_TABLE_REGNUM'
+   is clobbered by calls.  */
+/* ??? It is and it isn't.  It's required to be valid for a given
+   function when the function returns.  It isn't clobbered by
+   current_file functions.  Moreover, we do not expose the ldgp
+   until after reload, so we're probably safe.  */
+/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */
+
 /* Register in which address to store a structure value
    arrives in the function.  On the Alpha, the address is passed
    as a hidden argument.  */
@@ -821,8 +841,7 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
    register via memory.  */
 
 #define PREFERRED_RELOAD_CLASS(X, CLASS)               \
-  (GET_CODE (X) == HIGH ? GENERAL_REGS                 \
-   : CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
+   (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
    ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS) \
    : (CLASS))
 
@@ -2172,9 +2191,9 @@ do {                                                                      \
   {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}},          \
   {"call_operand", {REG, SYMBOL_REF}},                                 \
   {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,                \
-                    SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}},      \
+                    SYMBOL_REF, CONST, LABEL_REF}},                    \
   {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,         \
-                   SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}},       \
+                   SYMBOL_REF, CONST, LABEL_REF}},                     \
   {"some_ni_operand", {SUBREG, REG, MEM}},                             \
   {"aligned_memory_operand", {MEM}},                                   \
   {"unaligned_memory_operand", {MEM}},                                 \
index 34280f7f772d60e66b85e74bcd4bb0c52fc05c17..9a25ef48c9db66bcf6e30c2b2d59a75d5ea1ca1e 100644 (file)
@@ -638,6 +638,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   ""
   "")
 
+(define_insn "*adddi_er_high"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (match_operand:DI 1 "register_operand" "r")
+                (high:DI (match_operand:DI 2 "local_symbolic_operand" ""))))]
+  "TARGET_EXPLICIT_RELOCS"
+  "ldah %0,%2(%1)\t\t!gprelhigh")
+
 ;; We used to expend quite a lot of effort choosing addq/subq/lda.
 ;; With complications like
 ;;
@@ -5298,7 +5305,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
                   (match_operand:DI 2 "local_symbolic_operand" "")))]
   "TARGET_EXPLICIT_RELOCS"
-  "lda %0,%2(%1)\t\t!gprellow")
+{
+  if (true_regnum (operands[1]) == 29)
+    return "lda %0,%2(%1)\t\t!gprel";
+  else
+    return "lda %0,%2(%1)\t\t!gprellow";
+})
 
 (define_insn "*movdi_er_nofix"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
index 7c2ad236b44bfde9cf2d3530c6f50facfe118641..ddb781817f9ead04440545c41d55feb1061227fb 100644 (file)
@@ -302,15 +302,20 @@ void FN ()                                        \
 #define DO_SELECT_SECTION(SECNUM, DECL, RELOC)                 \
   do                                                           \
      {                                                         \
+       HOST_WIDE_INT size;                                     \
        SECNUM = 1;                                             \
        if (TREE_CODE (DECL) == FUNCTION_DECL)                  \
-        SECNUM = 0;                                            \
+        {                                                      \
+          SECNUM = 0;                                          \
+          break;                                               \
+        }                                                      \
        else if (TREE_CODE (DECL) == STRING_CST)                        \
         {                                                      \
           if (flag_writable_strings)                           \
             SECNUM = 2;                                        \
           else                                                 \
             SECNUM = 0x101;                                    \
+          break;                                               \
         }                                                      \
        else if (TREE_CODE (DECL) == VAR_DECL)                  \
         {                                                      \
@@ -344,11 +349,16 @@ void FN ()                                        \
         }                                                      \
                                                                \
        /* Select small data sections based on size.  */                \
-       if ((SECNUM & 0xff) >= 2)                               \
+       size = int_size_in_bytes (TREE_TYPE (DECL));            \
+       if (size >= 0 && size <= g_switch_value)                        \
         {                                                      \
-          int size = int_size_in_bytes (TREE_TYPE (DECL));     \
-          if (size >= 0 && size <= g_switch_value)             \
+          if ((SECNUM & 0xff) >= 2)                            \
             SECNUM += 1;                                       \
+          /* Move readonly data to .sdata only if -msmall-data.  */ \
+          /* ??? Consider .sdata.{lit4,lit8} as                \
+             SHF_MERGE|SHF_ALPHA_GPREL.  */                    \
+          else if (TARGET_SMALL_DATA)                          \
+            SECNUM = 3;                                        \
         }                                                      \
      }                                                         \
    while (0)
@@ -437,8 +447,14 @@ void FN ()                                 \
    go into the const section.  */
 
 #undef  SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-   mergeable_constant_section((MODE), (ALIGN), 0)
+#define SELECT_RTX_SECTION(MODE, RTX, ALIGN)                           \
+do {                                                                   \
+  if (TARGET_SMALL_DATA && GET_MODE_SIZE (MODE) <= g_switch_value)     \
+     /* ??? Consider .sdata.{lit4,lit8} as SHF_MERGE|SHF_ALPHA_GPREL.  */ \
+    sdata_section ();                                                  \
+  else                                                                 \
+    mergeable_constant_section((MODE), (ALIGN), 0);                    \
+} while (0)
 
 /* Define the strings used for the special svr4 .type and .size directives.
    These strings generally do not vary from one system running svr4 to