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
This commit is contained in:
Richard Sandiford 2007-03-06 09:00:00 +00:00 committed by Richard Sandiford
parent 31c5b44477
commit f7e7089441
5 changed files with 118 additions and 8 deletions

View 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> 2007-03-06 Richard Sandiford <richard@codesourcery.com>
* config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q * config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q

View File

@ -42,6 +42,7 @@ extern const char *output_andsi3 (rtx *);
extern const char *output_iorsi3 (rtx *); extern const char *output_iorsi3 (rtx *);
extern const char *output_xorsi3 (rtx *); extern const char *output_xorsi3 (rtx *);
extern const char *output_call (rtx); extern const char *output_call (rtx);
extern const char *output_sibcall (rtx);
extern void output_dbcc_and_branch (rtx *); extern void output_dbcc_and_branch (rtx *);
extern int floating_exact_log2 (rtx); extern int floating_exact_log2 (rtx);
extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target); 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 int flags_in_68881 (void);
extern void m68k_expand_prologue (void); extern void m68k_expand_prologue (void);
extern bool m68k_use_return_insn (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 void override_options (void);
extern const char *m68k_cpp_cpu_ident (const char *); extern const char *m68k_cpp_cpu_ident (const char *);
extern const char *m68k_cpp_cpu_family (const char *); extern const char *m68k_cpp_cpu_family (const char *);
extern void init_68881_table (void); extern void init_68881_table (void);
extern rtx m68k_legitimize_call_address (rtx); 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); extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);

View File

@ -146,6 +146,7 @@ static tree m68k_handle_fndecl_attribute (tree *node, tree name,
bool *no_add_attrs); bool *no_add_attrs);
static void m68k_compute_frame_layout (void); static void m68k_compute_frame_layout (void);
static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); 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 *); 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 #undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p #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[] = static const struct attribute_spec m68k_attribute_table[] =
{ {
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ /* { 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; 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! The function epilogue should not depend on the current stack pointer!
It should use the frame pointer only, if there is a frame 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. */ omit stack adjustments before returning. */
void void
m68k_expand_epilogue (void) m68k_expand_epilogue (bool sibcall_p)
{ {
HOST_WIDE_INT fsize, fsize_with_regs; HOST_WIDE_INT fsize, fsize_with_regs;
bool big, restore_from_sp; bool big, restore_from_sp;
@ -1181,7 +1186,8 @@ m68k_expand_epilogue (void)
stack_pointer_rtx, stack_pointer_rtx,
EH_RETURN_STACKADJ_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 /* 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; 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 /* Convert X to a legitimate function call memory reference and return the
result. */ result. */
@ -1230,6 +1246,19 @@ m68k_legitimize_call_address (rtx x)
return replace_equiv_address (x, force_reg (Pmode, XEXP (x, 0))); 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 /* Output a dbCC; jCC sequence. Note we do not handle the
floating point version of this sequence (Fdbcc). We also floating point version of this sequence (Fdbcc). We also
do not handle alternative conditions when CC_NO_OVERFLOW is do not handle alternative conditions when CC_NO_OVERFLOW is
@ -4013,6 +4042,17 @@ output_call (rtx x)
return "jsr %a0"; 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 #ifdef M68K_TARGET_COFF
/* Output assembly to switch to section NAME with attribute FLAGS. */ /* Output assembly to switch to section NAME with attribute FLAGS. */

View File

@ -6679,6 +6679,41 @@
"subql #1,%0\;cmpl #-1,%0\;jne %l1"; "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. ;; Call subroutine with no return value.
(define_expand "call" (define_expand "call"
[(call (match_operand:QI 0 "memory_operand" "") [(call (match_operand:QI 0 "memory_operand" "")
@ -6693,7 +6728,7 @@
[(call (mem:QI (match_operand:SI 0 "call_operand" "a,W")) [(call (mem:QI (match_operand:SI 0 "call_operand" "a,W"))
(match_operand:SI 1 "general_operand" "g,g"))] (match_operand:SI 1 "general_operand" "g,g"))]
;; Operand 1 not really used on the m68000. ;; Operand 1 not really used on the m68000.
"" "!SIBLING_CALL_P (insn)"
{ {
return output_call (operands[0]); return output_call (operands[0]);
}) })
@ -6715,7 +6750,7 @@
(call (mem:QI (match_operand:SI 1 "call_operand" "a,W")) (call (mem:QI (match_operand:SI 1 "call_operand" "a,W"))
(match_operand:SI 2 "general_operand" "g,g")))] (match_operand:SI 2 "general_operand" "g,g")))]
;; Operand 2 not really used on the m68000. ;; Operand 2 not really used on the m68000.
"" "!SIBLING_CALL_P (insn)"
{ {
operands[0] = operands[1]; operands[0] = operands[1];
return output_call (operands[0]); return output_call (operands[0]);
@ -6774,7 +6809,15 @@
[(return)] [(return)]
"" ""
{ {
m68k_expand_epilogue (); m68k_expand_epilogue (false);
DONE;
})
(define_expand "sibcall_epilogue"
[(return)]
""
{
m68k_expand_epilogue (true);
DONE; DONE;
}) })

View File

@ -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" (define_predicate "const_call_operand"
(ior (match_operand 0 "const_int_operand") (ior (match_operand 0 "const_int_operand")
(and (match_test "m68k_symbolic_call != NULL") (and (match_test "m68k_symbolic_call != NULL")
@ -170,6 +170,12 @@
(ior (match_operand 0 "const_call_operand") (ior (match_operand 0 "const_call_operand")
(match_operand 0 "register_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. ;; TODO: Add a comment here.
(define_predicate "post_inc_operand" (define_predicate "post_inc_operand"