Commit 6ff9d294 by Oleg Endo Committed by Kaz Kojima

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
parent 94a39b90
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> 2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
PR target/50354 PR target/50354
...@@ -242,7 +242,7 @@ static void sh_file_start (void); ...@@ -242,7 +242,7 @@ static void sh_file_start (void);
static int flow_dependent_p (rtx, rtx); static int flow_dependent_p (rtx, rtx);
static void flow_dependent_p_1 (rtx, const_rtx, void *); static void flow_dependent_p_1 (rtx, const_rtx, void *);
static int shiftcosts (rtx); 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 addsubcosts (rtx);
static int multcosts (rtx); static int multcosts (rtx);
static bool unspec_caller_rtx_p (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, ...@@ -2995,6 +2995,20 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
*total = 8; *total = 8;
return true; 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 CONST:
case LABEL_REF: case LABEL_REF:
case SYMBOL_REF: case SYMBOL_REF:
......
...@@ -1195,6 +1195,9 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; ...@@ -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 \ #define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 255) && ((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 #if 0
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \ #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((REGCLASS_HAS_FP_REG (CLASS) \ ((((REGCLASS_HAS_FP_REG (CLASS) \
......
...@@ -585,15 +585,164 @@ ...@@ -585,15 +585,164 @@
;; SImode signed integer comparisons ;; 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) [(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")) (match_operand:SI 1 "logical_operand" "K08,r"))
(const_int 0)))] (const_int 0)))]
"TARGET_SH1" "TARGET_SH1"
"tst %1,%0" "tst %1,%0"
[(set_attr "type" "mt_group")]) [(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. ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
;; That would still allow reload to create cmpi instructions, but would ;; That would still allow reload to create cmpi instructions, but would
;; perhaps allow forcing the constant into a register when that is better. ;; perhaps allow forcing the constant into a register when that is better.
...@@ -3015,9 +3164,9 @@ label: ...@@ -3015,9 +3164,9 @@ label:
;; ------------------------------------------------------------------------- ;; -------------------------------------------------------------------------
(define_insn "*andsi3_compact" (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") (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" "TARGET_SH1"
"and %2,%0" "and %2,%0"
[(set_attr "type" "arith")]) [(set_attr "type" "arith")])
......
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> 2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/debug1.ads: Tweak. * gnat.dg/specs/debug1.ads: Tweak.
......
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