summaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh-protos.h
diff options
context:
space:
mode:
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-24 13:04:53 +0000
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-24 13:04:53 +0000
commit6c97af1ba027ad70e8c722321fdaa4a157bc4cbc (patch)
treedb69dc3cf457df982a926d511d89a52be95ee9fc /gcc/config/sh/sh-protos.h
parent7155272449218f29e2aacb6938cf361d54081ecb (diff)
downloadgcc-6c97af1ba027ad70e8c722321fdaa4a157bc4cbc.tar.gz
gcc/
PR target/49263 PR target/53987 PR target/64345 PR target/59533 PR target/52933 PR target/54236 PR target/51244 * config/sh/sh-protos.h (sh_extending_set_of_reg::can_use_as_unextended_reg, sh_extending_set_of_reg::use_as_unextended_reg, sh_is_nott_insn, sh_movt_set_dest, sh_movrt_set_dest, sh_is_movt_insn, sh_is_movrt_insn, sh_insn_operands_modified_between_p, sh_reg_dead_or_unused_after_insn, sh_in_recog_treg_set_expr, sh_recog_treg_set_expr, sh_split_treg_set_expr): New functions. (sh_treg_insns): New class. * config/sh/sh.c (TARGET_LEGITIMATE_COMBINED_INSN): Define target hook. (scope_counter): New class. (sh_legitimate_combined_insn, sh_is_nott_insn, sh_movt_set_dest, sh_movrt_set_dest, sh_reg_dead_or_unused_after_insn, sh_extending_set_of_reg::can_use_as_unextended_reg, sh_extending_set_of_reg::use_as_unextended_reg, sh_recog_treg_set_expr, sh_in_recog_treg_set_expr, sh_try_split_insn_simple, sh_split_treg_set_expr): New functions. (addsubcosts): Handle treg_set_expr. (sh_rtx_costs): Handle IF_THEN_ELSE and ZERO_EXTRACT. (sh_rtx_costs): Use arith_reg_operand in SIGN_EXTEND and ZERO_EXTEND. (sh_rtx_costs): Handle additional bit test patterns in EQ and AND cases. (sh_insn_operands_modified_between_p): Make non-static. * config/sh/predicates.md (zero_extend_movu_operand): Allow simple_mem_operand in addition to displacement_mem_operand. (zero_extend_operand): Don't allow zero_extend_movu_operand. (treg_set_expr, treg_set_expr_not_const01, arith_reg_or_treg_set_expr): New predicates. * config/sh/sh.md (tstsi_t): Use arith_reg_operand and arith_or_int_operand instead of logical_operand. Convert to insn_and_split. Try to optimize constant operand in splitter. (tsthi_t, tstqi_t): Fold into *tst<mode>_t. Convert to insn_and_split. (*tstqi_t_zero): Delete. (*tst<mode>_t_subregs): Add !sh_in_recog_treg_set_expr split condition. (tstsi_t_and_not): Delete. (tst<mode>_t_zero_extract_eq): Rename to *tst<mode>_t_zero_extract. Convert to insn_and_split. (unnamed split, tstsi_t_zero_extract_xor, tstsi_t_zero_extract_subreg_xor_little, tstsi_t_zero_extract_subreg_xor_big): Delete. (*tstsi_t_shift_mask): New insn_and_split. (cmpeqsi_t, cmpgesi_t): Add new split for const_int 0 operands and try to recombine with surrounding insns when splitting. (*negtstsi): Add !sh_in_recog_treg_set_expr condition. (cmp_div0s_0, cmp_div0s_1, *cmp_div0s_0, *cmp_div0s_1): Rewrite as ... (cmp_div0s, *cmp_div0s_1, *cmp_div0s_2, *cmp_div0s_3, *cmp_div0s_4, *cmp_div0s_5, *cmp_div0s_6): ... these new insn_and_split patterns. (*cbranch_div0s: Delete. (*addc): Convert to insn_and_split. Use treg_set_expr as 3rd operand. Try to recombine with surrounding insns when splitting. Add operand order variants. (*addc_t_r, *addc_r_t): Use treg_set_expr_not_const01. (*addc_r_r_1, *addc_r_lsb, *addc_r_r_lsb, *addc_r_lsb_r, *addc_r_msb, *addc_r_r_msb, *addc_2r_msb): Delete. (*addc_2r_lsb): Rename to *addc_2r_t. Use treg_set_expr. Add operand order variant. (*addc_negreg_t): New insn_and_split. (*subc): Convert to insn_and_split. Use treg_set_expr as 3rd operand. Try to recombine with surrounding insns when splitting. Add operand order variants. (*subc_negt_reg, *subc_negreg_t, *reg_lsb_t, *reg_msb_t): New insn_and_split patterns. (*rotcr): Use arith_reg_or_treg_set_expr. Try to recombine with surrounding insns when splitting. (unnamed rotcr split): Use arith_reg_or_treg_set_expr. (*rotcl): Likewise. Add zero_extract variant. (*ashrsi2_31): New insn_and_split. (*negc): Convert to insn_and_split. Use treg_set_expr. (*zero_extend<mode>si2_disp_mem): Update comment. (movrt_negc, *movrt_negc, nott): Add !sh_in_recog_treg_set_expr split condition. (*mov_t_msb_neg, mov_neg_si_t): Use treg_set_expr. Try to recombine with surrounding insns when splitting. (any_treg_expr_to_reg): New insn_and_split. (*neg_zero_extract_0, *neg_zero_extract_1, *neg_zero_extract_2, *neg_zero_extract_3, *neg_zero_extract_4, *neg_zero_extract_5, *neg_zero_extract_6, *zero_extract_0, *zero_extract_1, *zero_extract_2): New single bit zero extract patterns. (bld_reg, *bld_regqi): Fold into bld<mode>_reg. (*get_thread_pointersi, store_gbr, *mov<mode>_gbr_load, *mov<mode>_gbr_load, *mov<mode>_gbr_load, *mov<mode>_gbr_load, *movdi_gbr_load): Use arith_reg_dest instead of register_operand for set destination. (set_thread_pointersi, load_gbr): Use arith_reg_operand instead of register_operand for set source. gcc/testsuite/ PR target/49263 PR target/53987 PR target/64345 PR target/59533 PR target/52933 PR target/54236 PR target/51244 * gcc.target/sh/pr64345-1.c: New. * gcc.target/sh/pr64345-2.c: New. * gcc.target/sh/pr59533-1.c: New. * gcc.target/sh/pr49263.c: Adjust matching of expected insns. * gcc.target/sh/pr52933-2.c: Likewise. * gcc.target/sh/pr54089-1.c: Likewise. * gcc.target/sh/pr54236-1.c: Likewise. * gcc.target/sh/pr51244-20-sh2a.c: Likewise. * gcc.target/sh/pr49263-1.c: Remove xfails. * gcc.target/sh/pr49263-2.c: Likewise. * gcc.target/sh/pr49263-3.c: Likewise. * gcc.target/sh/pr53987-1.c: Likewise. * gcc.target/sh/pr52933-1.c: Adjust matching of expected insns. (test_24, test_25, test_26, test_27, test_28, test_29, test_30): New. * gcc.target/sh/pr51244-12.c: Adjust matching of expected insns. (test05, test06, test07, test08, test09, test10, test11, test12): New. * gcc.target/sh/pr54236-3.c: Adjust matching of expected insns. (test_002, test_003, test_004, test_005, test_006, test_007, test_008, test_009): New. * gcc.target/sh/pr51244-4.c: Adjust matching of expected insns. (test_02): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@220081 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sh/sh-protos.h')
-rw-r--r--gcc/config/sh/sh-protos.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index bc2b3b30667..945a54f4f1b 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -264,6 +264,14 @@ struct sh_extending_set_of_reg : public set_of_reg
ext_code = UNKNOWN;
}
+ /* Returns true if it's possible to use the source reg of the sign
+ or zero extending set directly, bypassing the extension. */
+ bool can_use_as_unextended_reg (void) const;
+
+ /* Returns the reg rtx of the sign or zero extending set source, that can
+ be safely used at the specified insn in SImode. */
+ rtx use_as_unextended_reg (rtx_insn* use_at_insn) const;
+
/* Returns the reg rtx of the sign or zero extending result, that can be
safely used at the specified insn in SImode. If the set source is an
implicitly sign extending mem load, the mem load is converted into an
@@ -281,7 +289,66 @@ extern bool sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn,
extern void sh_split_tst_subregs (rtx_insn* curr_insn,
machine_mode subreg_mode, int subreg_offset,
rtx operands[]);
+
+extern bool sh_is_nott_insn (const rtx_insn* i);
+extern rtx sh_movt_set_dest (const rtx_insn* i);
+extern rtx sh_movrt_set_dest (const rtx_insn* i);
+
+inline bool sh_is_movt_insn (const rtx_insn* i)
+{
+ return sh_movt_set_dest (i) != NULL;
+}
+
+inline bool sh_is_movrt_insn (const rtx_insn* i)
+{
+ return sh_movrt_set_dest (i) != NULL;
+}
+
+extern bool sh_insn_operands_modified_between_p (rtx_insn* operands_insn,
+ const rtx_insn* from,
+ const rtx_insn* to);
+
+extern bool sh_reg_dead_or_unused_after_insn (const rtx_insn* i, int regno);
extern void sh_remove_reg_dead_or_unused_notes (rtx_insn* i, int regno);
+
+extern bool sh_in_recog_treg_set_expr (void);
+extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode);
+
+/* Result value of sh_split_treg_set_expr. Contains the first insn emitted
+ and the optional trailing nott insn. */
+class sh_treg_insns
+{
+public:
+ sh_treg_insns (void) : m_first_insn (NULL), m_trailing_nott_insn (NULL) { }
+ sh_treg_insns (rtx_insn* first_insn, rtx_insn* nott_insn)
+ : m_first_insn (first_insn),
+ m_trailing_nott_insn (nott_insn)
+ { }
+
+ bool was_treg_operand (void) const { return m_first_insn == NULL; }
+ bool has_trailing_nott (void) const { return m_trailing_nott_insn != NULL; }
+ rtx_insn* trailing_nott (void) const { return m_trailing_nott_insn; }
+ rtx_insn* first_insn (void) const { return m_first_insn; }
+
+ /* If there is a trailing nott, remove it from the emitted insns and
+ return true. Return false otherwise. */
+ bool
+ remove_trailing_nott (void)
+ {
+ if (!has_trailing_nott ())
+ return false;
+
+ remove_insn (trailing_nott ());
+ return true;
+ }
+
+private:
+ rtx_insn* m_first_insn;
+ rtx_insn* m_trailing_nott_insn;
+};
+
+extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn);
+
#endif /* RTX_CODE */
extern void sh_cpu_cpp_builtins (cpp_reader* pfile);