Commit 841dbf80 by Oleg Endo

re PR target/49263 (SH Target: underutilized "TST #imm, R0" instruction)

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.

From-SVN: r220081
parent 19bd4ebc
2015-01-24 Oleg Endo <olegendo@gcc.gnu.org>
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.
2015-01-23 Jan Hubicka <hubicka@ucw.cz>
* i386.opt (prefetch_sse): New targetsave.
......
......@@ -456,17 +456,17 @@
;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn.
(define_predicate "zero_extend_movu_operand"
(and (match_operand 0 "displacement_mem_operand")
(match_test "GET_MODE (op) == QImode || GET_MODE (op) == HImode")))
(and (ior (match_operand 0 "displacement_mem_operand")
(match_operand 0 "simple_mem_operand"))
(ior (match_test "GET_MODE (op) == QImode")
(match_test "GET_MODE (op) == HImode"))))
;; Returns 1 if the operand can be used in a zero_extend.
(define_predicate "zero_extend_operand"
(ior (and (match_test "TARGET_SHMEDIA")
(match_operand 0 "general_extend_operand"))
(and (match_test "! TARGET_SHMEDIA")
(match_operand 0 "arith_reg_operand"))
(and (match_test "TARGET_SH2A")
(match_operand 0 "zero_extend_movu_operand"))))
(match_operand 0 "arith_reg_operand"))))
;; Returns 1 if OP can be source of a simple move operation. Same as
;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as
......@@ -1152,6 +1152,18 @@
(match_test "mode != HImode")
(match_test "TARGET_SH4A"))))
;; A predicate that matches any expression for which there is an
;; insn pattern that sets the T bit.
(define_predicate "treg_set_expr"
(match_test "sh_recog_treg_set_expr (op, mode)"))
;; Same as treg_set_expr but disallow constants 0 and 1 which can be loaded
;; into the T bit.
(define_predicate "treg_set_expr_not_const01"
(and (match_test "op != const0_rtx")
(match_test "op != const1_rtx")
(match_operand 0 "treg_set_expr")))
;; A predicate describing the T bit register in any form.
(define_predicate "t_reg_operand"
(match_code "reg,subreg,sign_extend,zero_extend")
......@@ -1206,6 +1218,10 @@
(ior (match_operand 0 "arith_reg_operand")
(match_operand 0 "t_reg_operand")))
(define_predicate "arith_reg_or_treg_set_expr"
(ior (match_operand 0 "arith_reg_operand")
(match_operand 0 "treg_set_expr")))
;; A predicate describing the negated value of the T bit register shifted
;; left by 31.
(define_predicate "negt_reg_shl31_operand"
......
......@@ -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);
......
2015-01-24 Oleg Endo <olegendo@gcc.gnu.org>
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.
2015-01-24 Tom de Vries <tom@codesourcery.com>
* gcc.target/i386/funcspec-5.c: Replace avx512 with avx512f.
......
......@@ -3,9 +3,9 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "and" } } */
/* { dg-final { scan-assembler-not "bclr" { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "extu" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "exts" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not "bclr" } } */
/* { dg-final { scan-assembler-times "extu" 1 } } */
/* { dg-final { scan-assembler-times "exts" 1 } } */
#define make_func(__valtype__, __valget__, __tstval__, __suff__)\
int test_imm_##__tstval__##__suff__ (__valtype__ val) \
......
......@@ -3,13 +3,12 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "and" } } */
/* { dg-final { scan-assembler-not "exts" { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not "exts" } } */
/* { dg-final { scan-assembler-times "tst\t#127,r0" 2 } } */
/* { dg-final { scan-assembler-times "tst\t#255,r0" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "65407" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "-129" 2 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "extu" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#255,r0" 1 } } */
/* { dg-final { scan-assembler-times "65407" 1 } } */
/* { dg-final { scan-assembler-times "-129" 2 } } */
/* { dg-final { scan-assembler-times "extu" 1 } } */
int
test_00 (unsigned char x)
......
......@@ -2,18 +2,18 @@
is shifted by a constant amount. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "and|shl|sha|exts" { xfail *-*-* } } } */
/* { dg-final { scan-assembler-not "and|shl|sha|exts" } } */
/* { dg-final { scan-assembler-times "tst\t#7,r0" 3 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#12,r0" 1 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#24,r0" 6 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#13,r0" 3 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#242,r0" 3 { xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#7,r0" 3 } } */
/* { dg-final { scan-assembler-times "tst\t#12,r0" 1 } } */
/* { dg-final { scan-assembler-times "tst\t#24,r0" 6 } } */
/* { dg-final { scan-assembler-times "tst\t#13,r0" 3 } } */
/* { dg-final { scan-assembler-times "tst\t#242,r0" 3 } } */
/* { dg-final { scan-assembler-times "tst\t#252,r0" 1 } } */
/* { dg-final { scan-assembler-times "tst\t#64,r0" 6 { target { ! sh2a } xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#64,r0" 4 { target { sh2a } xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "bld\t#6" 2 { target { sh2a } xfail *-*-* } } } */
/* { dg-final { scan-assembler-times "tst\t#64,r0" 6 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#64,r0" 4 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#6" 2 { target { sh2a } } } } */
int
test_00 (unsigned char* x, int y, int z)
......
......@@ -5,6 +5,8 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "and" } } */
/* { dg-final { scan-assembler-not "extu" } } */
/* { dg-final { scan-assembler-not "exts" } } */
#define make_func(__valtype__, __valget__, __tstval__, __suff__)\
int test_imm_##__tstval__##__suff__ (__valtype__ val) \
......
......@@ -4,8 +4,9 @@
/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "negc" 10 } } */
/* { dg-final { scan-assembler-not "movrt|#-1|add|sub" } } */
/* { dg-final { scan-assembler-times "negc" 15 } } */
/* { dg-final { scan-assembler-times "addc" 3 } } */
/* { dg-final { scan-assembler-not "movrt|#-1|add\t|sub\t|movt" } } */
int
test00 (int a, int b, int* x)
......@@ -66,3 +67,56 @@ test04_inv (int a)
{
return ((a & 0x55) != 0) ? 0x80000000 : 0x7FFFFFFF;
}
int
test05 (int a, int b)
{
/* 1x addc */
return a != b ? 0x7FFFFFFF : 0x80000000;
}
int
test06 (char a)
{
return ((a & 0x03) == 0) ? 0x7FFFFFFF : 0x80000000;
}
int
test07 (char a)
{
return ((a & 0x80) == 0) ? 0x7FFFFFFF : 0x80000000;
}
int
test08 (char a)
{
return ((a & 1) == 0) ? 0x7FFFFFFF : 0x80000000;
}
int
test09 (int a)
{
/* 1x cmp/pz, 1x addc */
return a < 0 ? 0x7FFFFFFF : 0x80000000;
}
int
test10 (int a)
{
/* 1x cmp/pz, 1x negc */
return a >= 0 ? 0x7FFFFFFF : 0x80000000;
}
int
test11 (int a)
{
/* 1x cmp/pl, 1x negc */
return a > 0 ? 0x7FFFFFFF : 0x80000000;
}
int
test12 (int a)
{
/* 1x cmp/pl, 1x addc */
return a <= 0 ? 0x7FFFFFFF : 0x80000000;
}
......@@ -4,8 +4,8 @@
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "tst" 6 } } */
/* { dg-final { scan-assembler-times "movt" 1 } } */
/* { dg-final { scan-assembler-times "nott" 1 } } */
/* { dg-final { scan-assembler-not "movt" } } */
/* { dg-final { scan-assembler-times "nott" 2 } } */
/* { dg-final { scan-assembler-times "cmp/eq" 2 } } */
/* { dg-final { scan-assembler-times "cmp/hi" 4 } } */
/* { dg-final { scan-assembler-times "cmp/gt" 3 } } */
......
/* Check that storing the (negated) T bit as all ones or zeros in a reg
uses the subc instruction. On SH2A a sequence with the movrt instruction
is also OK instead of subc. */
uses the subc instruction. */
/* { dg-do compile } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "movt|tst|negc" } } */
/* { dg-final { scan-assembler "subc|movrt|neg|not" } } */
/* { dg-final { scan-assembler-not "movt|tst|negc|movrt" } } */
/* { dg-final { scan-assembler-times "subc" 3 } } */
/* { dg-final { scan-assembler-times "not\t" 1 } } */
/* { dg-final { scan-assembler-times "shll" 1 } } */
/* { dg-final { scan-assembler-not "cmp/gt" } } */
int test_00 (int x, int y)
int
test_00 (int x, int y)
{
/* 1x subc, 1x not */
return x != y ? -1 : 0;
}
int test_01 (int x, int y)
int
test_01 (int x, int y)
{
/* 1x subc */
return x == y ? -1 : 0;
}
int
test_02 (int x)
{
/* 1x shll, 1x subc */
return 0 <= x ? 0 : -1;
}
......@@ -5,8 +5,13 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "div0s" 25 } } */
/* { dg-final { scan-assembler-times "div0s" 32 } } */
/* { dg-final { scan-assembler-not "tst" } } */
/* { dg-final { scan-assembler-not "not\t" } } */
/* { dg-final { scan-assembler-not "nott" } } */
/* { dg-final { scan-assembler-times "negc" 9 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "movrt" 9 { target { sh2a } } } } */
typedef unsigned char bool;
......@@ -166,3 +171,45 @@ test_23 (int a, int b, int c, int d)
/* Should emit 2x div0s. */
return ((a < 0) == (b < 0)) | ((c < 0) == (d < 0));
}
bool
test_24 (int a, int b)
{
return a >= 0 != b >= 0;
}
bool
test_25 (int a, int b)
{
return !(a < 0 != b < 0);
}
int
test_26 (int a, int b, int c, int d)
{
return a >= 0 != b >= 0 ? c : d;
}
int
test_27 (int a, int b)
{
return a >= 0 == b >= 0;
}
int
test_28 (int a, int b, int c, int d)
{
return a >= 0 == b >= 0 ? c : d;
}
int
test_29 (int a, int b)
{
return ((a >> 31) ^ (b >= 0)) & 1;
}
int
test_30 (int a, int b)
{
return ((a >> 31) ^ (b >> 31)) & 1;
}
......@@ -6,7 +6,12 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mpretend-cmove" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "div0s" 25 } } */
/* { dg-final { scan-assembler-times "div0s" 32 } } */
/* { dg-final { scan-assembler-not "tst" } } */
/* { dg-final { scan-assembler-not "not\t" } } */
/* { dg-final { scan-assembler-not "nott" } } */
/* { dg-final { scan-assembler-times "negc" 9 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "movrt" 9 { target { sh2a } } } } */
#include "pr52933-1.c"
......@@ -6,7 +6,7 @@
/* { dg-final { scan-assembler-not "exts.b" } } */
/* { dg-final { scan-assembler-not "exts.w" } } */
/* { dg-final { scan-assembler-not "movu" } } */
/* { dg-final { scan-assembler-not "tst\t#255" { xfail *-*-*} } } */
/* { dg-final { scan-assembler-not "tst\t#255" } } */
int
test_00 (unsigned char* x, char* xx, int y, int z)
......
......@@ -4,6 +4,8 @@
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "rotcr" 24 } } */
/* { dg-final { scan-assembler-times "shll\t" 1 } } */
/* { dg-final { scan-assembler-not "and\t#1" } } */
/* { dg-final { scan-assembler-not "cmp/pl" } } */
typedef char bool;
......
......@@ -7,8 +7,12 @@
/* { dg-final { scan-assembler-times "addc" 4 } } */
/* { dg-final { scan-assembler-times "subc" 3 } } */
/* { dg-final { scan-assembler-times "sett" 5 } } */
/* { dg-final { scan-assembler-times "negc" 1 } } */
/* { dg-final { scan-assembler-not "movt" } } */
/* { dg-final { scan-assembler-times "negc" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-not "movt" { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "bld" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "movt" 1 { target { sh2a } } } } */
int
test_00 (int a, int b, int c, int d)
......@@ -64,7 +68,8 @@ test_07 (int *vec)
{
/* Must not see a 'sett' or 'addc' here.
This is a case where combine tries to produce
'a + (0 - b) + 1' out of 'a - b + 1'. */
'a + (0 - b) + 1' out of 'a - b + 1'.
On non-SH2A there is a 'tst + negc', on SH2A a 'bld + movt'. */
int z = vec[0];
int vi = vec[1];
int zi = vec[2];
......
......@@ -2,11 +2,13 @@
If everything works as expected we won't see any movt instructions in
these cases. */
/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "addc" 1 } } */
/* { dg-final { scan-assembler-times "subc" 1 } } */
/* { dg-final { scan-assembler-not "movt" } } */
/* { dg-final { scan-assembler-times "addc" 4 } } */
/* { dg-final { scan-assembler-times "subc" 5 } } */
/* { dg-final { scan-assembler-times "movt" 1 } } */
/* { dg-final { scan-assembler-times "sub\t" 1 } } */
/* { dg-final { scan-assembler-times "neg\t" 2 } } */
int
test_000 (int* x, unsigned int c)
......@@ -29,3 +31,66 @@ test_001 (int* x, unsigned int c)
s -= ! (x[i] & 0x3000);
return s;
}
int
test_002 (int a, int b, int c)
{
/* 1x tst, 1x subc */
return ((a & b) != 0) - c;
}
int
test_003 (int a, int b, int c)
{
/* 1x tst, 1x movt, 1x sub */
return ((a & b) == 0) - c;
}
int
test_004 (int a, int b, int c)
{
/* 1x tst, 1x addc */
return c - ((a & b) != 0);
}
int
test_005 (int a, int b, int c)
{
/* 1x shll, 1x subc */
int x = a < 0;
return c - (b + x);
}
int
test_006 (int a, int b, int c)
{
/* 1x neg, 1x cmp/pl, 1x addc */
int x = a > 0;
int y = b + x;
return y - c;
}
int
test_007 (int a, int b, int c)
{
/* 1x add #-1, 1x cmp/eq, 1x addc */
int x = a != 1;
int y = b - x;
return c + y;
}
int
test_008 (int a, int b, int c)
{
/* 1x neg, 1x cmp/gt, 1x subc */
int x = a > 1;
int y = b - x;
return c + y;
}
int
test_009 (int a, int b, int c, int d)
{
/* 1x div0s, 1x subc */
return c - d - (a < 0 != b < 0);
}
/* Check that the cmp/pz instruction is generated as expected. */
/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "shll" 1 } } */
/* { dg-final { scan-assembler-times "movt" 5 } } */
/* { dg-final { scan-assembler-times "rotcl" 1 } } */
/* { dg-final { scan-assembler-times "and" 3 } } */
/* { dg-final { scan-assembler-times "extu.b" 5 } } */
/* { dg-final { scan-assembler-times "cmp/pz" 22 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "addc" 3 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "subc" 12 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "cmp/pz" 20 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "addc" 5 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "subc" 10 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld" 2 { target { sh2a } } } } */
int
test_00 (unsigned char* a)
{
/* 1x cmp/pz, 1x movt */
return a[0] < 128;
}
int
test_01 (unsigned char* a)
{
/* 1x cmp/pz, 1x addc */
return a[0] + (a[0] < 128);
}
int
test_02 (unsigned char* a)
{
/* 1x cmp/pz, 1x addc */
return a[0] + ((a[0] & 0x80) == 0);
}
int
test_03 (unsigned char* a)
{
/* 1x cmp/pz, 1x subc
SH2A: 1x bld, 1x addc */
return a[0] + (a[0] > 127);
}
int
test_04 (unsigned char* a)
{
/* 1x cmp/pz, 1x subc
SH2A: 1x bld, 1x addc */
return a[0] + ((a[0] & 0x80) != 0);
}
int
test_05 (unsigned char* a, int b, int c)
{
/* 1x cmp/pz */
if (a[0] < 128)
return c;
else
return b + 50;
}
unsigned int
test_06 (unsigned int a)
{
/* 1x cmp/pz, 1x movt */
return ~a >> 31;
}
int
test_07 (unsigned short* a)
{
/* 1x cmp/pz */
return a[0] < 32768;
}
int
test_08 (unsigned short* a)
{
/* 1x cmp/pz, 1x addc */
return a[0] + (a[0] < 32768);
}
unsigned int
test_09 (unsigned int a)
{
/* 1x cmp/pz, 1x movt */
return (a >> 31) ^ 1;
}
unsigned int
test_10 (unsigned int a, unsigned int b)
{
/* 1x cmp/pz, 1x rotcl */
return (a << 1) | ((a >> 31) ^ 1);
}
unsigned int
test_11 (int x)
{
/* 1x cmp/pz, 1x subc */
return ~(x >> 31);
}
unsigned int
test_12 (int x)
{
/* 1x cmp/pz, 1x subc */
return 0xFFFFFFFF - (x >> 31);
}
unsigned int
test_13 (int x)
{
/* 1x cmp/pz, 1x subc, 1x add */
return ~(x >> 31) << 1;
}
unsigned int
test_14 (int x)
{
/* 1x cmp/pz, 1x subc */
return ~(x >> 31) >> 1;
}
unsigned int
test_15 (int x)
{
/* 1x cmp/pz, 1x subc */
return ~(x >> 31) >> 31;
}
unsigned int
test_16 (int x)
{
/* 1x cmp/pz, 1x subc, 1x and */
return ~(x >> 31) & 0xFF000000;
}
unsigned int
test_17 (int x)
{
/* 1x cmp/pz, 1x subc, 1x and */
return ~(x >> 31) & 0x00FF0000;
}
unsigned int
test_18 (int x)
{
/* 1x cmp/pz, 1x subc, 1x and */
return ~(x >> 31) & 0x0000FF00;
}
unsigned int
test_19 (int x)
{
/* 1x cmp/pz, 1x subc, 1x extu.b */
return ~(x >> 31) & 0x000000FF;
}
unsigned int
test_20 (int x, unsigned int y, unsigned int z)
{
/* 1x shll */
return ~(x >> 31) ? y : z;
}
int
test_21 (int x)
{
/* 1x cmp/pz, 1x subc */
return x >= 0 ? 0xFFFFFFFF : 0;
}
int
test_22 (int x)
{
/* 1x cmp/pz, 1x movt */
return (x >> 31) + 1;
}
/* Verify that single bit zero extractions emit the expected
insns sequences. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "exts|extu|sha|shld|subc|xor" } } */
/* { dg-final { scan-assembler-times "tst" 716 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "cmp/pz" 6 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "shll\t" 6 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "shlr\t" 8 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst" 442 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld" 276 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "cmp/pz" 6 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "shll\t" 4 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "shlr\t" 8 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "and\t#1" 32 } } */
#define make_func(type,shift)\
int test_##type##_##_shift_##shift##_0 (type x)\
{\
return ((x >> shift) ^ 1) & 1 ? -40 : -10;\
}\
int test_##type##_##_shift_##shift##_1 (type x)\
{\
return ((x >> shift) ^ 0) & 1 ? -40 : -10;\
}\
int test_##type##_##_shift_##shift##_2 (type x)\
{\
return ((x >> shift) ^ 1) & 1;\
}\
int test_##type##_##_shift_##shift##_3 (type x)\
{\
return ((x >> shift) ^ 0) & 1;\
}\
int test_##type##_##_shift_##shift##_4 (type x)\
{\
return (x & (1 << shift)) == 0;\
}\
int test_##type##_##_shift_##shift##_5 (type x)\
{\
return (x & (1 << shift)) != 0;\
}\
\
int test_##type##_##_shift_##shift##_6 (type* x)\
{\
return ((*x >> shift) ^ 1) & 1 ? -40 : -10;\
}\
int test_##type##_##_shift_##shift##_7 (type* x)\
{\
return ((*x >> shift) ^ 0) & 1 ? -40 : -10;\
}\
int test_##type##_##_shift_##shift##_8 (type* x)\
{\
return ((*x >> shift) ^ 1) & 1;\
}\
int test_##type##_##_shift_##shift##_9 (type* x)\
{\
return ((*x >> shift) ^ 0) & 1;\
}\
int test_##type##_##_shift_##shift##_10 (type* x)\
{\
return (*x & (1 << shift)) == 0;\
}\
int test_##type##_##_shift_##shift##_11 (type* x)\
{\
return (*x & (1 << shift)) != 0;\
}
#define make_funcs(type)\
make_func (type, 0)\
make_func (type, 1)\
make_func (type, 2)\
make_func (type, 3)\
make_func (type, 4)\
make_func (type, 5)\
make_func (type, 6)\
make_func (type, 7)
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
make_funcs (int8_t)
make_funcs (uint8_t)
make_funcs (int16_t)
make_funcs (uint16_t)
make_funcs (int32_t)
make_funcs (uint32_t)
make_funcs (int64_t)
make_funcs (uint64_t)
/* Verify that the TST insn is used to extract a zero extended
single bit into the T bit (for a following conditional branch) and into
a GP register. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "exts|extu|sha|shld|subc|xor" } } */
/* { dg-final { scan-assembler-times "tst" 61 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#1," 1 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#2" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#4" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#8" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#16" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#32" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#64" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#128" 2 { target { ! sh2a } } } } */
/* { dg-final { scan-assembler-times "tst" 54 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#1," 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#2" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#4" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#8" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#16" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#32" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#64" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "tst\t#128" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#1," 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#2" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#3" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#4" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#5" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#6" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld\t#7" 1 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "and\t#1" 1 } } */
/* { dg-final { scan-assembler-times "cmp/pz" 1 } } */
/* { dg-final { scan-assembler-times "shll" 1 } } */
typedef struct
{
unsigned int b31 : 1;
unsigned int b30 : 1;
unsigned int b29 : 1;
unsigned int b28 : 1;
unsigned int b27 : 1;
unsigned int b26 : 1;
unsigned int b25 : 1;
unsigned int b24 : 1;
unsigned int b23 : 1;
unsigned int b22 : 1;
unsigned int b21 : 1;
unsigned int b20 : 1;
unsigned int b19 : 1;
unsigned int b18 : 1;
unsigned int b17 : 1;
unsigned int b16 : 1;
unsigned int b15 : 1;
unsigned int b14 : 1;
unsigned int b13 : 1;
unsigned int b12 : 1;
unsigned int b11 : 1;
unsigned int b10 : 1;
unsigned int b9 : 1;
unsigned int b8 : 1;
unsigned int b7 : 1;
unsigned int b6 : 1;
unsigned int b5 : 1;
unsigned int b4 : 1;
unsigned int b3 : 1;
unsigned int b2 : 1;
unsigned int b1 : 1;
unsigned int b0 : 1;
} S;
#define make_funcs(bitpos)\
unsigned int test_b##bitpos##_0 (S s)\
{\
return s.b##bitpos;\
}\
unsigned int test_b##bitpos##_1 (S s)\
{\
return !s.b##bitpos;\
}\
make_funcs (0)
make_funcs (1)
make_funcs (2)
make_funcs (3)
make_funcs (4)
make_funcs (5)
make_funcs (6)
make_funcs (7)
make_funcs (8)
make_funcs (9)
make_funcs (10)
make_funcs (11)
make_funcs (12)
make_funcs (13)
make_funcs (14)
make_funcs (15)
make_funcs (16)
make_funcs (17)
make_funcs (18)
make_funcs (19)
make_funcs (20)
make_funcs (21)
make_funcs (22)
make_funcs (23)
make_funcs (24)
make_funcs (25)
make_funcs (26)
make_funcs (27)
make_funcs (28)
make_funcs (29)
make_funcs (30)
make_funcs (31)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment