diff options
author | Oleg Endo <oleg.endo@t-online.de> | 2011-10-15 02:32:53 +0000 |
---|---|---|
committer | Kaz Kojima <kkojima@gcc.gnu.org> | 2011-10-15 02:32:53 +0000 |
commit | 6ff9d29412643e24f930933526a837238227c68d (patch) | |
tree | ac691d12707f29a7d4e513210d069f96be3bfa3a | |
parent | 94a39b90ce90b6da1069fe3d7c0360571e73ffdc (diff) | |
download | gcc-6ff9d29412643e24f930933526a837238227c68d.zip gcc-6ff9d29412643e24f930933526a837238227c68d.tar.gz gcc-6ff9d29412643e24f930933526a837238227c68d.tar.bz2 |
re PR target/49263 (SH Target: underutilized "TST #imm, R0" instruction)
PR target/49263
* config/sh/sh.h (ZERO_EXTRACT_ANDMASK): New macro.
* config/sh/sh.c (sh_rtx_costs): Add test instruction case.
* config/sh/sh.md (tstsi_t): Name existing insn. Make inner
and instruction commutative.
(tsthi_t, tstqi_t, tstqi_t_zero, tstsi_t_and_not,
tstsi_t_zero_extract_eq, tstsi_t_zero_extract_xor,
tstsi_t_zero_extract_subreg_xor_little,
tstsi_t_zero_extract_subreg_xor_big): New insns.
(*movsicc_t_false, *movsicc_t_true): Replace space with tab in
asm output.
(*andsi_compact): Reorder alternatives so that K08 is considered
first.
* gcc.target/sh/pr49263.c: New.
From-SVN: r180020
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 16 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 3 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 161 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 |
5 files changed, 194 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b463a08..8eac26e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2011-10-15 Oleg Endo <oleg.endo@t-online.de> + + PR target/49263 + * config/sh/sh.h (ZERO_EXTRACT_ANDMASK): New macro. + * config/sh/sh.c (sh_rtx_costs): Add test instruction case. + * config/sh/sh.md (tstsi_t): Name existing insn. Make inner + and instruction commutative. + (tsthi_t, tstqi_t, tstqi_t_zero, tstsi_t_and_not, + tstsi_t_zero_extract_eq, tstsi_t_zero_extract_xor, + tstsi_t_zero_extract_subreg_xor_little, + tstsi_t_zero_extract_subreg_xor_big): New insns. + (*movsicc_t_false, *movsicc_t_true): Replace space with tab in + asm output. + (*andsi_compact): Reorder alternatives so that K08 is considered + first. + 2011-10-14 Eric Botcazou <ebotcazou@adacore.com> PR target/50354 diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index c0bfdd3..03c3c48 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -242,7 +242,7 @@ static void sh_file_start (void); static int flow_dependent_p (rtx, rtx); static void flow_dependent_p_1 (rtx, const_rtx, void *); static int shiftcosts (rtx); -static int and_xor_ior_costs (rtx, int code); +static int and_xor_ior_costs (rtx, int); static int addsubcosts (rtx); static int multcosts (rtx); static bool unspec_caller_rtx_p (rtx); @@ -2995,6 +2995,20 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, *total = 8; return true; + case EQ: + /* An and with a constant compared against zero is + most likely going to be a TST #imm, R0 instruction. + Notice that this does not catch the zero_extract variants from + the md file. */ + if (GET_CODE (XEXP (x, 0)) == AND + && CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 0) + { + *total = 1; + return true; + } + else + return false; + case CONST: case LABEL_REF: case SYMBOL_REF: diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index ef42a1b..1e65480 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1195,6 +1195,9 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; #define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \ && ((HOST_WIDE_INT)(VALUE)) <= 255) +#define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\ + (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX)) + #if 0 #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \ ((((REGCLASS_HAS_FP_REG (CLASS) \ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 63cb939..ce66018 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -585,15 +585,164 @@ ;; SImode signed integer comparisons ;; ------------------------------------------------------------------------- -(define_insn "" +;; Various patterns to generate the TST #imm, R0 instruction. +;; Although this adds some pressure on the R0 register, it can potentially +;; result in faster code, even if the operand has to be moved to R0 first. +;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group +;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0 +;; is an EX group instruction but still can be executed in parallel with the +;; MT group MOV Rm, Rn instruction. + +;; Usual TST #imm, R0 patterns for SI, HI and QI +;; This is usually used for bit patterns other than contiguous bits +;; and single bits. + +(define_insn "tstsi_t" [(set (reg:SI T_REG) - (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") + (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r") (match_operand:SI 1 "logical_operand" "K08,r")) (const_int 0)))] "TARGET_SH1" "tst %1,%0" [(set_attr "type" "mt_group")]) +(define_insn "tsthi_t" + [(set (reg:SI T_REG) + (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z") + (match_operand 1 "const_int_operand")) 0) + (const_int 0)))] + "TARGET_SH1 + && CONST_OK_FOR_K08 (INTVAL (operands[1]))" + "tst %1,%0" + [(set_attr "type" "mt_group")]) + +(define_insn "tstqi_t" + [(set (reg:SI T_REG) + (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z") + (match_operand 1 "const_int_operand")) 0) + (const_int 0)))] + "TARGET_SH1 + && (CONST_OK_FOR_K08 (INTVAL (operands[1])) + || CONST_OK_FOR_I08 (INTVAL (operands[1])))" +{ + operands[1] = GEN_INT (INTVAL (operands[1]) & 255); + return "tst %1,%0"; +} + [(set_attr "type" "mt_group")]) + +;; Test low QI subreg against zero. +;; This avoids unecessary zero extension before the test. + +(define_insn "tstqi_t_zero" + [(set (reg:SI T_REG) + (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))] + "TARGET_SH1" + "tst #255,%0" + [(set_attr "type" "mt_group")]) + +;; Extract LSB, negate and store in T bit. + +(define_insn "tstsi_t_and_not" + [(set (reg:SI T_REG) + (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z")) + (const_int 1)))] + "TARGET_SH1" + "tst #1,%0" + [(set_attr "type" "mt_group")]) + +;; Extract contiguous bits and compare them against zero. + +(define_insn "tstsi_t_zero_extract_eq" + [(set (reg:SI T_REG) + (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z") + (match_operand:SI 1 "const_int_operand") + (match_operand:SI 2 "const_int_operand")) + (const_int 0)))] + "TARGET_SH1 + && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))" +{ + operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2])); + return "tst %1,%0"; +} + [(set_attr "type" "mt_group")]) + +;; This split is required when testing bits in a QI subreg. + +(define_split + [(set (reg:SI T_REG) + (eq:SI (if_then_else:SI (zero_extract:SI + (match_operand 0 "logical_operand" "") + (match_operand 1 "const_int_operand") + (match_operand 2 "const_int_operand")) + (match_operand 3 "const_int_operand") + (const_int 0)) + (const_int 0)))] + "TARGET_SH1 + && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3]) + && CONST_OK_FOR_K08 (INTVAL (operands[3]))" + [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3)) + (const_int 0)))] + " +{ + if (GET_MODE (operands[0]) == QImode) + operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); +}") + +;; Extract single bit, negate and store it in the T bit. +;; Not used for SH4A. + +(define_insn "tstsi_t_zero_extract_xor" + [(set (reg:SI T_REG) + (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z") + (match_operand:SI 3 "const_int_operand")) + (match_operand:SI 1 "const_int_operand") + (match_operand:SI 2 "const_int_operand")))] + "TARGET_SH1 + && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3]) + && CONST_OK_FOR_K08 (INTVAL (operands[3]))" + "tst %3,%0" + [(set_attr "type" "mt_group")]) + +;; Extract single bit, negate and store it in the T bit. +;; Used for SH4A little endian. + +(define_insn "tstsi_t_zero_extract_subreg_xor_little" + [(set (reg:SI T_REG) + (zero_extract:SI + (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z") + (match_operand:SI 3 "const_int_operand")) 0) + (match_operand:SI 1 "const_int_operand") + (match_operand:SI 2 "const_int_operand")))] + "TARGET_SH1 && TARGET_LITTLE_ENDIAN + && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) + == (INTVAL (operands[3]) & 255) + && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)" +{ + operands[3] = GEN_INT (INTVAL (operands[3]) & 255); + return "tst %3,%0"; +} + [(set_attr "type" "mt_group")]) + +;; Extract single bit, negate and store it in the T bit. +;; Used for SH4A big endian. + +(define_insn "tstsi_t_zero_extract_subreg_xor_big" + [(set (reg:SI T_REG) + (zero_extract:SI + (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z") + (match_operand:SI 3 "const_int_operand")) 3) + (match_operand:SI 1 "const_int_operand") + (match_operand:SI 2 "const_int_operand")))] + "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN + && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) + == (INTVAL (operands[3]) & 255) + && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)" +{ + operands[3] = GEN_INT (INTVAL (operands[3]) & 255); + return "tst %3,%0"; +} + [(set_attr "type" "mt_group")]) + ;; ??? Perhaps should only accept reg/constant if the register is reg 0. ;; That would still allow reload to create cmpi instructions, but would ;; perhaps allow forcing the constant into a register when that is better. @@ -1157,7 +1306,7 @@ && (arith_reg_operand (operands[1], SImode) || (immediate_operand (operands[1], SImode) && satisfies_constraint_I08 (operands[1])))" - "bt 0f\;mov %1,%0\\n0:" + "bt 0f\;mov %1,%0\\n0:" [(set_attr "type" "mt_group,arith") ;; poor approximation (set_attr "length" "4")]) @@ -1170,7 +1319,7 @@ && (arith_reg_operand (operands[1], SImode) || (immediate_operand (operands[1], SImode) && satisfies_constraint_I08 (operands[1])))" - "bf 0f\;mov %1,%0\\n0:" + "bf 0f\;mov %1,%0\\n0:" [(set_attr "type" "mt_group,arith") ;; poor approximation (set_attr "length" "4")]) @@ -3015,9 +3164,9 @@ label: ;; ------------------------------------------------------------------------- (define_insn "*andsi3_compact" - [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") + [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") - (match_operand:SI 2 "logical_operand" "r,K08")))] + (match_operand:SI 2 "logical_operand" "K08,r")))] "TARGET_SH1" "and %2,%0" [(set_attr "type" "arith")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 885ca96..c89e644 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-15 Oleg Endo <oleg.endo@t-online.de> + + PR target/49263 + * gcc.target/sh/pr49263.c: New. + 2011-10-14 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/specs/debug1.ads: Tweak. |