m68k-protos.h (output_sibcall): Declare.
authorRichard Sandiford <richard@codesourcery.com>
Tue, 6 Mar 2007 09:00:00 +0000 (09:00 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 6 Mar 2007 09:00:00 +0000 (09:00 +0000)
gcc/
* config/m68k/m68k-protos.h (output_sibcall): Declare.
(mips_expand_epilogue): Add a bool parameter.
(m68k_legitimize_sibcall_address): Declare.
* config/m68k/m68k.c (TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
(m68k_expand_epilogue): Add a parameter to select between sibling
and normal epilogues.  Only generate a return for the latter.
(m68k_ok_for_sibcall_p): New function.
(m68k_legitimize_sibcall_address, output_sibcall): New functions.
* config/m68k/m68k.md (sibcall, *sibcall): New patterns.
(sibcall_value, *sibcall_value): Likewise.
(*call, *call_value): Require !SIBLING_CALL_P.
(epilogue): Update call to m68k_expand_epilogue.
(sibcall_epilogue): New pattern.
* config/m68k/predicates.md (const_call_operand): Say that this
predicate applies to sibling calls too.
(sibcall_operand): New predicate.

From-SVN: r122607

gcc/ChangeLog
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.md
gcc/config/m68k/predicates.md

index 00385a640cafb7b31997917a725e59402c1c9895..ce1caab046e925a7d7bb525acb6853126b14ced8 100644 (file)
@@ -1,3 +1,22 @@
+2007-03-06  Richard Sandiford  <richard@codesourcery.com>
+
+       * config/m68k/m68k-protos.h (output_sibcall): Declare.
+       (mips_expand_epilogue): Add a bool parameter.
+       (m68k_legitimize_sibcall_address): Declare.
+       * config/m68k/m68k.c (TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
+       (m68k_expand_epilogue): Add a parameter to select between sibling
+       and normal epilogues.  Only generate a return for the latter.
+       (m68k_ok_for_sibcall_p): New function.
+       (m68k_legitimize_sibcall_address, output_sibcall): New functions.
+       * config/m68k/m68k.md (sibcall, *sibcall): New patterns.
+       (sibcall_value, *sibcall_value): Likewise.
+       (*call, *call_value): Require !SIBLING_CALL_P.
+       (epilogue): Update call to m68k_expand_epilogue.
+       (sibcall_epilogue): New pattern.
+       * config/m68k/predicates.md (const_call_operand): Say that this
+       predicate applies to sibling calls too.
+       (sibcall_operand): New predicate.
+
 2007-03-06  Richard Sandiford  <richard@codesourcery.com>
 
        * config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q
index a6705c0f1a086f7796b318a97c5b34877613de31..185e7bc8809a7659d6071f99e52b20db7a0ddca7 100644 (file)
@@ -42,6 +42,7 @@ extern const char *output_andsi3 (rtx *);
 extern const char *output_iorsi3 (rtx *);
 extern const char *output_xorsi3 (rtx *);
 extern const char *output_call (rtx);
+extern const char *output_sibcall (rtx);
 extern void output_dbcc_and_branch (rtx *);
 extern int floating_exact_log2 (rtx);
 extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target);
@@ -71,10 +72,11 @@ extern bool m68k_regno_mode_ok (int, enum machine_mode);
 extern int flags_in_68881 (void);
 extern void m68k_expand_prologue (void);
 extern bool m68k_use_return_insn (void);
-extern void m68k_expand_epilogue (void);
+extern void m68k_expand_epilogue (bool);
 extern void override_options (void);
 extern const char *m68k_cpp_cpu_ident (const char *);
 extern const char *m68k_cpp_cpu_family (const char *);
 extern void init_68881_table (void);
 extern rtx m68k_legitimize_call_address (rtx);
+extern rtx m68k_legitimize_sibcall_address (rtx);
 extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);
index 1d6c03546d5fd61e397aaffb990fb5fbe511faea..8c99d4f30f8c76ed9e57ee501c7190c4a3e7cb47 100644 (file)
@@ -146,6 +146,7 @@ static tree m68k_handle_fndecl_attribute (tree *node, tree name,
                                          bool *no_add_attrs);
 static void m68k_compute_frame_layout (void);
 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
+static bool m68k_ok_for_sibcall_p (tree, tree);
 static bool m68k_rtx_costs (rtx, int, int, int *);
 \f
 
@@ -215,6 +216,9 @@ int m68k_last_compare_had_fp_operands;
 #undef TARGET_CANNOT_FORCE_CONST_MEM
 #define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
 
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL m68k_ok_for_sibcall_p
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
@@ -1015,7 +1019,8 @@ m68k_use_return_insn (void)
   return current_frame.offset == 0;
 }
 
-/* Emit RTL for the "epilogue" define_expand.
+/* Emit RTL for the "epilogue" or "sibcall_epilogue" define_expand;
+   SIBCALL_P says which.
 
    The function epilogue should not depend on the current stack pointer!
    It should use the frame pointer only, if there is a frame pointer.
@@ -1023,7 +1028,7 @@ m68k_use_return_insn (void)
    omit stack adjustments before returning.  */
 
 void
-m68k_expand_epilogue (void)
+m68k_expand_epilogue (bool sibcall_p)
 {
   HOST_WIDE_INT fsize, fsize_with_regs;
   bool big, restore_from_sp;
@@ -1181,7 +1186,8 @@ m68k_expand_epilogue (void)
                           stack_pointer_rtx,
                           EH_RETURN_STACKADJ_RTX));
 
-  emit_insn (gen_rtx_RETURN (VOIDmode));
+  if (!sibcall_p)
+    emit_insn (gen_rtx_RETURN (VOIDmode));
 }
 \f
 /* Return true if X is a valid comparison operator for the dbcc 
@@ -1218,6 +1224,16 @@ flags_in_68881 (void)
   return cc_status.flags & CC_IN_68881;
 }
 
+/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL_P.  We cannot use sibcalls
+   for nested functions because we use the static chain register for
+   indirect calls.  */
+
+static bool
+m68k_ok_for_sibcall_p (tree decl ATTRIBUTE_UNUSED, tree exp)
+{
+  return TREE_OPERAND (exp, 2) == NULL;
+}
+
 /* Convert X to a legitimate function call memory reference and return the
    result.  */
 
@@ -1230,6 +1246,19 @@ m68k_legitimize_call_address (rtx x)
   return replace_equiv_address (x, force_reg (Pmode, XEXP (x, 0)));
 }
 
+/* Likewise for sibling calls.  */
+
+rtx
+m68k_legitimize_sibcall_address (rtx x)
+{
+  gcc_assert (MEM_P (x));
+  if (sibcall_operand (XEXP (x, 0), VOIDmode))
+    return x;
+
+  emit_move_insn (gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM), XEXP (x, 0));
+  return replace_equiv_address (x, gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM));
+}
+
 /* Output a dbCC; jCC sequence.  Note we do not handle the 
    floating point version of this sequence (Fdbcc).  We also
    do not handle alternative conditions when CC_NO_OVERFLOW is
@@ -4013,6 +4042,17 @@ output_call (rtx x)
     return "jsr %a0";
 }
 
+/* Likewise sibling calls.  */
+
+const char *
+output_sibcall (rtx x)
+{
+  if (symbolic_operand (x, VOIDmode))
+    return m68k_symbolic_jump;
+  else
+    return "jmp %a0";
+}
+
 #ifdef M68K_TARGET_COFF
 
 /* Output assembly to switch to section NAME with attribute FLAGS.  */
index 40c80721b097fb343dea389464cae5566a7c29f3..f983d39cd32ce97be614376ee8f2ed478b646e01 100644 (file)
     "subql #1,%0\;cmpl #-1,%0\;jne %l1";
 })
 
+(define_expand "sibcall"
+  [(call (match_operand:QI 0 "memory_operand" "")
+        (match_operand:SI 1 "general_operand" ""))]
+  ""
+{
+  operands[0] = m68k_legitimize_sibcall_address (operands[0]);
+})
+
+(define_insn "*sibcall"
+  [(call (mem:QI (match_operand:SI 0 "sibcall_operand" ""))
+        (match_operand:SI 1 "general_operand" ""))]
+  "SIBLING_CALL_P (insn)"
+{
+  return output_sibcall (operands[0]);
+})
+
+(define_expand "sibcall_value"
+  [(set (match_operand 0 "" "")
+       (call (match_operand:QI 1 "memory_operand" "")
+             (match_operand:SI 2 "general_operand" "")))]
+  ""
+{
+  operands[1] = m68k_legitimize_sibcall_address (operands[1]);
+})
+
+(define_insn "*sibcall_value"
+  [(set (match_operand 0 "" "=rf,rf")
+       (call (mem:QI (match_operand:SI 1 "sibcall_operand" ""))
+             (match_operand:SI 2 "general_operand" "")))]
+  "SIBLING_CALL_P (insn)"
+{
+  operands[0] = operands[1];
+  return output_sibcall (operands[0]);
+})
+
 ;; Call subroutine with no return value.
 (define_expand "call"
   [(call (match_operand:QI 0 "memory_operand" "")
   [(call (mem:QI (match_operand:SI 0 "call_operand" "a,W"))
         (match_operand:SI 1 "general_operand" "g,g"))]
   ;; Operand 1 not really used on the m68000.
-  ""
+  "!SIBLING_CALL_P (insn)"
 {
   return output_call (operands[0]);
 })
        (call (mem:QI (match_operand:SI 1 "call_operand" "a,W"))
              (match_operand:SI 2 "general_operand" "g,g")))]
   ;; Operand 2 not really used on the m68000.
-  ""
+  "!SIBLING_CALL_P (insn)"
 {
   operands[0] = operands[1];
   return output_call (operands[0]);
   [(return)]
   ""
 {
-  m68k_expand_epilogue ();
+  m68k_expand_epilogue (false);
+  DONE;
+})
+
+(define_expand "sibcall_epilogue"
+  [(return)]
+  ""
+{
+  m68k_expand_epilogue (true);
   DONE;
 })
 
index 11e10f189b63e6e0cd4e9946b7677667915ee9c0..ae091f181ed0571cf79e1c3e95c098e8f347bde0 100644 (file)
     }
 })
 
-;; A constant that can be used the address in a call insn.
+;; A constant that can be used the address in a call or sibcall insn.
 (define_predicate "const_call_operand"
   (ior (match_operand 0 "const_int_operand")
        (and (match_test "m68k_symbolic_call != NULL")
   (ior (match_operand 0 "const_call_operand")
        (match_operand 0 "register_operand")))
 
+;; An operand that can be used as the address in a sibcall insn.
+(define_predicate "sibcall_operand"
+  (ior (match_operand 0 "const_call_operand")
+       (and (match_code "reg")
+           (match_test "REGNO (op) == STATIC_CHAIN_REGNUM"))))
+
 ;; TODO: Add a comment here.
 
 (define_predicate "post_inc_operand"