From ed9676cf0ca3101a8933826b0dcc9aacae689f23 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 30 Apr 2004 16:40:22 +0000 Subject: [PATCH] s390-protos.h (s390_emit_epilogue): Parameter added. 2004-04-29 Andreas Krebbel 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 --- gcc/ChangeLog | 29 ++++ gcc/config/s390/s390-protos.h | 4 +- gcc/config/s390/s390.c | 280 +++++++++++++++++++++++++------ gcc/config/s390/s390.h | 1 + gcc/config/s390/s390.md | 263 ++++++++++++----------------- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.dg/sibcall-3.c | 2 +- gcc/testsuite/gcc.dg/sibcall-4.c | 2 +- gcc/testsuite/gcc.dg/sibcall-6.c | 2 +- 9 files changed, 385 insertions(+), 204 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 57085d84f4f..4ef6b7eb4b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2004-04-29 Andreas Krebbel + + * 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 * bb-reorder.c, c-opts.c, cfglayout.c, cgraph.c, cgraphunit.c, diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 49dad24b5e7..a42dd20ab33 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -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); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index ed277ad4e85..35dca944d77 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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. */ - - p = rtvec_alloc (2); + if (! sibcall) + { - 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" diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 3354f45beed..0c4f2b381b0 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/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 diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index f6aeefbc175..30a7b8d7329 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -6970,71 +6970,111 @@ [(set_attr "type" "none") (set_attr "length" "0")]) - - ; -; call instruction pattern(s). +; sibcall patterns ; -(define_expand "call" +(define_expand "sibcall" [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] + (match_operand 1 "" ""))] "" { - 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); + s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX, NULL_RTX); + DONE; +}) - /* 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; - } +(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")]) - /* 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); - } +(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")]) - operands[0] = gen_rtx_MEM (QImode, sym); - } +(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")]) - /* Emit insn. */ - insn = emit_call_insn (gen_call_exp (operands[0], operands[1], - gen_rtx_REG (Pmode, RETURN_REGNUM))); +; +; sibcall_value patterns +; - /* 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); - +(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_expand "call_exp" - [(parallel [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (clobber (match_operand 2 "" ""))])] +(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")]) + + +; +; call instruction pattern(s). +; + +(define_expand "call" + [(call (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] "" - "") +{ + s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX, + gen_rtx_REG (Pmode, RETURN_REGNUM)); + DONE; +}) (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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5cc6e2e4289..6b13596625c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-04-29 Andreas Krebbel + + * 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 * gcc.c-torture/execute/20040331-1.c: Don't use too wide a diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c index d0908a2289c..e61110f0c41 100644 --- a/gcc/testsuite/gcc.dg/sibcall-3.c +++ b/gcc/testsuite/gcc.dg/sibcall-3.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson */ -/* { 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 diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c index 3980879536c..9674e75bd9c 100644 --- a/gcc/testsuite/gcc.dg/sibcall-4.c +++ b/gcc/testsuite/gcc.dg/sibcall-4.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson */ -/* { 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 diff --git a/gcc/testsuite/gcc.dg/sibcall-6.c b/gcc/testsuite/gcc.dg/sibcall-6.c index 771a14e8b56..4b0d299f5b7 100644 --- a/gcc/testsuite/gcc.dg/sibcall-6.c +++ b/gcc/testsuite/gcc.dg/sibcall-6.c @@ -6,7 +6,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Andreas Bauer */ -/* { 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); -- 2.30.2