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
This commit is contained in:
Oleg Endo 2016-05-07 01:43:12 +00:00
parent 02ceba4404
commit e22daa4bb5
4 changed files with 71 additions and 11 deletions

View File

@ -1,3 +1,10 @@
2016-05-07 Oleg Endo <olegendo@gcc.gnu.org>
* 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 <ubizjak@gmail.com>
* config/i386/i386.md (LEAMODE): New mode attribute.

View File

@ -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);

View File

@ -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<rtx_jump_insn*> (_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<rtx_code_label*> (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)

View File

@ -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)])
;; -------------------------------------------------------------------------