longer necessary. */
p = rtvec_alloc (9
- + 1
+ 32 - info->first_gp_reg_save
+ LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
+ 63 + 1 - info->first_fp_reg_save);
j = 0;
RTVEC_ELT (p, j++) = ret_rtx;
- RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode,
- LR_REGNO));
RTVEC_ELT (p, j++)
= gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
/* The instruction pattern requires a clobber here;
emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
}
- if (!sibcall)
+ if (!sibcall && restoring_FPRs_inline)
{
- rtvec p;
- bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
- if (! restoring_FPRs_inline)
- {
- p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
- RTVEC_ELT (p, 0) = ret_rtx;
- }
- else
+ if (cfa_restores)
{
- if (cfa_restores)
- {
- /* We can't hang the cfa_restores off a simple return,
- since the shrink-wrap code sometimes uses an existing
- return. This means there might be a path from
- pre-prologue code to this return, and dwarf2cfi code
- wants the eh_frame unwinder state to be the same on
- all paths to any point. So we need to emit the
- cfa_restores before the return. For -m64 we really
- don't need epilogue cfa_restores at all, except for
- this irritating dwarf2cfi with shrink-wrap
- requirement; The stack red-zone means eh_frame info
- from the prologue telling the unwinder to restore
- from the stack is perfectly good right to the end of
- the function. */
- emit_insn (gen_blockage ());
- emit_cfa_restores (cfa_restores);
- cfa_restores = NULL_RTX;
- }
- p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) = simple_return_rtx;
+ /* We can't hang the cfa_restores off a simple return,
+ since the shrink-wrap code sometimes uses an existing
+ return. This means there might be a path from
+ pre-prologue code to this return, and dwarf2cfi code
+ wants the eh_frame unwinder state to be the same on
+ all paths to any point. So we need to emit the
+ cfa_restores before the return. For -m64 we really
+ don't need epilogue cfa_restores at all, except for
+ this irritating dwarf2cfi with shrink-wrap
+ requirement; The stack red-zone means eh_frame info
+ from the prologue telling the unwinder to restore
+ from the stack is perfectly good right to the end of
+ the function. */
+ emit_insn (gen_blockage ());
+ emit_cfa_restores (cfa_restores);
+ cfa_restores = NULL_RTX;
}
- RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
- ? gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode, LR_REGNO))
- : gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, LR_REGNO)));
+ emit_jump_insn (targetm.gen_simple_return ());
+ }
- /* If we have to restore more than two FP registers, branch to the
+ if (!sibcall && !restoring_FPRs_inline)
+ {
+ bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
+ rtvec p = rtvec_alloc (3 + !!lr + 64 - info->first_fp_reg_save);
+ int elt = 0;
+ RTVEC_ELT (p, elt++) = ret_rtx;
+ if (lr)
+ RTVEC_ELT (p, elt++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
+
+ /* We have to restore more than two FP registers, so branch to the
restore function. It will return to our caller. */
- if (! restoring_FPRs_inline)
- {
- int i;
- int reg;
- rtx sym;
+ int i;
+ int reg;
+ rtx sym;
- if (flag_shrink_wrap)
- cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
+ if (flag_shrink_wrap)
+ cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
- sym = rs6000_savres_routine_sym (info,
- SAVRES_FPR | (lr ? SAVRES_LR : 0));
- RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym);
- reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
- RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
+ sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0));
+ RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, sym);
+ reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
+ RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
- for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- {
- rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
- RTVEC_ELT (p, i + 4)
- = gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
- if (flag_shrink_wrap)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
+ RTVEC_ELT (p, elt++)
+ = gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
generate sibcall RTL explicitly. */
insn = emit_call_insn (
gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (4,
+ gen_rtvec (3,
gen_rtx_CALL (VOIDmode,
funexp, const0_rtx),
gen_rtx_USE (VOIDmode, const0_rtx),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (SImode,
- LR_REGNO)),
simple_return_rtx)));
SIBLING_CALL_P (insn) = 1;
emit_barrier ();
/* Note use of the TOC register. */
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
- /* We need to also mark a use of the link register since the function we
- sibling-call to will use it to return to our caller. */
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO));
}
/* Return whether we need to always update the saved TOC pointer when we update
[(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNO))
(simple_return)])]
""
"
(call (mem:SI (match_operand 1 "address_operand" ""))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNO))
(simple_return)])]
""
"
}
}")
-;; 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 (reg:SI LR_REGNO))
(simple_return)]
"(INTVAL (operands[2]) & CALL_LONG) == 0"
"*
[(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 (reg:SI LR_REGNO))
(simple_return)]
"TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 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 (reg:SI LR_REGNO))
(simple_return)]
"(INTVAL (operands[3]) & CALL_LONG) == 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 (reg:SI LR_REGNO))
(simple_return)]
"TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
"*
[(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" "O,n,O,n"))
- (use (reg:SI LR_REGNO))
(simple_return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4)
(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
(match_operand 2 "" "")))
(use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
- (use (reg:SI LR_REGNO))
(simple_return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4)
(set_attr "indexed" "yes")
(set_attr "cell_micro" "always")])
-(define_insn "*return_internal_<mode>"
- [(simple_return)
- (use (match_operand:P 0 "register_operand" "lc"))]
- ""
- "b%T0"
- [(set_attr "type" "jmpreg")])
-
; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...