From d8a48c211e9056e8aa8d62d4bb2a2cbe32c74815 Mon Sep 17 00:00:00 2001 From: Oleg Endo Date: Wed, 25 Jul 2012 23:03:06 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 16 +++++++ gcc/config/sh/predicates.md | 15 +++++++ gcc/config/sh/sh-protos.h | 2 - gcc/config/sh/sh.c | 20 ++++++--- gcc/config/sh/sh.md | 103 ++++++++++++++++++++++++++------------------ 5 files changed, 104 insertions(+), 52 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5c6403e..2ef72fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2012-07-25 Oleg Endo + + 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 Jim Wilson diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 3b93721..e87f6ba 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -755,6 +755,13 @@ (define_predicate "shift_count_operand" (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) ? (CONST_INT_P (op) ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode) @@ -785,6 +792,14 @@ 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. (define_predicate "shift_operator" diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 63fa599..ff29399 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -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_set (rtx *, enum machine_mode); 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_hi_op (int, rtx *); extern bool expand_ashiftrt (rtx *); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 604e500..b0ef972 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -3277,9 +3277,11 @@ sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) /* Code to expand a shift. */ -void +static void gen_ashift (int type, int n, rtx reg) { + rtx n_rtx; + /* Negative values here come from the shift_amounts array. */ if (n < 0) { @@ -3290,26 +3292,30 @@ gen_ashift (int type, int n, rtx reg) n = -n; } + n_rtx = GEN_INT (n); + gcc_assert (satisfies_constraint_P27 (n_rtx)); + switch (type) { case ASHIFTRT: - emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n))); + emit_insn (gen_ashrsi3_k (reg, reg, n_rtx)); break; case LSHIFTRT: if (n == 1) - emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n))); + emit_insn (gen_lshrsi3_m (reg, reg, n_rtx)); else - emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n))); + emit_insn (gen_lshrsi3_k (reg, reg, n_rtx)); break; case ASHIFT: - emit_insn (gen_ashlsi3_std (reg, reg, GEN_INT (n))); + emit_insn (gen_ashlsi3_k (reg, reg, n_rtx)); break; + default: + gcc_unreachable (); } } /* Same for HImode */ - -void +static void gen_ashift_hi (int type, int n, rtx reg) { /* Negative values here come from the shift_amounts array. */ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index a8c11b5..2224fa4 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3492,10 +3492,9 @@ label: ;; SImode shift left (define_expand "ashlsi3" - [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") - (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" ""))) - (clobber (reg:SI T_REG))])] + [(set (match_operand:SI 0 "arith_reg_operand" "") + (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") + (match_operand:SI 2 "shift_count_operand" "")))] "" { if (TARGET_SHMEDIA) @@ -3503,56 +3502,74 @@ label: emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); DONE; } - if (CONST_INT_P (operands[2]) - && sh_dynamicalize_shift_p (operands[2])) - operands[2] = force_reg (SImode, operands[2]); - if (TARGET_DYNSHIFT) + if (TARGET_DYNSHIFT + && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) + operands[2] = force_reg (SImode, operands[2]); +}) + +(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; } - if (! immediate_operand (operands[2], GET_MODE (operands[2]))) - FAIL; -}) -;; This pattern is used by init_expmed for computing the costs of shift -;; 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); + FAIL; } - [(set_attr "length" "*,*,*,4") - (set_attr "type" "dyn_shift,arith,arith,arith")]) + [(set_attr "type" "arith")]) (define_insn_and_split "ashlsi3_n" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))) - (clobber (reg:SI T_REG))] - "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])" + (match_operand:SI 2 "not_p27_shift_count_operand" "")))] + "TARGET_SH1" "#" - "TARGET_SH1 && reload_completed" - [(use (reg:SI R0_REG))] + "&& (reload_completed || INTVAL (operands[2]) == 31 + || (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; }) -- 2.7.4