From e22daa4bb5154115b93f2e7b86a7d1ae74203eab Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Sat, 7 May 2016 01:43:12 +0000 Subject: [PATCH] sh-protos.h (sh_cbranch_distance): Declare new function. gcc/ * config/sh/sh-protos.h (sh_cbranch_distance): Declare new function. * config/sh/sh.c (sh_cbranch_distance): Implement it. * config/sh/sh.md (branch_zero): Remove define_attr. (define_delay): Disable delay slot if branch distance is one insn. From-SVN: r235993 --- gcc/ChangeLog | 7 ++++++ gcc/config/sh/sh-protos.h | 12 ++++++++++ gcc/config/sh/sh.c | 46 +++++++++++++++++++++++++++++++++++++++ gcc/config/sh/sh.md | 17 +++++---------- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 156359254af..ce10e79d4e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-05-07 Oleg Endo + + * config/sh/sh-protos.h (sh_cbranch_distance): Declare new function. + * config/sh/sh.c (sh_cbranch_distance): Implement it. + * config/sh/sh.md (branch_zero): Remove define_attr. + (define_delay): Disable delay slot if branch distance is one insn. + 2016-05-06 Uros Bizjak * config/i386/i386.md (LEAMODE): New mode attribute. diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index c47e2eade15..d302394d52e 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -348,6 +348,18 @@ private: extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn); +enum +{ + /* An effective conditional branch distance of zero bytes is impossible. + Hence we can use it to designate an unknown value. */ + unknown_cbranch_distance = 0u, + infinite_cbranch_distance = ~0u +}; + +unsigned int +sh_cbranch_distance (rtx_insn* cbranch_insn, + unsigned int max_dist = infinite_cbranch_distance); + #endif /* RTX_CODE */ extern void sh_cpu_cpp_builtins (cpp_reader* pfile); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 809f679f807..6d1d1a38eeb 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1928,6 +1928,52 @@ sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2) return true; } +/* Try to calculate the branch distance of a conditional branch in bytes. + + FIXME: Because of PR 59189 we can't use the CFG here. Instead just + walk from this insn into the next (fall-through) basic block and see if + we hit the label. */ +unsigned int +sh_cbranch_distance (rtx_insn* _cbranch_insn, unsigned int max_dist) +{ + rtx_jump_insn* cbranch_insn = safe_as_a (_cbranch_insn); + + if (dump_file) + { + fprintf (dump_file, "sh_cbranch_distance insn = \n"); + print_rtl_single (dump_file, cbranch_insn); + } + + unsigned int dist = 0; + + for (rtx_insn* i = next_nonnote_insn (cbranch_insn); + i != NULL && dist < max_dist; i = next_nonnote_insn (i)) + { + const unsigned int i_len = get_attr_length (i); + dist += i_len; + + if (dump_file) + fprintf (dump_file, " insn %d length = %u dist = %u\n", + INSN_UID (i), i_len, dist); + + if (rtx_code_label* l = dyn_cast (i)) + { + if (l == cbranch_insn->jump_target ()) + { + if (dump_file) + fprintf (dump_file, " cbranch dist = %u\n", dist); + return dist; + } + break; + } + } + + if (dump_file) + fprintf (dump_file, " cbranch dist = unknown\n"); + + return unknown_cbranch_distance; +} + enum rtx_code prepare_cbranch_operands (rtx *operands, machine_mode mode, enum rtx_code comparison) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 39270ce8e92..406721dc736 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -477,16 +477,6 @@ (define_attr "is_sfunc" "" (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0))) -(define_attr "branch_zero" "yes,no" - (cond [(eq_attr "type" "!cbranch") (const_string "no") - (ne (symbol_ref "(next_active_insn (insn)\ - == (prev_active_insn\ - (XEXP (SET_SRC (PATTERN (insn)), 1))))\ - && get_attr_length (next_active_insn (insn)) == 2") - (const_int 0)) - (const_string "yes")] - (const_string "no"))) - ;; SH4 Double-precision computation with double-precision result - ;; the two halves are ready at different times. (define_attr "dfp_comp" "yes,no" @@ -539,8 +529,13 @@ (eq_attr "type" "!pstore,prget")) (nil) (nil)]) ;; Conditional branches with delay slots are available starting with SH2. +;; If zero displacement conditional branches are fast, disable the delay +;; slot if the branch jumps over only one 2-byte insn. (define_delay - (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2")) + (and (eq_attr "type" "cbranch") + (match_test "TARGET_SH2") + (not (and (match_test "TARGET_ZDCBRANCH") + (match_test "sh_cbranch_distance (insn, 4) == 2")))) [(eq_attr "cond_delay_slot" "yes") (nil) (nil)]) ;; ------------------------------------------------------------------------- -- 2.30.2