OSDN Git Service

* config/i386/i386.c (ix86_output_function_epilogue): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 May 2002 20:54:00 +0000 (20:54 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 29 May 2002 20:54:00 +0000 (20:54 +0000)
        (TARGET_ASM_FUNCTION_EPILOGUE): New.
        (pic_label_name): Remove.
        (pic_labels_used): New.
        (ix86_asm_file_end): Emit one pc load stub for each register used.
        (output_set_got): Generate deep pc load to any register.
        (ix86_select_alt_pic_regnum): New.
        (ix86_save_reg): Don't save pic register if we can find a valid
        call-clobbered replacement.
        (ix86_expand_prologue): If we found a valid replacement, renumber
        pic_offset_table_rtx.
        * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Look at
        pic_offset_table_rtx after reload.
        (REAL_PIC_OFFSET_TABLE_REGNUM): New.
        * config/i386/i386.md (set_got): Make insn, not expander.
        (set_got_nopic, set_got_deep, set_got_nodeep): Remove.

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

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 14069a7..ed6849e 100644 (file)
@@ -1,5 +1,24 @@
 2002-05-29  Richard Henderson  <rth@redhat.com>
 
+       * config/i386/i386.c (ix86_output_function_epilogue): New.
+       (TARGET_ASM_FUNCTION_EPILOGUE): New.
+       (pic_label_name): Remove.
+       (pic_labels_used): New.
+       (ix86_asm_file_end): Emit one pc load stub for each register used.
+       (output_set_got): Generate deep pc load to any register.
+       (ix86_select_alt_pic_regnum): New.
+       (ix86_save_reg): Don't save pic register if we can find a valid
+       call-clobbered replacement.
+       (ix86_expand_prologue): If we found a valid replacement, renumber
+       pic_offset_table_rtx.
+       * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Look at
+       pic_offset_table_rtx after reload.
+       (REAL_PIC_OFFSET_TABLE_REGNUM): New.
+       * config/i386/i386.md (set_got): Make insn, not expander.
+       (set_got_nopic, set_got_deep, set_got_nodeep): Remove.
+
+2002-05-29  Richard Henderson  <rth@redhat.com>
+
        * config/i386/i386.c (ix86_compute_frame_layout): Do add bottom
        alignment for alloca.
 
index 877f355..bea81e8 100644 (file)
@@ -687,6 +687,7 @@ static int ix86_nsaved_regs PARAMS ((void));
 static void ix86_emit_save_regs PARAMS ((void));
 static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));
 static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
+static void ix86_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
 static void ix86_sched_reorder_ppro PARAMS ((rtx *, rtx *));
 static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));
@@ -737,6 +738,7 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
 static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
 static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
 static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
+static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
 static int ix86_save_reg PARAMS ((unsigned int, int));
 static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
 static int ix86_comp_type_attributes PARAMS ((tree, tree));
@@ -806,6 +808,8 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
 #  undef TARGET_ASM_FUNCTION_PROLOGUE
 #  define TARGET_ASM_FUNCTION_PROLOGUE ix86_osf_output_function_prologue
 #endif
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
 
 #undef TARGET_ASM_OPEN_PAREN
 #define TARGET_ASM_OPEN_PAREN ""
@@ -3894,7 +3898,7 @@ ix86_setup_frame_addresses ()
   cfun->machine->accesses_prev_frame = 1;
 }
 \f
-static char pic_label_name[32];
+static int pic_labels_used;
 
 /* This function generates code for -fpic that loads %ebx with
    the return address of the caller and then returns.  */
@@ -3904,48 +3908,28 @@ ix86_asm_file_end (file)
      FILE *file;
 {
   rtx xops[2];
+  int regno;
 
-  if (pic_label_name[0] == 0)
-    return;
-
-  /* ??? Binutils 2.10 and earlier has a linkonce elimination bug related
-     to updating relocations to a section being discarded such that this
-     doesn't work.  Ought to detect this at configure time.  */
-#if 0
-  /* The trick here is to create a linkonce section containing the
-     pic label thunk, but to refer to it with an internal label.
-     Because the label is internal, we don't have inter-dso name
-     binding issues on hosts that don't support ".hidden".
-
-     In order to use these macros, however, we must create a fake
-     function decl.  */
-  if (targetm.have_named_sections)
-    {
-      tree decl = build_decl (FUNCTION_DECL,
-                             get_identifier ("i686.get_pc_thunk"),
-                             error_mark_node);
-      DECL_ONE_ONLY (decl) = 1;
-      (*targetm.asm_out.unique_section) (decl, 0);
-      named_section (decl, NULL);
-    }
-  else
-#else
-    text_section ();
-#endif
+  for (regno = 0; regno < 8; ++regno)
+    {
+      if (! ((pic_labels_used >> regno) & 1))
+       continue;
 
-  /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
-     internal (non-global) label that's being emitted, it didn't make
-     sense to have .type information for local labels.   This caused
-     the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
-     me debug info for a label that you're declaring non-global?) this
-     was changed to call ASM_OUTPUT_LABEL() instead.  */
+      text_section ();
 
-  ASM_OUTPUT_LABEL (file, pic_label_name);
+      /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
+        internal (non-global) label that's being emitted, it didn't make
+        sense to have .type information for local labels.   This caused
+        the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
+        me debug info for a label that you're declaring non-global?) this
+        was changed to call ASM_OUTPUT_LABEL() instead.  */
+      ASM_OUTPUT_INTERNAL_LABEL (file, "LPR", regno);
 
-  xops[0] = pic_offset_table_rtx;
-  xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
-  output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
-  output_asm_insn ("ret", xops);
+      xops[0] = gen_rtx_REG (SImode, regno);
+      xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
+      output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
+      output_asm_insn ("ret", xops);
+    }
 }
 
 /* Emit code for the SET_GOT patterns.  */
@@ -3976,10 +3960,11 @@ output_set_got (dest)
     }
   else
     {
-      if (! pic_label_name[0])
-       ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
+      char pic_label_name[32];
+      ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", REGNO (dest));
+      pic_labels_used |= 1 << REGNO (dest);
 
-      xops[2] = gen_rtx_SYMBOL_REF (Pmode, pic_label_name);
+      xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (pic_label_name));
       xops[2] = gen_rtx_MEM (QImode, xops[2]);
       output_asm_insn ("call\t%X2", xops);
     }
@@ -4005,17 +3990,39 @@ gen_push (arg)
                      arg);
 }
 
+/* Return >= 0 if there is an unused call-clobbered register available
+   for the entire function.  */
+
+static unsigned int
+ix86_select_alt_pic_regnum ()
+{
+  if (current_function_is_leaf && !current_function_profile)
+    {
+      int i;
+      for (i = 2; i >= 0; --i)
+        if (!regs_ever_live[i])
+         return i;
+    }
+
+  return INVALID_REGNUM;
+}
+  
 /* Return 1 if we need to save REGNO.  */
 static int
 ix86_save_reg (regno, maybe_eh_return)
      unsigned int regno;
      int maybe_eh_return;
 {
-  if (regno == PIC_OFFSET_TABLE_REGNUM
-      && (regs_ever_live[regno]
+  if (pic_offset_table_rtx
+      && regno == REAL_PIC_OFFSET_TABLE_REGNUM
+      && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
          || current_function_profile
          || current_function_calls_eh_return))
-    return 1;
+    {
+      if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
+       return 0;
+      return 1;
+    }
 
   if (current_function_calls_eh_return && maybe_eh_return)
     {
@@ -4236,9 +4243,7 @@ void
 ix86_expand_prologue ()
 {
   rtx insn;
-  int pic_reg_used = (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
-                     && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
-                         || current_function_profile));
+  bool pic_reg_used;
   struct ix86_frame frame;
   int use_mov = 0;
   HOST_WIDE_INT allocate;
@@ -4317,6 +4322,19 @@ ix86_expand_prologue ()
   SUBTARGET_PROLOGUE;
 #endif
 
+  pic_reg_used = false;
+  if (pic_offset_table_rtx
+      && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
+         || current_function_profile))
+    {
+      unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum ();
+
+      if (alt_pic_reg_used != INVALID_REGNUM)
+       REGNO (pic_offset_table_rtx) = alt_pic_reg_used;
+
+      pic_reg_used = true;
+    }
+
   if (pic_reg_used)
     {
       insn = emit_insn (gen_set_got (pic_offset_table_rtx));
@@ -4522,6 +4540,17 @@ ix86_expand_epilogue (style)
   else
     emit_jump_insn (gen_return_internal ());
 }
+
+/* Reset from the function's potential modifications.  */
+
+static void
+ix86_output_function_epilogue (file, size)
+     FILE *file ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+  if (pic_offset_table_rtx)
+    REGNO (pic_offset_table_rtx) = REAL_PIC_OFFSET_TABLE_REGNUM;
+}
 \f
 /* Extract the parts of an RTL expression that is a valid memory address
    for an instruction.  Return 0 if the structure of the address is
index 970dfdf..dc51aef 100644 (file)
@@ -1086,9 +1086,18 @@ do {                                                                     \
 /* Register to hold the addressing base for position independent
    code access to data items.  We don't use PIC pointer for 64bit
    mode.  Define the regnum to dummy value to prevent gcc from
-   pessimizing code dealing with EBX.  */
-#define PIC_OFFSET_TABLE_REGNUM \
-  (TARGET_64BIT || !flag_pic ? INVALID_REGNUM : 3)
+   pessimizing code dealing with EBX. 
+
+   To avoid clobbering a call-saved register unnecessarily, we renumber
+   the pic register when possible.  The change is visible after the
+   prologue has been emitted.  */
+
+#define REAL_PIC_OFFSET_TABLE_REGNUM  3
+
+#define PIC_OFFSET_TABLE_REGNUM                                \
+  (TARGET_64BIT || !flag_pic ? INVALID_REGNUM          \
+   : reload_completed ? REGNO (pic_offset_table_rtx)   \
+   : REAL_PIC_OFFSET_TABLE_REGNUM)
 
 /* Register in which address to store a structure value
    arrives in the function.  On the 386, the prologue
index 1c99f60..f2203c4 100644 (file)
   ""
   "ix86_expand_prologue (); DONE;")
 
-(define_expand "set_got"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
-             (clobber (reg:CC 17))])]
-  "!TARGET_64BIT"
-  "")
-
-(define_insn "*set_got_nopic"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
-   (clobber (reg:CC 17))]
-  "!TARGET_64BIT && !flag_pic"
-  { return output_set_got (operands[0]); }
-  [(set_attr "type" "multi")
-   (set_attr "length" "11")])
-
-(define_insn "*set_got_deep"
-  [(set (match_operand:SI 0 "register_operand" "=b")
-       (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
-   (clobber (reg:CC 17))]
-  "!TARGET_64BIT && TARGET_DEEP_BRANCH_PREDICTION"
-  { return output_set_got (operands[0]); }
-  [(set_attr "type" "multi")
-   (set_attr "length" "11")])
-
-(define_insn "*set_got_nodeep"
+(define_insn "set_got"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
    (clobber (reg:CC 17))]