Commit 5e1bf043 by Dale Johannesen Committed by Dale Johannesen

Add sibcall handling for rs6000 target.

From-SVN: r56166
parent 3971a4d2
2002-08-09 Dale Johannesen <dalej@apple.com>
* config/rs6000/rs6000.md: Add sibcall patterns.
* config/rs6000/rs6000.h (FUNCTION_OK_FOR_SIBCALL): Define.
* config/rs6000/rs6000.c (rs6000_ra_ever_killed):
Rewritten to handle sibcalls.
* config/rs6000/rs6000.c (function_ok_for_sibcall): New.
* config/rs6000/rs6000-protos.h (function_ok_for_sibcall): New.
2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
* profile.c (da_file_name): New static var.
......
......@@ -151,6 +151,7 @@ extern void setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
int *, int));
extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree));
extern void output_mi_thunk PARAMS ((FILE *, tree, int, tree));
extern int function_ok_for_sibcall PARAMS ((tree));
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
......
......@@ -9412,25 +9412,82 @@ rs6000_return_addr (count, frame)
return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
}
/* Say whether a function is a candidate for sibcall handling or not.
We do not allow indirect calls to be optimized into sibling calls.
Also, we can't do it if there are any vector parameters; there's
nowhere to put the VRsave code so it works; note that functions with
vector parameters are required to have a prototype, so the argument
type info must be available here. (The tail recursion case can work
with vector parameters, but there's no way to distinguish here.) */
int
function_ok_for_sibcall (fndecl)
tree fndecl;
{
tree type;
if (fndecl)
{
if (TARGET_ALTIVEC_VRSAVE)
{
for (type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
type; type = TREE_CHAIN (type))
{
if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE )
return 0;
}
}
if (DEFAULT_ABI == ABI_DARWIN
|| (TREE_ASM_WRITTEN (fndecl) && !flag_pic) || !TREE_PUBLIC (fndecl))
return 1;
}
return 0;
}
/* function rewritten to handle sibcalls */
static int
rs6000_ra_ever_killed ()
{
rtx top;
rtx reg;
rtx insn;
#ifdef ASM_OUTPUT_MI_THUNK
if (current_function_is_thunk)
return 0;
#endif
if (!has_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM)
|| cfun->machine->ra_needs_full_frame)
return regs_ever_live[LINK_REGISTER_REGNUM];
/* regs_ever_live has LR marked as used if any sibcalls
are present. Which it is, but this should not force
saving and restoring in the prologue/epilog. Likewise,
reg_set_between_p thinks a sibcall clobbers LR, so
that is inappropriate. */
/* Also, the prologue can generate a store into LR that
doesn't really count, like this:
move LR->R0
bcl to set PIC register
move LR->R31
move R0->LR
When we're called from the epilog, we need to avoid counting
this as a store; thus we ignore any insns with a REG_MAYBE_DEAD note. */
push_topmost_sequence ();
top = get_insns ();
pop_topmost_sequence ();
reg = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
return reg_set_between_p (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
top, NULL_RTX);
for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
{
if (FIND_REG_INC_NOTE (insn, reg))
return 1;
else if (GET_CODE (insn) == CALL_INSN
&& !SIBLING_CALL_P (insn))
return 1;
else if (set_of (reg, insn) != NULL_RTX
&& find_reg_note (insn, REG_MAYBE_DEAD, NULL_RTX) == 0)
return 1;
}
}
return 0;
}
/* Add a REG_MAYBE_DEAD note to the insn. */
......
......@@ -1798,6 +1798,10 @@ typedef struct rs6000_args
argument is passed depends on whether or not it is a named argument. */
#define STRICT_ARGUMENT_NAMING 1
/* We do not allow indirect calls to be optimized into sibling calls, nor
do we allow calls with vector parameters. */
#define FUNCTION_OK_FOR_SIBCALL(DECL) function_ok_for_sibcall ((DECL))
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
......
......@@ -10710,6 +10710,247 @@
DONE;
}")
;; sibling call patterns
(define_expand "sibcall"
[(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(use (scratch:SI))
(return)])]
""
"
{
#if TARGET_MACHO
if (flag_pic)
operands[0] = machopic_indirect_call_target (operands[0]);
#endif
if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
abort ();
operands[0] = XEXP (operands[0], 0);
}")
;; this and similar patterns must be marked as using LR, otherwise
;; dataflow will try to delete the store into it. This is true
;; even when the actual reg to jump to is in CTR, when LR was
;; saved and restored around the PIC-setting BCL.
(define_insn "*sibcall_local32"
[(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(use (match_scratch:SI 3 "=l,l"))
(return)]
"(INTVAL (operands[2]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
(define_insn "*sibcall_local64"
[(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(use (match_scratch:SI 3 "=l,l"))
(return)]
"TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
(define_insn "*sibcall_value_local32"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (match_scratch:SI 4 "=l,l"))
(return)]
"(INTVAL (operands[3]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
(define_insn "*sibcall_value_local64"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (match_scratch:SI 4 "=l,l"))
(return)]
"TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
}"
[(set_attr "type" "branch")
(set_attr "length" "4,8")])
(define_insn "*sibcall_nonlocal_aix32"
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
(match_operand 1 "" "g"))
(use (match_operand:SI 2 "immediate_operand" "O"))
(use (match_scratch:SI 3 "=l"))
(return)]
"TARGET_32BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"b %z0"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(define_insn "*sibcall_nonlocal_aix64"
[(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
(match_operand 1 "" "g"))
(use (match_operand:SI 2 "immediate_operand" "O"))
(use (match_scratch:SI 3 "=l"))
(return)]
"TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"b %z0"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(define_insn "*sibcall_value_nonlocal_aix32"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
(match_operand 2 "" "g")))
(use (match_operand:SI 3 "immediate_operand" "O"))
(use (match_scratch:SI 4 "=l"))
(return)]
"TARGET_32BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"b %z1"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(define_insn "*sibcall_value_nonlocal_aix64"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
(match_operand 2 "" "g")))
(use (match_operand:SI 3 "immediate_operand" "O"))
(use (match_scratch:SI 4 "=l"))
(return)]
"TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"b %z1"
[(set_attr "type" "branch")
(set_attr "length" "4")])
(define_insn "*sibcall_nonlocal_sysv"
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" "O,n"))
(use (match_scratch:SI 3 "=l,l"))
(return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_AIX_NODESC)
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "register_operand" "")
(call (mem:SI (match_operand 1 "address_operand" ""))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(use (scratch:SI))
(return)])]
""
"
{
#if TARGET_MACHO
if (flag_pic)
operands[1] = machopic_indirect_call_target (operands[1]);
#endif
if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
abort ();
operands[1] = XEXP (operands[1], 0);
}")
(define_insn "*sibcall_value_nonlocal_sysv"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
(match_operand 2 "" "")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (match_scratch:SI 4 "=l,l"))
(return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_AIX_NODESC)
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"*
{
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
(define_expand "sibcall_epilogue"
[(use (const_int 0))]
"TARGET_SCHED_PROLOG"
"
{
rs6000_emit_epilogue (TRUE);
DONE;
}")
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment