mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 19:41:06 +08:00
s390-protos.h (s390_emit_epilogue): Parameter added.
2004-04-29 Andreas Krebbel <krebbel1@de.ibm.com> ChangeLog: * config/s390/s390-protos.h (s390_emit_epilogue): Parameter added. (s390_emit_call): New function prototype added. (s390_tls_get_offset): Function removed. * config/s390/s390.c (s390_function_ok_for_sibcall, s390_call_saved_register_used_p): New functions. (TARGET_FUNCTION_OK_FOR_SIBCALL): Definition of target macro added. (s390_tls_get_offset): Function merged into s390_emit_tls_call_insn. (s390_emit_tls_call_insn): New function. (legitimize_tls_address): Call s390_emit_tls_call_insn instead of emit_call_insn. (s390_emit_prologue): Use s390_emit_call instead of emit_call_insn. (s390_emit_epilogue): Like s390_emit_prologue. Parameter for sibcalls added. * config/s390/s390.h (SIBCALL_REGNUM): New macro representing the register number used to hold the target address for sibcalls. * config/s390/s390.md ("sibcall", "sibcall_value", "sibcall_epilogue"): New expanders. ("*sibcall_br", "*sibcall_brc", "*sibcall_brcl", "*sibcall_value_br", "*sibcall_value_brc", "*sibcall_value_brcl"): New insns. ("call_exp", "call_value_exp", "call_value_tls", "call_value_tls_exp"): Expanders removed. ("call", "call_value"): Call s390_emit_call to emit the call patterns. ("*bras", "*brasl", "*bras_r", "*brasl_r", "*bras_tls", "*brasl_tls", "*basr", "*basr_r", "*basr_tls"): Added constraint: !SIBLING_CALL_P. ("epilogue"): Changed the call to s390_emit_epilogue to use the new parameter. testsuite/ChangeLog: * gcc.dg/sibcall-3.c: Delete s390 from expected fail list. * gcc.dg/sibcall-4.c: Likewise. * gcc.dg/sibcall-6.c: Enable s390 as test platform. From-SVN: r81347
This commit is contained in:
parent
1ae58c30e2
commit
ed9676cf0c
@ -1,3 +1,32 @@
|
||||
2004-04-29 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_emit_epilogue): Parameter added.
|
||||
(s390_emit_call): New function prototype added.
|
||||
(s390_tls_get_offset): Function removed.
|
||||
* config/s390/s390.c (s390_function_ok_for_sibcall,
|
||||
s390_call_saved_register_used_p): New functions.
|
||||
(TARGET_FUNCTION_OK_FOR_SIBCALL): Definition of target macro added.
|
||||
(s390_tls_get_offset): Function merged into s390_emit_tls_call_insn.
|
||||
(s390_emit_tls_call_insn): New function.
|
||||
(legitimize_tls_address): Call s390_emit_tls_call_insn instead of
|
||||
emit_call_insn.
|
||||
(s390_emit_prologue): Use s390_emit_call instead of emit_call_insn.
|
||||
(s390_emit_epilogue): Like s390_emit_prologue. Parameter for sibcalls
|
||||
added.
|
||||
* config/s390/s390.h (SIBCALL_REGNUM): New macro representing the
|
||||
register number used to hold the target address for sibcalls.
|
||||
* config/s390/s390.md ("sibcall", "sibcall_value", "sibcall_epilogue"):
|
||||
New expanders.
|
||||
("*sibcall_br", "*sibcall_brc", "*sibcall_brcl", "*sibcall_value_br",
|
||||
"*sibcall_value_brc", "*sibcall_value_brcl"): New insns.
|
||||
("call_exp", "call_value_exp", "call_value_tls", "call_value_tls_exp"):
|
||||
Expanders removed.
|
||||
("call", "call_value"): Call s390_emit_call to emit the call patterns.
|
||||
("*bras", "*brasl", "*bras_r", "*brasl_r", "*bras_tls", "*brasl_tls",
|
||||
"*basr", "*basr_r", "*basr_tls"): Added constraint: !SIBLING_CALL_P.
|
||||
("epilogue"): Changed the call to s390_emit_epilogue to use the
|
||||
new parameter.
|
||||
|
||||
2004-04-30 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* bb-reorder.c, c-opts.c, cfglayout.c, cgraph.c, cgraphunit.c,
|
||||
|
@ -26,7 +26,7 @@ extern void override_options (void);
|
||||
extern HOST_WIDE_INT s390_arg_frame_offset (void);
|
||||
extern void s390_load_got (int);
|
||||
extern void s390_emit_prologue (void);
|
||||
extern void s390_emit_epilogue (void);
|
||||
extern void s390_emit_epilogue (bool);
|
||||
extern void s390_function_profiler (FILE *, int);
|
||||
|
||||
#ifdef RTX_CODE
|
||||
@ -53,7 +53,6 @@ extern int s390_alc_comparison (rtx op, enum machine_mode mode);
|
||||
extern int s390_slb_comparison (rtx op, enum machine_mode mode);
|
||||
extern int symbolic_reference_mentioned_p (rtx);
|
||||
extern int tls_symbolic_reference_mentioned_p (rtx);
|
||||
extern rtx s390_tls_get_offset (void);
|
||||
extern int legitimate_la_operand_p (rtx);
|
||||
extern int preferred_la_operand_p (rtx);
|
||||
extern int legitimate_pic_operand_p (rtx);
|
||||
@ -77,6 +76,7 @@ extern void s390_expand_movstr (rtx, rtx, rtx);
|
||||
extern void s390_expand_clrstr (rtx, rtx);
|
||||
extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
|
||||
extern rtx s390_return_addr_rtx (int, rtx);
|
||||
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
|
||||
|
||||
extern bool s390_output_addr_const_extra (FILE*, rtx);
|
||||
extern void print_operand_address (FILE *, rtx);
|
||||
|
@ -78,6 +78,8 @@ static int s390_address_cost (rtx);
|
||||
static void s390_reorg (void);
|
||||
static bool s390_valid_pointer_mode (enum machine_mode);
|
||||
static tree s390_build_builtin_va_list (void);
|
||||
static bool s390_function_ok_for_sibcall (tree, tree);
|
||||
static bool s390_call_saved_register_used (tree);
|
||||
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
|
||||
@ -151,6 +153,9 @@ static tree s390_build_builtin_va_list (void);
|
||||
#undef TARGET_PROMOTE_FUNCTION_RETURN
|
||||
#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
|
||||
|
||||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL s390_function_ok_for_sibcall
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
extern int reload_completed;
|
||||
@ -2610,16 +2615,29 @@ get_thread_pointer (void)
|
||||
return tp;
|
||||
}
|
||||
|
||||
/* Construct the SYMBOL_REF for the tls_get_offset function. */
|
||||
/* Emit a tls call insn. The call target is the SYMBOL_REF stored
|
||||
in s390_tls_symbol which always refers to __tls_get_offset.
|
||||
The returned offset is written to RESULT_REG and an USE rtx is
|
||||
generated for TLS_CALL. */
|
||||
|
||||
static GTY(()) rtx s390_tls_symbol;
|
||||
rtx
|
||||
s390_tls_get_offset (void)
|
||||
|
||||
static void
|
||||
s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
if (!flag_pic)
|
||||
abort ();
|
||||
|
||||
if (!s390_tls_symbol)
|
||||
s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
|
||||
|
||||
return s390_tls_symbol;
|
||||
insn = s390_emit_call (s390_tls_symbol, tls_call, result_reg,
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM));
|
||||
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
|
||||
CONST_OR_PURE_CALL_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
|
||||
@ -2640,7 +2658,7 @@ legitimize_tls_address (rtx addr, rtx reg)
|
||||
new = gen_rtx_CONST (Pmode, tls_call);
|
||||
new = force_const_mem (Pmode, new);
|
||||
emit_move_insn (r2, new);
|
||||
emit_call_insn (gen_call_value_tls (r2, tls_call));
|
||||
s390_emit_tls_call_insn (r2, tls_call);
|
||||
insn = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
@ -2663,7 +2681,7 @@ legitimize_tls_address (rtx addr, rtx reg)
|
||||
new = gen_rtx_CONST (Pmode, tls_call);
|
||||
new = force_const_mem (Pmode, new);
|
||||
emit_move_insn (r2, new);
|
||||
emit_call_insn (gen_call_value_tls (r2, tls_call));
|
||||
s390_emit_tls_call_insn (r2, tls_call);
|
||||
insn = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
@ -5668,15 +5686,8 @@ s390_emit_prologue (void)
|
||||
algorithms located at the branch target.
|
||||
|
||||
This must use register 1. */
|
||||
rtx addr;
|
||||
rtx unkn;
|
||||
rtx link;
|
||||
|
||||
addr = GEN_INT (0xfe0);
|
||||
unkn = CONST0_RTX (SImode);
|
||||
link = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
emit_call_insn (gen_call_exp (gen_rtx_MEM (QImode, addr), unkn, link));
|
||||
s390_emit_call (GEN_INT (0xfe0), NULL_RTX, NULL_RTX,
|
||||
gen_rtx_REG (Pmode, 1));
|
||||
|
||||
/* Emit a blockage here so that all code
|
||||
lies between the profiling mechanisms. */
|
||||
@ -5687,7 +5698,7 @@ s390_emit_prologue (void)
|
||||
/* Expand the epilogue into a bunch of separate insns. */
|
||||
|
||||
void
|
||||
s390_emit_epilogue (void)
|
||||
s390_emit_epilogue (bool sibcall)
|
||||
{
|
||||
rtx frame_pointer, return_reg;
|
||||
int area_bottom, area_top, offset = 0;
|
||||
@ -5703,19 +5714,12 @@ s390_emit_epilogue (void)
|
||||
|
||||
This must use register 1. */
|
||||
|
||||
rtx addr;
|
||||
rtx unkn;
|
||||
rtx link;
|
||||
|
||||
addr = GEN_INT (0xfe6);
|
||||
unkn = CONST0_RTX (SImode);
|
||||
link = gen_rtx_REG (Pmode, 1);
|
||||
|
||||
/* Emit a blockage here so that all code
|
||||
lies between the profiling mechanisms. */
|
||||
emit_insn (gen_blockage ());
|
||||
|
||||
emit_call_insn (gen_call_exp (gen_rtx_MEM (QImode, addr), unkn, link));
|
||||
s390_emit_call (GEN_INT (0xfe6), NULL_RTX, NULL_RTX,
|
||||
gen_rtx_REG (Pmode, 1));
|
||||
}
|
||||
|
||||
/* Check whether to use frame or stack pointer for restore. */
|
||||
@ -5847,23 +5851,26 @@ s390_emit_epilogue (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch return address from stack before load multiple,
|
||||
this will do good for scheduling. */
|
||||
|
||||
if (cfun->machine->save_return_addr_p
|
||||
|| (cfun->machine->first_restore_gpr < BASE_REGISTER
|
||||
&& cfun->machine->last_save_gpr > RETURN_REGNUM))
|
||||
if (! sibcall)
|
||||
{
|
||||
int return_regnum = find_unused_clobbered_reg();
|
||||
if (!return_regnum)
|
||||
return_regnum = 4;
|
||||
return_reg = gen_rtx_REG (Pmode, return_regnum);
|
||||
|
||||
addr = plus_constant (frame_pointer,
|
||||
offset + RETURN_REGNUM * UNITS_PER_WORD);
|
||||
addr = gen_rtx_MEM (Pmode, addr);
|
||||
set_mem_alias_set (addr, s390_sr_alias_set);
|
||||
emit_move_insn (return_reg, addr);
|
||||
/* Fetch return address from stack before load multiple,
|
||||
this will do good for scheduling. */
|
||||
|
||||
if (cfun->machine->save_return_addr_p
|
||||
|| (cfun->machine->first_restore_gpr < BASE_REGISTER
|
||||
&& cfun->machine->last_save_gpr > RETURN_REGNUM))
|
||||
{
|
||||
int return_regnum = find_unused_clobbered_reg();
|
||||
if (!return_regnum)
|
||||
return_regnum = 4;
|
||||
return_reg = gen_rtx_REG (Pmode, return_regnum);
|
||||
|
||||
addr = plus_constant (frame_pointer,
|
||||
offset + RETURN_REGNUM * UNITS_PER_WORD);
|
||||
addr = gen_rtx_MEM (Pmode, addr);
|
||||
set_mem_alias_set (addr, s390_sr_alias_set);
|
||||
emit_move_insn (return_reg, addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ??? As references to the base register are not made
|
||||
@ -5878,13 +5885,17 @@ s390_emit_epilogue (void)
|
||||
emit_insn (insn);
|
||||
}
|
||||
|
||||
/* Return to caller. */
|
||||
if (! sibcall)
|
||||
{
|
||||
|
||||
p = rtvec_alloc (2);
|
||||
|
||||
RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
|
||||
RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
|
||||
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
/* Return to caller. */
|
||||
|
||||
p = rtvec_alloc (2);
|
||||
|
||||
RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
|
||||
RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
|
||||
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6999,4 +7010,179 @@ s390_init_machine_status (void)
|
||||
return ggc_alloc_cleared (sizeof (struct machine_function));
|
||||
}
|
||||
|
||||
/* Checks whether the given ARGUMENT_LIST would use a caller
|
||||
saved register. This is used to decide whether sibling call
|
||||
optimization could be performed on the respective function
|
||||
call. */
|
||||
|
||||
static bool
|
||||
s390_call_saved_register_used (tree argument_list)
|
||||
{
|
||||
CUMULATIVE_ARGS cum;
|
||||
tree parameter;
|
||||
enum machine_mode mode;
|
||||
tree type;
|
||||
rtx parm_rtx;
|
||||
int reg;
|
||||
|
||||
INIT_CUMULATIVE_ARGS (cum, NULL, NULL, 0, 0);
|
||||
|
||||
while (argument_list)
|
||||
{
|
||||
parameter = TREE_VALUE (argument_list);
|
||||
argument_list = TREE_CHAIN (argument_list);
|
||||
|
||||
if (!parameter)
|
||||
abort();
|
||||
|
||||
/* For an undeclared variable passed as parameter we will get
|
||||
an ERROR_MARK node here. */
|
||||
if (TREE_CODE (parameter) == ERROR_MARK)
|
||||
return true;
|
||||
|
||||
if (! (type = TREE_TYPE (parameter)))
|
||||
abort();
|
||||
|
||||
if (! (mode = TYPE_MODE (TREE_TYPE (parameter))))
|
||||
abort();
|
||||
|
||||
if (s390_function_arg_pass_by_reference (mode, type))
|
||||
{
|
||||
mode = Pmode;
|
||||
type = build_pointer_type (type);
|
||||
}
|
||||
|
||||
parm_rtx = s390_function_arg (&cum, mode, type, 0);
|
||||
|
||||
s390_function_arg_advance (&cum, mode, type, 0);
|
||||
|
||||
if (parm_rtx && REG_P (parm_rtx))
|
||||
{
|
||||
for (reg = 0;
|
||||
reg < HARD_REGNO_NREGS (REGNO (parm_rtx), GET_MODE (parm_rtx));
|
||||
reg++)
|
||||
if (! call_used_regs[reg + REGNO (parm_rtx)])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return true if the given call expression can be
|
||||
turned into a sibling call.
|
||||
DECL holds the declaration of the function to be called whereas
|
||||
EXP is the call expression itself. */
|
||||
|
||||
static bool
|
||||
s390_function_ok_for_sibcall (tree decl, tree exp)
|
||||
{
|
||||
/* The TPF epilogue uses register 1. */
|
||||
if (TARGET_TPF)
|
||||
return false;
|
||||
|
||||
/* The 31 bit PLT code uses register 12 (GOT pointer - caller saved)
|
||||
which would have to be restored before the sibcall. */
|
||||
if (!TARGET_64BIT && flag_pic && decl && TREE_PUBLIC (decl))
|
||||
return false;
|
||||
|
||||
/* Register 6 on s390 is available as an argument register but unfortunately
|
||||
"caller saved". This makes functions needing this register for arguments
|
||||
not suitable for sibcalls. */
|
||||
if (TREE_OPERAND (exp, 1)
|
||||
&& s390_call_saved_register_used (TREE_OPERAND (exp, 1)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* This function is used by the call expanders of the machine description.
|
||||
It emits the call insn itself together with the necessary operations
|
||||
to adjust the target address and returns the emitted insn.
|
||||
ADDR_LOCATION is the target address rtx
|
||||
TLS_CALL the location of the thread-local symbol
|
||||
RESULT_REG the register where the result of the call should be stored
|
||||
RETADDR_REG the register where the return address should be stored
|
||||
If this parameter is NULL_RTX the call is considered
|
||||
to be a sibling call. */
|
||||
|
||||
rtx
|
||||
s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
|
||||
rtx retaddr_reg)
|
||||
{
|
||||
bool plt_call = false;
|
||||
rtx insn;
|
||||
rtx call;
|
||||
rtx clobber;
|
||||
rtvec vec;
|
||||
|
||||
/* Direct function calls need special treatment. */
|
||||
if (GET_CODE (addr_location) == SYMBOL_REF)
|
||||
{
|
||||
/* When calling a global routine in PIC mode, we must
|
||||
replace the symbol itself with the PLT stub. */
|
||||
if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
|
||||
{
|
||||
addr_location = gen_rtx_UNSPEC (Pmode,
|
||||
gen_rtvec (1, addr_location),
|
||||
UNSPEC_PLT);
|
||||
addr_location = gen_rtx_CONST (Pmode, addr_location);
|
||||
plt_call = true;
|
||||
}
|
||||
|
||||
/* Unless we can use the bras(l) insn, force the
|
||||
routine address into a register. */
|
||||
if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
|
||||
{
|
||||
if (flag_pic)
|
||||
addr_location = legitimize_pic_address (addr_location, 0);
|
||||
else
|
||||
addr_location = force_reg (Pmode, addr_location);
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is already an indirect call or the code above moved the
|
||||
SYMBOL_REF to somewhere else make sure the address can be found in
|
||||
register 1. */
|
||||
if (retaddr_reg == NULL_RTX
|
||||
&& GET_CODE (addr_location) != SYMBOL_REF
|
||||
&& !plt_call)
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (Pmode, SIBCALL_REGNUM), addr_location);
|
||||
addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM);
|
||||
}
|
||||
|
||||
addr_location = gen_rtx_MEM (QImode, addr_location);
|
||||
call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
|
||||
|
||||
if (result_reg != NULL_RTX)
|
||||
call = gen_rtx_SET (VOIDmode, result_reg, call);
|
||||
|
||||
if (retaddr_reg != NULL_RTX)
|
||||
{
|
||||
clobber = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
|
||||
|
||||
if (tls_call != NULL_RTX)
|
||||
vec = gen_rtvec (3, call, clobber,
|
||||
gen_rtx_USE (VOIDmode, tls_call));
|
||||
else
|
||||
vec = gen_rtvec (2, call, clobber);
|
||||
|
||||
call = gen_rtx_PARALLEL (VOIDmode, vec);
|
||||
}
|
||||
|
||||
insn = emit_call_insn (call);
|
||||
|
||||
/* 31-bit PLT stubs and tls calls use the GOT register implicitly. */
|
||||
if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX)
|
||||
{
|
||||
/* s390_function_ok_for_sibcall should
|
||||
have denied sibcalls in this case. */
|
||||
if (retaddr_reg == NULL_RTX)
|
||||
abort ();
|
||||
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
|
||||
#include "gt-s390.h"
|
||||
|
@ -299,6 +299,7 @@ if (INTEGRAL_MODE_P (MODE) && \
|
||||
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
|
||||
#define FRAME_REG_P(X) (REG_P (X) && FRAME_REGNO_P (REGNO (X)))
|
||||
|
||||
#define SIBCALL_REGNUM 1
|
||||
#define BASE_REGISTER 13
|
||||
#define RETURN_REGNUM 14
|
||||
#define CC_REGNUM 33
|
||||
|
@ -6970,6 +6970,87 @@
|
||||
[(set_attr "type" "none")
|
||||
(set_attr "length" "0")])
|
||||
|
||||
;
|
||||
; sibcall patterns
|
||||
;
|
||||
|
||||
(define_expand "sibcall"
|
||||
[(call (match_operand 0 "" "")
|
||||
(match_operand 1 "" ""))]
|
||||
""
|
||||
{
|
||||
s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX, NULL_RTX);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "*sibcall_br"
|
||||
[(call (mem:QI (reg 1))
|
||||
(match_operand 0 "const_int_operand" "n"))]
|
||||
"SIBLING_CALL_P (insn)
|
||||
&& GET_MODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == Pmode"
|
||||
"br\t%%r1"
|
||||
[(set_attr "op_type" "RR")
|
||||
(set_attr "type" "branch")
|
||||
(set_attr "atype" "agen")])
|
||||
|
||||
(define_insn "*sibcall_brc"
|
||||
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
|
||||
(match_operand 1 "const_int_operand" "n"))]
|
||||
"SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
|
||||
"j\t%0"
|
||||
[(set_attr "op_type" "RI")
|
||||
(set_attr "type" "branch")])
|
||||
|
||||
(define_insn "*sibcall_brcl"
|
||||
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
|
||||
(match_operand 1 "const_int_operand" "n"))]
|
||||
"SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
|
||||
"jg\t%0"
|
||||
[(set_attr "op_type" "RIL")
|
||||
(set_attr "type" "branch")])
|
||||
|
||||
;
|
||||
; sibcall_value patterns
|
||||
;
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "" "")
|
||||
(match_operand 2 "" "")))]
|
||||
""
|
||||
{
|
||||
s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0], NULL_RTX);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "*sibcall_value_br"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (reg 1))
|
||||
(match_operand 1 "const_int_operand" "n")))]
|
||||
"SIBLING_CALL_P (insn)
|
||||
&& GET_MODE (XEXP (XEXP (XEXP (PATTERN (insn), 1), 0), 0)) == Pmode"
|
||||
"br\t%%r1"
|
||||
[(set_attr "op_type" "RR")
|
||||
(set_attr "type" "branch")
|
||||
(set_attr "atype" "agen")])
|
||||
|
||||
(define_insn "*sibcall_value_brc"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
|
||||
"j\t%1"
|
||||
[(set_attr "op_type" "RI")
|
||||
(set_attr "type" "branch")])
|
||||
|
||||
(define_insn "*sibcall_value_brcl"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
|
||||
"jg\t%1"
|
||||
[(set_attr "op_type" "RIL")
|
||||
(set_attr "type" "branch")])
|
||||
|
||||
|
||||
;
|
||||
@ -6982,59 +7063,18 @@
|
||||
(use (match_operand 2 "" ""))]
|
||||
""
|
||||
{
|
||||
bool plt_call = false;
|
||||
rtx insn;
|
||||
|
||||
/* Direct function calls need special treatment. */
|
||||
if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
|
||||
{
|
||||
rtx sym = XEXP (operands[0], 0);
|
||||
|
||||
/* When calling a global routine in PIC mode, we must
|
||||
replace the symbol itself with the PLT stub. */
|
||||
if (flag_pic && !SYMBOL_REF_LOCAL_P (sym))
|
||||
{
|
||||
sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
|
||||
sym = gen_rtx_CONST (Pmode, sym);
|
||||
plt_call = true;
|
||||
}
|
||||
|
||||
/* Unless we can use the bras(l) insn, force the
|
||||
routine address into a register. */
|
||||
if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
|
||||
{
|
||||
if (flag_pic)
|
||||
sym = legitimize_pic_address (sym, 0);
|
||||
else
|
||||
sym = force_reg (Pmode, sym);
|
||||
}
|
||||
|
||||
operands[0] = gen_rtx_MEM (QImode, sym);
|
||||
}
|
||||
|
||||
/* Emit insn. */
|
||||
insn = emit_call_insn (gen_call_exp (operands[0], operands[1],
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM)));
|
||||
|
||||
/* 31-bit PLT stubs use the GOT register implicitly. */
|
||||
if (!TARGET_64BIT && plt_call)
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
|
||||
s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX,
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "call_exp"
|
||||
[(parallel [(call (match_operand 0 "" "")
|
||||
(match_operand 1 "" ""))
|
||||
(clobber (match_operand 2 "" ""))])]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*bras"
|
||||
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(clobber (match_operand 2 "register_operand" "=r"))]
|
||||
"TARGET_SMALL_EXEC && GET_MODE (operands[2]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_SMALL_EXEC
|
||||
&& GET_MODE (operands[2]) == Pmode"
|
||||
"bras\t%2,%0"
|
||||
[(set_attr "op_type" "RI")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7043,7 +7083,9 @@
|
||||
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(clobber (match_operand 2 "register_operand" "=r"))]
|
||||
"TARGET_CPU_ZARCH && GET_MODE (operands[2]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_CPU_ZARCH
|
||||
&& GET_MODE (operands[2]) == Pmode"
|
||||
"brasl\t%2,%0"
|
||||
[(set_attr "op_type" "RIL")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7052,7 +7094,7 @@
|
||||
[(call (mem:QI (match_operand 0 "address_operand" "U"))
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(clobber (match_operand 2 "register_operand" "=r"))]
|
||||
"GET_MODE (operands[2]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
|
||||
{
|
||||
if (get_attr_op_type (insn) == OP_TYPE_RR)
|
||||
return "basr\t%2,%0";
|
||||
@ -7076,62 +7118,19 @@
|
||||
(use (match_operand 3 "" ""))]
|
||||
""
|
||||
{
|
||||
bool plt_call = false;
|
||||
rtx insn;
|
||||
|
||||
/* Direct function calls need special treatment. */
|
||||
if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
|
||||
{
|
||||
rtx sym = XEXP (operands[1], 0);
|
||||
|
||||
/* When calling a global routine in PIC mode, we must
|
||||
replace the symbol itself with the PLT stub. */
|
||||
if (flag_pic && !SYMBOL_REF_LOCAL_P (sym))
|
||||
{
|
||||
sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
|
||||
sym = gen_rtx_CONST (Pmode, sym);
|
||||
plt_call = true;
|
||||
}
|
||||
|
||||
/* Unless we can use the bras(l) insn, force the
|
||||
routine address into a register. */
|
||||
if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
|
||||
{
|
||||
if (flag_pic)
|
||||
sym = legitimize_pic_address (sym, 0);
|
||||
else
|
||||
sym = force_reg (Pmode, sym);
|
||||
}
|
||||
|
||||
operands[1] = gen_rtx_MEM (QImode, sym);
|
||||
}
|
||||
|
||||
/* Emit insn. */
|
||||
insn = emit_call_insn (
|
||||
gen_call_value_exp (operands[0], operands[1], operands[2],
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM)));
|
||||
|
||||
/* 31-bit PLT stubs use the GOT register implicitly. */
|
||||
if (!TARGET_64BIT && plt_call)
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
|
||||
s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0],
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "call_value_exp"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "" "")
|
||||
(match_operand 2 "" "")))
|
||||
(clobber (match_operand 3 "" ""))])]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*bras_r"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
|
||||
(match_operand:SI 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))]
|
||||
"TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_SMALL_EXEC
|
||||
&& GET_MODE (operands[3]) == Pmode"
|
||||
"bras\t%3,%1"
|
||||
[(set_attr "op_type" "RI")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7141,7 +7140,9 @@
|
||||
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))]
|
||||
"TARGET_CPU_ZARCH && GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_CPU_ZARCH
|
||||
&& GET_MODE (operands[3]) == Pmode"
|
||||
"brasl\t%3,%1"
|
||||
[(set_attr "op_type" "RIL")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7151,7 +7152,7 @@
|
||||
(call (mem:QI (match_operand 1 "address_operand" "U"))
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))]
|
||||
"GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
|
||||
{
|
||||
if (get_attr_op_type (insn) == OP_TYPE_RR)
|
||||
return "basr\t%3,%1";
|
||||
@ -7229,64 +7230,15 @@
|
||||
ly\t%0,%1%J2"
|
||||
[(set_attr "op_type" "RX,RXY")])
|
||||
|
||||
(define_expand "call_value_tls"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (const_int 0) (const_int 0)))
|
||||
(use (match_operand 1 "" ""))]
|
||||
""
|
||||
{
|
||||
rtx insn, sym;
|
||||
|
||||
if (!flag_pic)
|
||||
abort ();
|
||||
|
||||
sym = s390_tls_get_offset ();
|
||||
sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
|
||||
sym = gen_rtx_CONST (Pmode, sym);
|
||||
|
||||
/* Unless we can use the bras(l) insn, force the
|
||||
routine address into a register. */
|
||||
if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
|
||||
{
|
||||
if (flag_pic)
|
||||
sym = legitimize_pic_address (sym, 0);
|
||||
else
|
||||
sym = force_reg (Pmode, sym);
|
||||
}
|
||||
|
||||
sym = gen_rtx_MEM (QImode, sym);
|
||||
|
||||
/* Emit insn. */
|
||||
insn = emit_call_insn (
|
||||
gen_call_value_tls_exp (operands[0], sym, const0_rtx,
|
||||
gen_rtx_REG (Pmode, RETURN_REGNUM),
|
||||
operands[1]));
|
||||
|
||||
/* The calling convention of __tls_get_offset uses the
|
||||
GOT register implicitly. */
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), operands[0]);
|
||||
CONST_OR_PURE_CALL_P (insn) = 1;
|
||||
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "call_value_tls_exp"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "" "")
|
||||
(match_operand 2 "" "")))
|
||||
(clobber (match_operand 3 "" ""))
|
||||
(use (match_operand 4 "" ""))])]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*bras_tls"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))
|
||||
(use (match_operand 4 "" ""))]
|
||||
"TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_SMALL_EXEC
|
||||
&& GET_MODE (operands[3]) == Pmode"
|
||||
"bras\t%3,%1%J4"
|
||||
[(set_attr "op_type" "RI")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7297,7 +7249,9 @@
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))
|
||||
(use (match_operand 4 "" ""))]
|
||||
"TARGET_CPU_ZARCH && GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn)
|
||||
&& TARGET_CPU_ZARCH
|
||||
&& GET_MODE (operands[3]) == Pmode"
|
||||
"brasl\t%3,%1%J4"
|
||||
[(set_attr "op_type" "RIL")
|
||||
(set_attr "type" "jsr")])
|
||||
@ -7308,7 +7262,7 @@
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))
|
||||
(use (match_operand 4 "" ""))]
|
||||
"GET_MODE (operands[3]) == Pmode"
|
||||
"!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
|
||||
{
|
||||
if (get_attr_op_type (insn) == OP_TYPE_RR)
|
||||
return "basr\t%3,%1%J4";
|
||||
@ -7571,7 +7525,12 @@
|
||||
(define_expand "epilogue"
|
||||
[(use (const_int 1))]
|
||||
""
|
||||
"s390_emit_epilogue (); DONE;")
|
||||
"s390_emit_epilogue (false); DONE;")
|
||||
|
||||
(define_expand "sibcall_epilogue"
|
||||
[(use (const_int 0))]
|
||||
""
|
||||
"s390_emit_epilogue (true); DONE;")
|
||||
|
||||
(define_insn "*return"
|
||||
[(return)
|
||||
|
@ -1,3 +1,9 @@
|
||||
2004-04-29 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* gcc.dg/sibcall-3.c: Delete s390 from expected fail list.
|
||||
* gcc.dg/sibcall-4.c: Likewise.
|
||||
* gcc.dg/sibcall-6.c: Enable s390 as test platform.
|
||||
|
||||
2004-04-30 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* gcc.c-torture/execute/20040331-1.c: Don't use too wide a
|
||||
|
@ -5,7 +5,7 @@
|
||||
Copyright (C) 2002 Free Software Foundation Inc.
|
||||
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
|
||||
|
||||
/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
||||
/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
||||
/* { dg-options "-O2 -foptimize-sibling-calls" } */
|
||||
|
||||
/* The option -foptimize-sibling-calls is the default, but serves as
|
||||
|
@ -5,7 +5,7 @@
|
||||
Copyright (C) 2002 Free Software Foundation Inc.
|
||||
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
|
||||
|
||||
/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
||||
/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
||||
/* { dg-options "-O2 -foptimize-sibling-calls" } */
|
||||
|
||||
/* The option -foptimize-sibling-calls is the default, but serves as
|
||||
|
@ -6,7 +6,7 @@
|
||||
Copyright (C) 2002 Free Software Foundation Inc.
|
||||
Contributed by Andreas Bauer <baueran@in.tum.de> */
|
||||
|
||||
/* { dg-do run { target i?86-*-* x86_64-*-*} } */
|
||||
/* { dg-do run { target i?86-*-* s390*-*-* x86_64-*-*} } */
|
||||
/* { dg-options "-O2 -foptimize-sibling-calls" } */
|
||||
|
||||
int foo (int);
|
||||
|
Loading…
x
Reference in New Issue
Block a user