diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 69 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 241 |
5 files changed, 317 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa73454..a8b9a19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +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. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 42563d3..4209211 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ad99417..28a0a75 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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. */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 17a3015..42aa929 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index dd1cad7..4a441e2 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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. |