frv-protos.h (frv_expand_epilogue, [...]): Add bool argument.
* config/frv/frv-protos.h (frv_expand_epilogue, frv_expand_fdpic_call): Add bool argument. * config/frv/frv.c (frv_function_ok_for_sibcall): New. (TARGET_FUNCTION_OK_FOR_SIBCALL): Define to it. (frv_expand_epilogue): Use new argument to decide whether to emit return instruction or copy the return address to LR. (frv_expand_fdpic_call): Inline PLT entry when emitting direct sibcalls. (sibcall_operand): New. * config/frv/frv.h (PREDICATE_CODES): call_operand doesn't match PLUS nor LABEL_REF. Add sibcall_operand. * config/frv/frv.md (call, call_value): Pass false to frv_expand_fdpic_call. (call_fdpicdi, call_value_fdpicdi): Insert %i0 in calll. (sibcall, sibcall_internal, sibcall_fdpicdi, sibcall_value, sibcall_value_internal, sibcall_value_fdpicdi): New. (return_unsigned_true, return_unsigned_false): New. (epilogue): Adjust call to frv_expand_epilogue. (sibcall_epilogue): New. From-SVN: r81405
This commit is contained in:
parent
afbe7e61fe
commit
764678d17d
5 changed files with 217 additions and 19 deletions
|
@ -1,5 +1,25 @@
|
|||
2004-05-02 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* config/frv/frv-protos.h (frv_expand_epilogue,
|
||||
frv_expand_fdpic_call): Add bool argument.
|
||||
* config/frv/frv.c (frv_function_ok_for_sibcall): New.
|
||||
(TARGET_FUNCTION_OK_FOR_SIBCALL): Define to it.
|
||||
(frv_expand_epilogue): Use new argument to decide whether to emit
|
||||
return instruction or copy the return address to LR.
|
||||
(frv_expand_fdpic_call): Inline PLT entry when emitting direct
|
||||
sibcalls.
|
||||
(sibcall_operand): New.
|
||||
* config/frv/frv.h (PREDICATE_CODES): call_operand doesn't match
|
||||
PLUS nor LABEL_REF. Add sibcall_operand.
|
||||
* config/frv/frv.md (call, call_value): Pass false to
|
||||
frv_expand_fdpic_call.
|
||||
(call_fdpicdi, call_value_fdpicdi): Insert %i0 in calll.
|
||||
(sibcall, sibcall_internal, sibcall_fdpicdi, sibcall_value,
|
||||
sibcall_value_internal, sibcall_value_fdpicdi): New.
|
||||
(return_unsigned_true, return_unsigned_false): New.
|
||||
(epilogue): Adjust call to frv_expand_epilogue.
|
||||
(sibcall_epilogue): New.
|
||||
|
||||
* config/frv/frv.h (ASM_SPEC): Pass -mno-fdpic as -mnopic.
|
||||
(CPP_SPEC, CPP_SIMPLE_SPEC): Undefine __FRV_ACC__ and __FRV_FPR__
|
||||
before redefining them.
|
||||
|
|
|
@ -53,7 +53,7 @@ extern frv_cpu_t frv_cpu_type; /* value of -mcpu= */
|
|||
|
||||
/* Define functions defined in frv.c */
|
||||
extern void frv_expand_prologue (void);
|
||||
extern void frv_expand_epilogue (int);
|
||||
extern void frv_expand_epilogue (bool);
|
||||
extern void frv_override_options (void);
|
||||
extern void frv_optimization_options (int, int);
|
||||
extern void frv_conditional_register_usage (void);
|
||||
|
@ -225,7 +225,7 @@ extern int even_acc_operand (rtx, enum machine_mode);
|
|||
extern int quad_acc_operand (rtx, enum machine_mode);
|
||||
extern int accg_operand (rtx, enum machine_mode);
|
||||
extern rtx frv_matching_accg_for_acc (rtx);
|
||||
extern void frv_expand_fdpic_call (rtx *, int);
|
||||
extern void frv_expand_fdpic_call (rtx *, bool, bool);
|
||||
extern rtx frv_gen_GPsym2reg (rtx, rtx);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -285,6 +285,7 @@ static bool frv_cannot_force_const_mem (rtx);
|
|||
static const char *unspec_got_name (int);
|
||||
static void frv_output_const_unspec (FILE *,
|
||||
const struct frv_unspec *);
|
||||
static bool frv_function_ok_for_sibcall (tree, tree);
|
||||
static rtx frv_struct_value_rtx (tree, int);
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
|
@ -319,6 +320,8 @@ static rtx frv_struct_value_rtx (tree, int);
|
|||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE frv_use_dfa_pipeline_interface
|
||||
|
||||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
|
||||
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
||||
#define TARGET_CANNOT_FORCE_CONST_MEM frv_cannot_force_const_mem
|
||||
|
||||
|
@ -332,6 +335,16 @@ static rtx frv_struct_value_rtx (tree, int);
|
|||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Any function call that satisfies the machine-independent
|
||||
requirements is eligible on FR-V. */
|
||||
|
||||
static bool
|
||||
frv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
|
||||
tree exp ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true if SYMBOL is a small data symbol and relocation RELOC
|
||||
can be used to access it directly in a load or store. */
|
||||
|
||||
|
@ -1749,7 +1762,7 @@ frv_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
|
|||
slots for arguments passed to the current function. */
|
||||
|
||||
void
|
||||
frv_expand_epilogue (int sibcall_p)
|
||||
frv_expand_epilogue (bool emit_return)
|
||||
{
|
||||
frv_stack_t *info = frv_stack_info ();
|
||||
rtx fp = frame_pointer_rtx;
|
||||
|
@ -1769,9 +1782,7 @@ frv_expand_epilogue (int sibcall_p)
|
|||
|
||||
/* Set RETURN_ADDR to the address we should return to. Set it to NULL if
|
||||
no return instruction should be emitted. */
|
||||
if (sibcall_p)
|
||||
return_addr = 0;
|
||||
else if (info->save_p[LR_REGNO])
|
||||
if (info->save_p[LR_REGNO])
|
||||
{
|
||||
int lr_offset;
|
||||
rtx mem;
|
||||
|
@ -1814,8 +1825,20 @@ frv_expand_epilogue (int sibcall_p)
|
|||
if (current_function_calls_eh_return)
|
||||
emit_insn (gen_stack_adjust (sp, sp, EH_RETURN_STACKADJ_RTX));
|
||||
|
||||
if (return_addr)
|
||||
if (emit_return)
|
||||
emit_jump_insn (gen_epilogue_return (return_addr));
|
||||
else
|
||||
{
|
||||
rtx lr = return_addr;
|
||||
|
||||
if (REGNO (return_addr) != LR_REGNO)
|
||||
{
|
||||
lr = gen_rtx_REG (Pmode, LR_REGNO);
|
||||
emit_move_insn (lr, return_addr);
|
||||
}
|
||||
|
||||
emit_insn (gen_rtx_USE (VOIDmode, lr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3529,7 +3552,7 @@ frv_legitimate_memory_operand (rtx op, enum machine_mode mode, int condexec_p)
|
|||
}
|
||||
|
||||
void
|
||||
frv_expand_fdpic_call (rtx *operands, int ret_value)
|
||||
frv_expand_fdpic_call (rtx *operands, bool ret_value, bool sibcall)
|
||||
{
|
||||
rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
|
||||
rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REG);
|
||||
|
@ -3565,8 +3588,9 @@ frv_expand_fdpic_call (rtx *operands, int ret_value)
|
|||
all external functions, so one would have to also mark function
|
||||
declarations available in the same module with non-default
|
||||
visibility, which is advantageous in itself. */
|
||||
if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr)
|
||||
&& TARGET_INLINE_PLT)
|
||||
if (GET_CODE (addr) == SYMBOL_REF
|
||||
&& ((!SYMBOL_REF_LOCAL_P (addr) && TARGET_INLINE_PLT)
|
||||
|| sibcall))
|
||||
{
|
||||
rtx x, dest;
|
||||
dest = gen_reg_rtx (SImode);
|
||||
|
@ -3598,7 +3622,11 @@ frv_expand_fdpic_call (rtx *operands, int ret_value)
|
|||
picreg = gen_reg_rtx (DImode);
|
||||
emit_insn (gen_movdi_ldd (picreg, addr));
|
||||
|
||||
if (ret_value)
|
||||
if (sibcall && ret_value)
|
||||
c = gen_sibcall_value_fdpicdi (rvrtx, picreg, const0_rtx);
|
||||
else if (sibcall)
|
||||
c = gen_sibcall_fdpicdi (picreg, const0_rtx);
|
||||
else if (ret_value)
|
||||
c = gen_call_value_fdpicdi (rvrtx, picreg, const0_rtx, lr);
|
||||
else
|
||||
c = gen_call_fdpicdi (picreg, const0_rtx, lr);
|
||||
|
@ -4766,6 +4794,21 @@ call_operand (rtx op, enum machine_mode mode)
|
|||
return gpr_or_int12_operand (op, mode);
|
||||
}
|
||||
|
||||
/* Return true if operand is a memory reference suitable for a sibcall. */
|
||||
|
||||
int
|
||||
sibcall_operand (rtx op, enum machine_mode mode)
|
||||
{
|
||||
if (GET_MODE (op) != mode && mode != VOIDmode && GET_CODE (op) != CONST_INT)
|
||||
return FALSE;
|
||||
|
||||
/* Note this doesn't allow reg+reg or reg+imm12 addressing (which should
|
||||
never occur anyway), but prevents reload from not handling the case
|
||||
properly of a call through a pointer on a function that calls
|
||||
vfork/setjmp, etc. due to the need to flush all of the registers to stack. */
|
||||
return gpr_or_int12_operand (op, mode);
|
||||
}
|
||||
|
||||
/* Return true if operator is a kind of relational operator. */
|
||||
|
||||
int
|
||||
|
|
|
@ -3111,8 +3111,10 @@ do { \
|
|||
{ "odd_fpr_operand", { REG, SUBREG }}, \
|
||||
{ "dbl_memory_one_insn_operand", { MEM }}, \
|
||||
{ "dbl_memory_two_insn_operand", { MEM }}, \
|
||||
{ "call_operand", { REG, SUBREG, PLUS, CONST_INT, \
|
||||
SYMBOL_REF, LABEL_REF, CONST }}, \
|
||||
{ "call_operand", { REG, SUBREG, CONST_INT, \
|
||||
CONST, SYMBOL_REF }}, \
|
||||
{ "sibcall_operand", { REG, SUBREG, CONST_INT, \
|
||||
CONST }}, \
|
||||
{ "upper_int16_operand", { CONST_INT }}, \
|
||||
{ "uint16_operand", { CONST_INT }}, \
|
||||
{ "relational_operator", { EQ, NE, LE, LT, GE, GT, \
|
||||
|
|
|
@ -5260,7 +5260,7 @@
|
|||
operands[2] = const0_rtx;
|
||||
|
||||
if (TARGET_FDPIC)
|
||||
frv_expand_fdpic_call (operands, 0);
|
||||
frv_expand_fdpic_call (operands, false, false);
|
||||
else
|
||||
emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr));
|
||||
|
||||
|
@ -5308,7 +5308,7 @@
|
|||
(match_operand 1 "" ""))
|
||||
(clobber (match_operand:SI 2 "lr_operand" "=l"))]
|
||||
"TARGET_FDPIC"
|
||||
"calll %M0"
|
||||
"call%i0l %M0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
|
@ -5325,6 +5325,65 @@
|
|||
[(set_attr "length" "4")
|
||||
(set_attr "type" "call,jumpl")])
|
||||
|
||||
(define_expand "sibcall"
|
||||
[(use (match_operand:QI 0 "" ""))
|
||||
(use (match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(use (match_operand 3 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr;
|
||||
|
||||
if (GET_CODE (operands[0]) != MEM)
|
||||
abort ();
|
||||
|
||||
addr = XEXP (operands[0], 0);
|
||||
if (! sibcall_operand (addr, Pmode))
|
||||
addr = force_reg (Pmode, addr);
|
||||
|
||||
if (! operands[2])
|
||||
operands[2] = const0_rtx;
|
||||
|
||||
if (TARGET_FDPIC)
|
||||
frv_expand_fdpic_call (operands, false, true);
|
||||
else
|
||||
emit_call_insn (gen_sibcall_internal (addr, operands[1], operands[2]));
|
||||
|
||||
DONE;
|
||||
}")
|
||||
|
||||
;; It might seem that these sibcall patterns are missing references to
|
||||
;; LR, but they're not necessary because sibcall_epilogue will make
|
||||
;; sure LR is restored, and having LR here will set
|
||||
;; regs_ever_used[REG_LR], forcing it to be saved on the stack, and
|
||||
;; then restored in sibcalls and regular return code paths, even if
|
||||
;; the function becomes a leaf function after tail-call elimination.
|
||||
|
||||
;; We must not use a call-saved register here. `W' limits ourselves
|
||||
;; to gr14 or gr15, but since we're almost running out of constraint
|
||||
;; letters, and most other call-clobbered registers are often used for
|
||||
;; argument-passing, this will do.
|
||||
(define_insn "sibcall_internal"
|
||||
[(call (mem:QI (match_operand:SI 0 "sibcall_operand" "WNOP"))
|
||||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(return)]
|
||||
"! TARGET_FDPIC"
|
||||
"jmp%i0l %M0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
(define_insn "sibcall_fdpicdi"
|
||||
[(call (mem:QI (match_operand:DI 0 "fdpic_fptr_operand" "W"))
|
||||
(match_operand 1 "" ""))
|
||||
(return)]
|
||||
"TARGET_FDPIC"
|
||||
"jmp%i0l %M0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
|
||||
;; Subroutine call instruction returning a value. Operand 0 is the hard
|
||||
;; register in which the value is returned. There are three more operands, the
|
||||
;; same as the three operands of the `call' instruction (but with numbers
|
||||
|
@ -5355,7 +5414,7 @@
|
|||
operands[3] = const0_rtx;
|
||||
|
||||
if (TARGET_FDPIC)
|
||||
frv_expand_fdpic_call (operands, 1);
|
||||
frv_expand_fdpic_call (operands, true, false);
|
||||
else
|
||||
emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
|
||||
operands[3], lr));
|
||||
|
@ -5382,7 +5441,7 @@
|
|||
(match_operand 2 "" "")))
|
||||
(clobber (match_operand:SI 3 "lr_operand" "=l"))]
|
||||
"TARGET_FDPIC"
|
||||
"calll %M1"
|
||||
"call%i1l %M1"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
|
@ -5400,6 +5459,56 @@
|
|||
[(set_attr "length" "4")
|
||||
(set_attr "type" "call,jumpl")])
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(use (match_operand 0 "" ""))
|
||||
(use (match_operand:QI 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(use (match_operand 3 "" ""))
|
||||
(use (match_operand 4 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr;
|
||||
|
||||
if (GET_CODE (operands[1]) != MEM)
|
||||
abort ();
|
||||
|
||||
addr = XEXP (operands[1], 0);
|
||||
if (! sibcall_operand (addr, Pmode))
|
||||
addr = force_reg (Pmode, addr);
|
||||
|
||||
if (! operands[3])
|
||||
operands[3] = const0_rtx;
|
||||
|
||||
if (TARGET_FDPIC)
|
||||
frv_expand_fdpic_call (operands, true, true);
|
||||
else
|
||||
emit_call_insn (gen_sibcall_value_internal (operands[0], addr, operands[2],
|
||||
operands[3]));
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_insn "sibcall_value_internal"
|
||||
[(set (match_operand 0 "register_operand" "=d")
|
||||
(call (mem:QI (match_operand:SI 1 "sibcall_operand" "WNOP"))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(return)]
|
||||
"! TARGET_FDPIC"
|
||||
"jmp%i1l %M1"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
(define_insn "sibcall_value_fdpicdi"
|
||||
[(set (match_operand 0 "register_operand" "=d")
|
||||
(call (mem:QI (match_operand:DI 1 "fdpic_fptr_operand" "W"))
|
||||
(match_operand 2 "" "")))
|
||||
(return)]
|
||||
"TARGET_FDPIC"
|
||||
"jmp%i1l %M1"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jumpl")])
|
||||
|
||||
;; return instruction generated instead of jmp to epilog
|
||||
(define_expand "return"
|
||||
[(parallel [(return)
|
||||
|
@ -5430,6 +5539,30 @@
|
|||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jump,jumpl")])
|
||||
|
||||
(define_insn "*return_unsigned_true"
|
||||
[(set (pc)
|
||||
(if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
|
||||
[(match_operand 1 "icc_operand" "t")
|
||||
(const_int 0)])
|
||||
(return)
|
||||
(pc)))]
|
||||
"direct_return_p ()"
|
||||
"b%c0lr %1,%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jump")])
|
||||
|
||||
(define_insn "*return_unsigned_false"
|
||||
[(set (pc)
|
||||
(if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
|
||||
[(match_operand 1 "icc_operand" "t")
|
||||
(const_int 0)])
|
||||
(pc)
|
||||
(return)))]
|
||||
"direct_return_p ()"
|
||||
"b%C0lr %1,%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "jump")])
|
||||
|
||||
;; A version of addsi3 for deallocating stack space at the end of the
|
||||
;; epilogue. The addition is done in parallel with an (unspec_volatile),
|
||||
;; which represents the clobbering of the deallocated space.
|
||||
|
@ -5634,7 +5767,7 @@
|
|||
""
|
||||
"
|
||||
{
|
||||
frv_expand_epilogue (FALSE);
|
||||
frv_expand_epilogue (true);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
|
@ -5650,7 +5783,7 @@
|
|||
""
|
||||
"
|
||||
{
|
||||
frv_expand_epilogue (TRUE);
|
||||
frv_expand_epilogue (false);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue