OSDN Git Service

PR target/14454
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Oct 2004 14:04:32 +0000 (14:04 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 13 Oct 2004 14:04:32 +0000 (14:04 +0000)
* config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to
sparc_can_output_mi_thunk.
(sparc_output_mi_thunk): Simplify handling of delta offset.  Add
handling of vcall offset.
(sparc_can_output_mi_thunk): New predicate.
* doc/tm.texi (TARGET_ASM_OUTPUT_MI_THUNK): Document VCALL_OFFSET.
(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Delete.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New target hook.

* config/sparc/sparc.c (emit_and_preserve): Preserve stack alignment.

* config/sparc/sparc.md (movdi): Remove redundant test.

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

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.md
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/thunk1.C

index 3ecb586..923175c 100644 (file)
@@ -1,3 +1,19 @@
+2004-10-13  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       PR target/14454
+       * config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to
+       sparc_can_output_mi_thunk.
+       (sparc_output_mi_thunk): Simplify handling of delta offset.  Add
+       handling of vcall offset.
+       (sparc_can_output_mi_thunk): New predicate.
+       * doc/tm.texi (TARGET_ASM_OUTPUT_MI_THUNK): Document VCALL_OFFSET.
+       (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Delete.
+       (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New target hook.
+
+       * config/sparc/sparc.c (emit_and_preserve): Preserve stack alignment.
+
+       * config/sparc/sparc.md (movdi): Remove redundant test.
+
 2004-10-13  Paolo Bonzini  <bonzini@gnu.org>
 
        * tree-dump.c (dump_options): Remove TDF_TREE, TDF_RTL,
index 3f75954..3371db9 100644 (file)
@@ -334,6 +334,8 @@ static bool sparc_function_ok_for_sibcall (tree, tree);
 static void sparc_init_libfuncs (void);
 static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
                                   HOST_WIDE_INT, tree);
+static bool sparc_can_output_mi_thunk (tree, HOST_WIDE_INT,
+                                      HOST_WIDE_INT, tree);
 static struct machine_function * sparc_init_machine_status (void);
 static bool sparc_cannot_force_const_mem (rtx);
 static rtx sparc_tls_get_addr (void);
@@ -425,7 +427,7 @@ enum processor_type sparc_cpu;
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
 
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS sparc_rtx_costs
@@ -8511,23 +8513,25 @@ emit_and_preserve (rtx seq, rtx reg)
   rtx slot = gen_rtx_MEM (word_mode,
                          plus_constant (stack_pointer_rtx, SPARC_STACK_BIAS));
 
-  emit_stack_pointer_decrement (GEN_INT (UNITS_PER_WORD));
+  emit_stack_pointer_decrement (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
   emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
   emit_insn (seq);
   emit_insn (gen_rtx_SET (VOIDmode, reg, slot));
-  emit_stack_pointer_increment (GEN_INT (UNITS_PER_WORD));
+  emit_stack_pointer_increment (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
 }
 
-/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
-   Used for C++ multiple inheritance.  */
+/* Output the assembler code for a thunk function.  THUNK_DECL is the
+   declaration for the thunk function itself, FUNCTION is the decl for
+   the target function.  DELTA is an immediate constant offset to be
+   added to THIS.  If VCALL_OFFSET is nonzero, the word at address
+   (*THIS + VCALL_OFFSET) should be additionally added to THIS.  */
 
 static void
 sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
-                      HOST_WIDE_INT delta,
-                      HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+                      HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
                       tree function)
 {
-  rtx this, insn, funexp, delta_rtx;
+  rtx this, insn, funexp;
   unsigned int int_arg_first;
 
   reload_completed = 1;
@@ -8566,27 +8570,73 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
 
   /* Add DELTA.  When possible use a plain add, otherwise load it into
      a register first.  */
-  delta_rtx = GEN_INT (delta);
-  if (!SPARC_SIMM13_P (delta))
+  if (delta)
     {
+      rtx delta_rtx = GEN_INT (delta);
+
+      if (! SPARC_SIMM13_P (delta))
+       {
+         rtx scratch = gen_rtx_REG (Pmode, 1);
+         emit_move_insn (scratch, delta_rtx);
+         delta_rtx = scratch;
+       }
+
+      /* THIS += DELTA.  */
+      emit_insn (gen_add2_insn (this, delta_rtx));
+    }
+
+  /* Add the word at address (*THIS + VCALL_OFFSET).  */
+  if (vcall_offset)
+    {
+      rtx vcall_offset_rtx = GEN_INT (vcall_offset);
       rtx scratch = gen_rtx_REG (Pmode, 1);
 
-      if (input_operand (delta_rtx, GET_MODE (scratch)))
-       emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx));
+      if (vcall_offset >= 0)
+       abort ();
+
+      /* SCRATCH = *THIS.  */
+      emit_move_insn (scratch, gen_rtx_MEM (Pmode, this));
+
+      /* Prepare for adding VCALL_OFFSET.  The difficulty is that we
+        may not have any available scratch register at this point.  */
+      if (SPARC_SIMM13_P (vcall_offset))
+       ;
+      /* This is the case if ARCH64 (unless -ffixed-g5 is passed).  */
+      else if (! fixed_regs[5]
+              /* The below sequence is made up of at least 2 insns,
+                 while the default method may need only one.  */
+              && vcall_offset < -8192)
+       {
+         rtx scratch2 = gen_rtx_REG (Pmode, 5);
+         emit_move_insn (scratch2, vcall_offset_rtx);
+         vcall_offset_rtx = scratch2;
+       }
       else
        {
-         if (TARGET_ARCH64)
-           sparc_emit_set_const64 (scratch, delta_rtx);
-         else
-           sparc_emit_set_const32 (scratch, delta_rtx);
+         rtx increment = GEN_INT (-4096);
+
+         /* VCALL_OFFSET is a negative number whose typical range can be
+            estimated as -32768..0 in 32-bit mode.  In almost all cases
+            it is therefore cheaper to emit multiple add insns than
+            spilling and loading the constant into a register (at least
+            6 insns).  */
+         while (! SPARC_SIMM13_P (vcall_offset))
+           {
+             emit_insn (gen_add2_insn (scratch, increment));
+             vcall_offset += 4096;
+           }
+         vcall_offset_rtx = GEN_INT (vcall_offset); /* cannot be 0 */
        }
 
-      delta_rtx = scratch;
-    }
+      /* SCRATCH = *(*THIS + VCALL_OFFSET).  */
+      emit_move_insn (scratch, gen_rtx_MEM (Pmode,
+                                           gen_rtx_PLUS (Pmode,
+                                                         scratch,
+                                                         vcall_offset_rtx)));
 
-  emit_insn (gen_rtx_SET (VOIDmode,
-                         this,
-                         gen_rtx_PLUS (Pmode, this, delta_rtx)));
+      /* THIS += *(*THIS + VCALL_OFFSET).  */
+      emit_insn (gen_add2_insn (this, scratch));
+    }
 
   /* Generate a tail call to the target function.  */
   if (! TREE_USED (function))
@@ -8674,6 +8724,19 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   no_new_pseudos = 0;
 }
 
+/* Return true if sparc_output_mi_thunk would be able to output the
+   assembler code for the thunk function specified by the arguments
+   it is passed, and false otherwise.  */
+static bool
+sparc_can_output_mi_thunk (tree thunk_fndecl ATTRIBUTE_UNUSED,
+                          HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
+                          HOST_WIDE_INT vcall_offset,
+                          tree function ATTRIBUTE_UNUSED)
+{
+  /* Bound the loop used in the default method above.  */
+  return (vcall_offset >= -32768 || ! fixed_regs[5]);
+}
+
 /* How to allocate a 'struct machine_function'.  */
 
 static struct machine_function *
index 182afb9..1000fbb 100644 (file)
   if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
     ;
   else if (TARGET_ARCH64
-          && CONSTANT_P (operands[1])
            && GET_CODE (operands[1]) != HIGH
            && GET_CODE (operands[1]) != LO_SUM)
     {
index d08d005..a87db9a 100644 (file)
@@ -1,3 +1,7 @@
+2004-10-13  Eric Botcazou  <ebotcazou@libertysurf.fr>
+
+       * g++.dg/inherit/thunk1.C: Run on the SPARC.
+
 2004-10-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/17724
index 4426419..3bbd050 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { target i?86-*-* x86_64-*-* s390*-*-* alpha*-*-* ia64-*-* } }
+// { dg-do run { target i?86-*-* x86_64-*-* s390*-*-* alpha*-*-* ia64-*-* sparc*-*-* } }
 
 #include <stdarg.h>