Commit d8a48c21 by Oleg Endo

re PR target/54089 ([SH] Refactor shift patterns)

	PR target/54089
	* config/sh/predicates.md (shift_count_operand): Handle not-SHMEDIA
	case.
	(p27_shift_count_operand, not_p27_shift_count_operand): New predicates.
	* config/sh/sh.md (ashlsi3): Remove parallel and T_REG clobber
	from expander.  Do not emit shift insn for not-SHMEDIA case.
	(ashlsi3_std): Replace with ...
	(ashlsi3_k, ashlsi3_d): ... these new insns.
	* config/sh/sh.c (gen_ashift): Make static.  Add sanity checks.
	Emit ashlsi3_k insn instead of ashlsi3_std in ASHIFT case.
	(gen_ashift_hi): Make static.
	* config/sh/sh-protos.h (gen_ashift, gen_ashift_hi): Remove forward
	declaration.

From-SVN: r189872
parent 1acc3340
2012-07-25 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54089
* config/sh/predicates.md (shift_count_operand): Handle not-SHMEDIA
case.
(p27_shift_count_operand, not_p27_shift_count_operand): New predicates.
* config/sh/sh.md (ashlsi3): Remove parallel and T_REG clobber
from expander. Do not emit shift insn for not-SHMEDIA case.
(ashlsi3_std): Replace with ...
(ashlsi3_k, ashlsi3_d): ... these new insns.
* config/sh/sh.c (gen_ashift): Make static. Add sanity checks.
Emit ashlsi3_k insn instead of ashlsi3_std in ASHIFT case.
(gen_ashift_hi): Make static.
* config/sh/sh-protos.h (gen_ashift, gen_ashift_hi): Remove forward
declaration.
2012-07-25 Bharathi Seshadri <bseshadr@cisco.com> 2012-07-25 Bharathi Seshadri <bseshadr@cisco.com>
Jim Wilson <jimwilso@cisco.com> Jim Wilson <jimwilso@cisco.com>
......
...@@ -755,6 +755,13 @@ ...@@ -755,6 +755,13 @@
(define_predicate "shift_count_operand" (define_predicate "shift_count_operand"
(match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend") (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend")
{ {
/* Allow T_REG as shift count for dynamic shifts, although it is not
really possible. It will then be copied to a general purpose reg. */
if (! TARGET_SHMEDIA)
return const_int_operand (op, mode)
|| (TARGET_DYNSHIFT && (arith_reg_operand (op, mode)
|| t_reg_operand (op, mode)));
return (CONSTANT_P (op) return (CONSTANT_P (op)
? (CONST_INT_P (op) ? (CONST_INT_P (op)
? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode)
...@@ -785,6 +792,14 @@ ...@@ -785,6 +792,14 @@
return arith_reg_operand (op, mode); return arith_reg_operand (op, mode);
}) })
(define_predicate "p27_shift_count_operand"
(and (match_code "const_int")
(match_test "satisfies_constraint_P27 (op)")))
(define_predicate "not_p27_shift_count_operand"
(and (match_code "const_int")
(match_test "! satisfies_constraint_P27 (op)")))
;; TODO: Add a comment here. ;; TODO: Add a comment here.
(define_predicate "shift_operator" (define_predicate "shift_operator"
......
...@@ -74,8 +74,6 @@ extern rtx sh_emit_cheap_store_flag (enum machine_mode, enum rtx_code, rtx, rtx) ...@@ -74,8 +74,6 @@ extern rtx sh_emit_cheap_store_flag (enum machine_mode, enum rtx_code, rtx, rtx)
extern void sh_emit_compare_and_branch (rtx *, enum machine_mode); extern void sh_emit_compare_and_branch (rtx *, enum machine_mode);
extern void sh_emit_compare_and_set (rtx *, enum machine_mode); extern void sh_emit_compare_and_set (rtx *, enum machine_mode);
extern int shift_insns_rtx (rtx); extern int shift_insns_rtx (rtx);
extern void gen_ashift (int, int, rtx);
extern void gen_ashift_hi (int, int, rtx);
extern void gen_shifty_op (int, rtx *); extern void gen_shifty_op (int, rtx *);
extern void gen_shifty_hi_op (int, rtx *); extern void gen_shifty_hi_op (int, rtx *);
extern bool expand_ashiftrt (rtx *); extern bool expand_ashiftrt (rtx *);
......
...@@ -3277,9 +3277,11 @@ sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) ...@@ -3277,9 +3277,11 @@ sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
/* Code to expand a shift. */ /* Code to expand a shift. */
void static void
gen_ashift (int type, int n, rtx reg) gen_ashift (int type, int n, rtx reg)
{ {
rtx n_rtx;
/* Negative values here come from the shift_amounts array. */ /* Negative values here come from the shift_amounts array. */
if (n < 0) if (n < 0)
{ {
...@@ -3290,26 +3292,30 @@ gen_ashift (int type, int n, rtx reg) ...@@ -3290,26 +3292,30 @@ gen_ashift (int type, int n, rtx reg)
n = -n; n = -n;
} }
n_rtx = GEN_INT (n);
gcc_assert (satisfies_constraint_P27 (n_rtx));
switch (type) switch (type)
{ {
case ASHIFTRT: case ASHIFTRT:
emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n))); emit_insn (gen_ashrsi3_k (reg, reg, n_rtx));
break; break;
case LSHIFTRT: case LSHIFTRT:
if (n == 1) if (n == 1)
emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n))); emit_insn (gen_lshrsi3_m (reg, reg, n_rtx));
else else
emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n))); emit_insn (gen_lshrsi3_k (reg, reg, n_rtx));
break; break;
case ASHIFT: case ASHIFT:
emit_insn (gen_ashlsi3_std (reg, reg, GEN_INT (n))); emit_insn (gen_ashlsi3_k (reg, reg, n_rtx));
break; break;
default:
gcc_unreachable ();
} }
} }
/* Same for HImode */ /* Same for HImode */
static void
void
gen_ashift_hi (int type, int n, rtx reg) gen_ashift_hi (int type, int n, rtx reg)
{ {
/* Negative values here come from the shift_amounts array. */ /* Negative values here come from the shift_amounts array. */
......
...@@ -3492,10 +3492,9 @@ label: ...@@ -3492,10 +3492,9 @@ label:
;; SImode shift left ;; SImode shift left
(define_expand "ashlsi3" (define_expand "ashlsi3"
[(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") [(set (match_operand:SI 0 "arith_reg_operand" "")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" ""))) (match_operand:SI 2 "shift_count_operand" "")))]
(clobber (reg:SI T_REG))])]
"" ""
{ {
if (TARGET_SHMEDIA) if (TARGET_SHMEDIA)
...@@ -3503,56 +3502,74 @@ label: ...@@ -3503,56 +3502,74 @@ label:
emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
DONE; DONE;
} }
if (CONST_INT_P (operands[2]) if (TARGET_DYNSHIFT
&& sh_dynamicalize_shift_p (operands[2])) && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
operands[2] = force_reg (SImode, operands[2]); operands[2] = force_reg (SImode, operands[2]);
if (TARGET_DYNSHIFT) })
(define_insn "ashlsi3_k"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0")
(match_operand:SI 2 "p27_shift_count_operand" "M,P27")))]
"TARGET_SH1"
"@
add %0,%0
shll%O2 %0"
[(set_attr "type" "arith")])
(define_insn_and_split "ashlsi3_d"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "shift_count_operand" "r")))]
"TARGET_DYNSHIFT"
"shld %2,%0"
"&& (CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2]))"
[(const_int 0)]
{
if (satisfies_constraint_P27 (operands[2]))
{ {
emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2])); emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2]));
DONE;
}
else if (!satisfies_constraint_P27 (operands[2]))
{
emit_insn (gen_ashlsi3_n (operands[0], operands[1], operands[2]));
DONE; DONE;
} }
if (! immediate_operand (operands[2], GET_MODE (operands[2])))
FAIL;
})
;; This pattern is used by init_expmed for computing the costs of shift FAIL;
;; insns.
(define_insn_and_split "ashlsi3_std"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
(match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
(clobber (match_scratch:SI 3 "=X,X,X,&r"))]
"TARGET_DYNSHIFT || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
"@
shld %2,%0
add %0,%0
shll%O2 %0
#"
"TARGET_DYNSHIFT
&& reload_completed
&& CONST_INT_P (operands[2])
&& ! satisfies_constraint_P27 (operands[2])"
[(set (match_dup 3) (match_dup 2))
(parallel
[(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3)))
(clobber (match_dup 4))])]
{
operands[4] = gen_rtx_SCRATCH (SImode);
} }
[(set_attr "length" "*,*,*,4") [(set_attr "type" "arith")])
(set_attr "type" "dyn_shift,arith,arith,arith")])
(define_insn_and_split "ashlsi3_n" (define_insn_and_split "ashlsi3_n"
[(set (match_operand:SI 0 "arith_reg_dest" "=r") [(set (match_operand:SI 0 "arith_reg_dest" "=r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n"))) (match_operand:SI 2 "not_p27_shift_count_operand" "")))]
(clobber (reg:SI T_REG))] "TARGET_SH1"
"TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
"#" "#"
"TARGET_SH1 && reload_completed" "&& (reload_completed || INTVAL (operands[2]) == 31
[(use (reg:SI R0_REG))] || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
[(const_int 0)]
{ {
gen_shifty_op (ASHIFT, operands); if (INTVAL (operands[2]) == 31)
{
/* If the shift amount is 31 we split into a different sequence before
reload so that it gets a chance to allocate R0 for the sequence.
If it fails to do so (due to pressure on R0), it will take one insn
more for the and. */
emit_insn (gen_andsi3 (operands[0], operands[1], const1_rtx));
emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
}
else if (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ())
{
/* If this pattern was picked and dynamic shifts are supported, switch
to dynamic shift pattern before reload. */
operands[2] = force_reg (SImode, operands[2]);
emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
}
else
gen_shifty_op (ASHIFT, operands);
DONE; DONE;
}) })
......
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