From f7e70894412aa334b68cceb241496c302c663dd9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 6 Mar 2007 09:00:00 +0000 Subject: [PATCH] m68k-protos.h (output_sibcall): Declare. 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 | 19 ++++++++++++++ gcc/config/m68k/m68k-protos.h | 4 ++- gcc/config/m68k/m68k.c | 46 +++++++++++++++++++++++++++++--- gcc/config/m68k/m68k.md | 49 ++++++++++++++++++++++++++++++++--- gcc/config/m68k/predicates.md | 8 +++++- 5 files changed, 118 insertions(+), 8 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00385a640ca..ce1caab046e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2007-03-06 Richard Sandiford + + * 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 * config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h index a6705c0f1a0..185e7bc8809 100644 --- a/gcc/config/m68k/m68k-protos.h +++ b/gcc/config/m68k/m68k-protos.h @@ -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); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 1d6c03546d5..8c99d4f30f8 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -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 *); @@ -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)); } /* 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. */ diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 40c80721b09..f983d39cd32 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -6679,6 +6679,41 @@ "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" "") @@ -6693,7 +6728,7 @@ [(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]); }) @@ -6715,7 +6750,7 @@ (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]); @@ -6774,7 +6809,15 @@ [(return)] "" { - m68k_expand_epilogue (); + m68k_expand_epilogue (false); + DONE; +}) + +(define_expand "sibcall_epilogue" + [(return)] + "" +{ + m68k_expand_epilogue (true); DONE; }) diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md index 11e10f189b6..ae091f181ed 100644 --- a/gcc/config/m68k/predicates.md +++ b/gcc/config/m68k/predicates.md @@ -159,7 +159,7 @@ } }) -;; 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") @@ -170,6 +170,12 @@ (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"