From: rsandifo Date: Fri, 7 Feb 2014 14:52:26 +0000 (+0000) Subject: gcc/ X-Git-Tag: upstream/4.9.2~1195 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7a64c761698e15b8be5f4fbda6147bdc53bc0d5f;p=platform%2Fupstream%2Flinaro-gcc.git gcc/ * config/s390/s390-protos.h (s390_can_use_simple_return_insn) (s390_can_use_return_insn): Declare. * config/s390/s390.h (EPILOGUE_USES): Define. * config/s390/s390.c (s390_mainpool_start): Allow two main_pool instructions. (s390_chunkify_start): Handle return JUMP_LABELs. (s390_early_mach): Emit a main_pool instruction on the entry edge. (s300_set_up_by_prologue, s390_can_use_simple_return_insn) (s390_can_use_return_insn): New functions. (s390_fix_long_loop_prediction): Handle conditional returns. (TARGET_SET_UP_BY_PROLOGUE): Define. * config/s390/s390.md (ANY_RETURN): New code iterator. (*creturn, *csimple_return, return, simple_return): New patterns. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207605 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0d0f887..5703bb5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,21 @@ 2014-02-07 Richard Sandiford + * config/s390/s390-protos.h (s390_can_use_simple_return_insn) + (s390_can_use_return_insn): Declare. + * config/s390/s390.h (EPILOGUE_USES): Define. + * config/s390/s390.c (s390_mainpool_start): Allow two main_pool + instructions. + (s390_chunkify_start): Handle return JUMP_LABELs. + (s390_early_mach): Emit a main_pool instruction on the entry edge. + (s300_set_up_by_prologue, s390_can_use_simple_return_insn) + (s390_can_use_return_insn): New functions. + (s390_fix_long_loop_prediction): Handle conditional returns. + (TARGET_SET_UP_BY_PROLOGUE): Define. + * config/s390/s390.md (ANY_RETURN): New code iterator. + (*creturn, *csimple_return, return, simple_return): New patterns. + +2014-02-07 Richard Sandiford + * config/s390/s390.c (s390_restore_gprs_from_fprs): Add REG_CFA_RESTORE notes to each restore. Also add REG_CFA_DEF_CFA when restoring %r15. (s390_optimize_prologue): Don't clear RTX_FRAME_RELATED_P. Update the diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 72f8bb7..9bd08fa 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -36,6 +36,8 @@ extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment); extern HOST_WIDE_INT s390_initial_elimination_offset (int, int); extern void s390_emit_prologue (void); extern void s390_emit_epilogue (bool); +extern bool s390_can_use_simple_return_insn (void); +extern bool s390_can_use_return_insn (void); extern void s390_function_profiler (FILE *, int); extern void s390_set_has_landing_pad_p (bool); extern bool s390_hard_regno_mode_ok (unsigned int, enum machine_mode); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 2d6f8d0..993ed84 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -6673,7 +6673,15 @@ s390_mainpool_start (void) && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL) { - gcc_assert (!pool->pool_insn); + /* There might be two main_pool instructions if base_reg + is call-clobbered; one for shrink-wrapped code and one + for the rest. We want to keep the first. */ + if (pool->pool_insn) + { + insn = PREV_INSN (insn); + delete_insn (NEXT_INSN (insn)); + continue; + } pool->pool_insn = insn; } @@ -7110,7 +7118,7 @@ s390_chunkify_start (void) if (GET_CODE (pat) == SET) { rtx label = JUMP_LABEL (insn); - if (label) + if (label && !ANY_RETURN_P (label)) { if (s390_find_pool (pool_list, label) != s390_find_pool (pool_list, insn)) @@ -8635,6 +8643,11 @@ s390_early_mach (void) /* Re-compute register info. */ s390_register_info (); + /* If we're using a base register, ensure that it is always valid for + the first non-prologue instruction. */ + if (cfun->machine->base_reg) + emit_insn_at_entry (gen_main_pool (cfun->machine->base_reg)); + /* Annotate all constant pool references to let the scheduler know they implicitly use the base register. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) @@ -9170,6 +9183,55 @@ s390_emit_epilogue (bool sibcall) } } +/* Implement TARGET_SET_UP_BY_PROLOGUE. */ + +static void +s300_set_up_by_prologue (hard_reg_set_container *regs) +{ + if (cfun->machine->base_reg + && !call_really_used_regs[REGNO (cfun->machine->base_reg)]) + SET_HARD_REG_BIT (regs->set, REGNO (cfun->machine->base_reg)); +} + +/* Return true if the function can use simple_return to return outside + of a shrink-wrapped region. At present shrink-wrapping is supported + in all cases. */ + +bool +s390_can_use_simple_return_insn (void) +{ + return true; +} + +/* Return true if the epilogue is guaranteed to contain only a return + instruction and if a direct return can therefore be used instead. + One of the main advantages of using direct return instructions + is that we can then use conditional returns. */ + +bool +s390_can_use_return_insn (void) +{ + int i; + + if (!reload_completed) + return false; + + if (crtl->profile) + return false; + + if (TARGET_TPF_PROFILING) + return false; + + for (i = 0; i < 16; i++) + if (cfun_gpr_save_slot (i)) + return false; + + if (cfun->machine->base_reg + && !call_really_used_regs[REGNO (cfun->machine->base_reg)]) + return false; + + return cfun_frame_layout.frame_size == 0; +} /* Return the size in bytes of a function argument of type TYPE and/or mode MODE. At least one of TYPE or @@ -11019,6 +11081,11 @@ s390_fix_long_loop_prediction (rtx insn) || GET_CODE (SET_SRC(set)) != IF_THEN_ELSE) return false; + /* Skip conditional returns. */ + if (ANY_RETURN_P (XEXP (SET_SRC (set), 1)) + && XEXP (SET_SRC (set), 2) == pc_rtx) + return false; + label_ref = (GET_CODE (XEXP (SET_SRC (set), 1)) == LABEL_REF ? XEXP (SET_SRC (set), 1) : XEXP (SET_SRC (set), 2)); @@ -12163,6 +12230,9 @@ s390_option_override (void) #undef TARGET_CAN_INLINE_P #define TARGET_CAN_INLINE_P s390_can_inline_p +#undef TARGET_SET_UP_BY_PROLOGUE +#define TARGET_SET_UP_BY_PROLOGUE s300_set_up_by_prologue + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-s390.h" diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 9099fc8..2f2139e 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -878,6 +878,10 @@ do { \ fputc ('\n', (FILE)); \ } while (0) +/* Mark the return register as used by the epilogue so that we can + use it in unadorned (return) and (simple_return) instructions. */ +#define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_REGNUM) + #undef ASM_OUTPUT_FUNCTION_LABEL #define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \ s390_asm_output_function_label (FILE, NAME, DECL) diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 3f86304..76902b5 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -598,6 +598,9 @@ ;; In place of GET_MODE_BITSIZE (mode) (define_mode_attr bitsize [(DI "64") (SI "32") (HI "16") (QI "8")]) +;; Allow return and simple_return to be defined from a single template. +(define_code_iterator ANY_RETURN [return simple_return]) + ;; ;;- Compare instructions. ;; @@ -8079,6 +8082,18 @@ (set_attr "type" "branch") (set_attr "atype" "agen")]) +;; A conditional return instruction. +(define_insn "*c" + [(set (pc) + (if_then_else + (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)]) + (ANY_RETURN) + (pc)))] + "s390_can_use__insn ()" + "b%C0r\t%%r14" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr") + (set_attr "atype" "agen")]) ;; ;;- Negated conditional jump instructions. @@ -9674,6 +9689,15 @@ "" "s390_emit_epilogue (true); DONE;") +;; A direct return instruction, without using an epilogue. +(define_insn "" + [(ANY_RETURN)] + "s390_can_use__insn ()" + "br\t%%r14" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr") + (set_attr "atype" "agen")]) + (define_insn "*return" [(return) (use (match_operand 0 "register_operand" "a"))]