diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-08-09 23:27:51 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-08-09 23:27:51 +0000 |
commit | 70d4736c9af4dd94e932aee07f4e27e675350331 (patch) | |
tree | a03a6d2ae30fcbeeb358b351b3eb28289129916d | |
parent | 9ab48d6e6ca06afe12664be30bb30043a9572604 (diff) | |
download | gcc-70d4736c9af4dd94e932aee07f4e27e675350331.zip gcc-70d4736c9af4dd94e932aee07f4e27e675350331.tar.gz gcc-70d4736c9af4dd94e932aee07f4e27e675350331.tar.bz2 |
re PR target/54089 ([SH] Refactor shift patterns)
PR target/54089
* config/sh/sh-protos (shift_insns_rtx): Delete.
(sh_ashlsi_clobbers_t_reg_p): Add.
* config/sh/sh.c (shift_insns, shift_amounts, ext_shift_insns,
ext_shift_amounts): Merge arrays of ints to array of structs.
Adapt usage of arrays throughout the file.
(shift_insns_rtx): Delete unused function.
(sh_ashlsi_clobbers_t_reg_p): New function.
* config/sh/sh.md (ashlsi3): Emit ashlsi3_n_clobbers_t insn if the
final shift sequence will clobber T_REG.
(ashlsi3_n): Split only if the final shift sequence will not
clobber T_REG.
(ashlsi3_n_clobbers_t): New insn_and_split.
From-SVN: r190273
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 229 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 40 |
4 files changed, 198 insertions, 89 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e9652f8..b73c690 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2012-08-09 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54089 + * config/sh/sh-protos (shift_insns_rtx): Delete. + (sh_ashlsi_clobbers_t_reg_p): Add. + * config/sh/sh.c (shift_insns, shift_amounts, ext_shift_insns, + ext_shift_amounts): Merge arrays of ints to array of structs. + Adapt usage of arrays throughout the file. + (shift_insns_rtx): Delete unused function. + (sh_ashlsi_clobbers_t_reg_p): New function. + * config/sh/sh.md (ashlsi3): Emit ashlsi3_n_clobbers_t insn if the + final shift sequence will clobber T_REG. + (ashlsi3_n): Split only if the final shift sequence will not + clobber T_REG. + (ashlsi3_n_clobbers_t): New insn_and_split. + 2012-08-09 Steven Bosscher <steven@gcc.gnu.org> * calls.c (mem_overlaps_already_clobbered_arg_p): Use SBITMAP_SIZE diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index ff29399..db5f975 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -73,7 +73,7 @@ extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx); 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 bool sh_ashlsi_clobbers_t_reg_p (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 afd6d3d..bac849b 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -2786,72 +2786,117 @@ sh_cannot_copy_insn_p (rtx insn) return false; } -/* Actual number of instructions used to make a shift by N. */ +/* Number of instructions used to make an arithmetic right shift by N. */ static const char ashiftrt_insns[] = { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2}; -/* Left shift and logical right shift are the same. */ -static const char shift_insns[] = - { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3}; - -/* Individual shift amounts needed to get the above length sequences. - One bit right shifts clobber the T bit, so when possible, put one bit - shifts in the middle of the sequence, so the ends are eligible for - branch delay slots. */ -static const short shift_amounts[32][5] = { - {0}, {1}, {2}, {2, 1}, - {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2}, - {8}, {8, 1}, {8, 2}, {8, 1, 2}, - {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8}, - {16}, {16, 1}, {16, 2}, {16, 1, 2}, - {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, - {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, - {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; - -/* Likewise, but for shift amounts < 16, up to three highmost bits - might be clobbered. This is typically used when combined with some - kind of sign or zero extension. */ +/* Description of a logical left or right shift, when expanded to a sequence + of 1/2/8/16 shifts. + Notice that one bit right shifts clobber the T bit. One bit left shifts + are done with an 'add Rn,Rm' insn and thus do not clobber the T bit. */ +enum +{ + ASHL_CLOBBERS_T = 1 << 0, + LSHR_CLOBBERS_T = 1 << 1 +}; + +struct ashl_lshr_sequence +{ + char insn_count; + char amount[6]; + char clobbers_t; +}; + +static const struct ashl_lshr_sequence ashl_lshr_seq[32] = +{ + { 0, { 0 }, 0 }, + { 1, { 1 }, LSHR_CLOBBERS_T }, + { 1, { 2 }, 0 }, + { 2, { 2, 1 }, LSHR_CLOBBERS_T }, + { 2, { 2, 2 }, 0 }, + { 3, { 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 2, 2, 2 }, 0 }, + { 4, { 2, 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 1, { 8 }, 0 }, + { 2, { 8, 1 }, LSHR_CLOBBERS_T }, + { 2, { 8, 2 }, 0 }, + { 3, { 8, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 8, 2, 2 }, 0 }, + { 4, { 8, 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 8, -2, 8 }, 0 }, + { 3, { 8, -1, 8 }, ASHL_CLOBBERS_T }, + { 1, { 16 }, 0 }, + { 2, { 16, 1 }, LSHR_CLOBBERS_T }, + { 2, { 16, 2 }, 0 }, + { 3, { 16, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 16, 2, 2 }, 0 }, + { 4, { 16, 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 16, -2, 8 }, 0 }, + { 3, { 16, -1, 8 }, ASHL_CLOBBERS_T }, + { 2, { 16, 8 }, 0 }, + { 3, { 16, 1, 8 }, LSHR_CLOBBERS_T }, + { 3, { 16, 8, 2 }, 0 }, + { 4, { 16, 8, 1, 2 }, LSHR_CLOBBERS_T }, + { 4, { 16, 8, 2, 2 }, 0 }, + { 4, { 16, -1, -2, 16 }, ASHL_CLOBBERS_T }, + { 3, { 16, -2, 16 }, 0 }, + { 3, { 16, -1, 16 }, ASHL_CLOBBERS_T } +}; -static const char ext_shift_insns[] = - { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3}; +/* Individual shift amounts for shift amounts < 16, up to three highmost + bits might be clobbered. This is typically used when combined with some + kind of sign or zero extension. */ +static const struct ashl_lshr_sequence ext_ashl_lshr_seq[32] = +{ + { 0, { 0 }, 0 }, + { 1, { 1 }, LSHR_CLOBBERS_T }, + { 1, { 2 }, 0 }, + { 2, { 2, 1 }, LSHR_CLOBBERS_T }, + { 2, { 2, 2 }, 0 }, + { 3, { 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 2, { 8, -2 }, 0 }, + { 2, { 8, -1 }, ASHL_CLOBBERS_T }, + { 1, { 8 }, 0 }, + { 2, { 8, 1 }, LSHR_CLOBBERS_T }, + { 2, { 8, 2 }, 0 }, + { 3, { 8, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 8, 2, 2 }, 0 }, + { 3, { 16, -2, -1 }, ASHL_CLOBBERS_T }, + { 2, { 16, -2 }, 0 }, + { 2, { 16, -1 }, ASHL_CLOBBERS_T }, + { 1, { 16 }, 0 }, + { 2, { 16, 1 }, LSHR_CLOBBERS_T }, + { 2, { 16, 2 }, 0 }, + { 3, { 16, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 16, 2, 2 }, 0 }, + { 4, { 16, 2, 1, 2 }, LSHR_CLOBBERS_T }, + { 3, { 16, -2, 8 }, 0 }, + { 3, { 16, -1, 8 }, ASHL_CLOBBERS_T }, + { 2, { 16, 8 }, 0 }, + { 3, { 16, 1, 8 }, LSHR_CLOBBERS_T }, + { 3, { 16, 8, 2 }, 0 }, + { 4, { 16, 8, 1, 2 }, LSHR_CLOBBERS_T }, + { 4, { 16, 8, 2, 2 }, 0 }, + { 4, { 16, -1, -2, 16 }, ASHL_CLOBBERS_T }, + { 3, { 16, -2, 16 }, 0 }, + { 3, { 16, -1, 16 }, ASHL_CLOBBERS_T } +}; -static const short ext_shift_amounts[32][4] = { - {0}, {1}, {2}, {2, 1}, - {2, 2}, {2, 1, 2}, {8, -2}, {8, -1}, - {8}, {8, 1}, {8, 2}, {8, 1, 2}, - {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1}, - {16}, {16, 1}, {16, 2}, {16, 1, 2}, - {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8}, - {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2}, - {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}}; +/* Return true if a shift left consisting of 1/2/8/16 shift instructions + will clobber the T bit. */ +bool +sh_ashlsi_clobbers_t_reg_p (rtx shift_amount) +{ + gcc_assert (CONST_INT_P (shift_amount)); + return (ashl_lshr_seq[INTVAL (shift_amount) & 31].clobbers_t + & ASHL_CLOBBERS_T) != 0; +} /* Assuming we have a value that has been sign-extended by at least one bit, can we use the ext_shift_amounts with the last shift turned to an arithmetic shift to shift it by N without data loss, and quicker than by other means? */ #define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15) -/* This is used in length attributes in sh.md to help compute the length - of arbitrary constant shift instructions. */ - -int -shift_insns_rtx (rtx insn) -{ - rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - int shift_count = INTVAL (XEXP (set_src, 1)) & 31; - enum rtx_code shift_code = GET_CODE (set_src); - - switch (shift_code) - { - case ASHIFTRT: - return ashiftrt_insns[shift_count]; - case LSHIFTRT: - case ASHIFT: - return shift_insns[shift_count]; - default: - gcc_unreachable (); - } -} - /* Return the cost of a shift. */ static inline int @@ -2890,7 +2935,7 @@ shiftcosts (rtx x) return cost; } else - return shift_insns[value]; + return ashl_lshr_seq[value].insn_count; } /* Return the cost of an AND/XOR/IOR operation. */ @@ -3400,9 +3445,9 @@ gen_shifty_op (int code, rtx *operands) return; } - max = shift_insns[value]; + max = ashl_lshr_seq[value].insn_count; for (i = 0; i < max; i++) - gen_ashift (code, shift_amounts[value][i], operands[0]); + gen_ashift (code, ashl_lshr_seq[value].amount[i], operands[0]); } /* Same as above, but optimized for values where the topmost bits don't @@ -3427,15 +3472,15 @@ gen_shifty_hi_op (int code, rtx *operands) gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift; if (code == ASHIFT) { - max = ext_shift_insns[value]; + max = ext_ashl_lshr_seq[value].insn_count; for (i = 0; i < max; i++) - gen_fun (code, ext_shift_amounts[value][i], operands[0]); + gen_fun (code, ext_ashl_lshr_seq[value].amount[i], operands[0]); } else /* When shifting right, emit the shifts in reverse order, so that solitary negative values come first. */ - for (i = ext_shift_insns[value] - 1; i >= 0; i--) - gen_fun (code, ext_shift_amounts[value][i], operands[0]); + for (i = ext_ashl_lshr_seq[value].insn_count - 1; i >= 0; i--) + gen_fun (code, ext_ashl_lshr_seq[value].amount[i], operands[0]); } /* Output RTL for an arithmetic right shift. */ @@ -3526,9 +3571,10 @@ expand_ashiftrt (rtx *operands) bool sh_dynamicalize_shift_p (rtx count) { + int insn_count; gcc_assert (CONST_INT_P (count)); - return TARGET_DYNSHIFT - && (shift_insns[INTVAL (count) & 31] > 1 + SH_DYNAMIC_SHIFT_COST); + insn_count = ashl_lshr_seq[INTVAL (count) & 31].insn_count; + return TARGET_DYNSHIFT && (insn_count > 1 + SH_DYNAMIC_SHIFT_COST); } /* Try to find a good way to implement the combiner pattern @@ -3575,12 +3621,14 @@ shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp) lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1; /* mask has no zeroes but trailing zeroes <==> ! mask2 */ if (! mask2) - best_cost = shift_insns[right] + shift_insns[right + left]; + best_cost = ashl_lshr_seq[right].insn_count + + ashl_lshr_seq[right + left].insn_count; /* mask has no trailing zeroes <==> ! right */ else if (! right && mask2 == ~(lsb2 - 1)) { int late_right = exact_log2 (lsb2); - best_cost = shift_insns[left + late_right] + shift_insns[late_right]; + best_cost = ashl_lshr_seq[left + late_right].insn_count + + ashl_lshr_seq[late_right].insn_count; } /* Try to use zero extend. */ if (mask2 == ~(lsb2 - 1)) @@ -3592,8 +3640,8 @@ shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp) /* Can we zero-extend right away? */ if (lsb2 == (unsigned HOST_WIDE_INT) 1 << width) { - cost - = 1 + ext_shift_insns[right] + ext_shift_insns[left + right]; + cost = 1 + ext_ashl_lshr_seq[right].insn_count + + ext_ashl_lshr_seq[left + right].insn_count; if (cost < best_cost) { best = 1; @@ -3612,8 +3660,10 @@ shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp) first = width - exact_log2 (lsb2) + right; if (first >= 0 && right + left - first >= 0) { - cost = ext_shift_insns[right] + ext_shift_insns[first] + 1 - + ext_shift_insns[right + left - first]; + cost = ext_ashl_lshr_seq[right].insn_count + + ext_ashl_lshr_seq[first].insn_count + 1 + + ext_ashl_lshr_seq[right + left - first].insn_count; + if (cost < best_cost) { best = 1; @@ -3633,7 +3683,7 @@ shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp) break; if (! CONST_OK_FOR_K08 (mask >> i)) continue; - cost = (i != 0) + 2 + ext_shift_insns[left + i]; + cost = (i != 0) + 2 + ext_ashl_lshr_seq[left + i].insn_count; if (cost < best_cost) { best = 2; @@ -3649,7 +3699,9 @@ shl_and_kind (rtx left_rtx, rtx mask_rtx, int *attrp) if (i > right) break; cost = (i != 0) + (CONST_OK_FOR_I08 (mask >> i) ? 2 : 3) - + (can_ext ? ext_shift_insns : shift_insns)[left + i]; + + (can_ext + ? ext_ashl_lshr_seq + : ashl_lshr_seq)[left + i].insn_count; if (cost < best_cost) { best = 4 - can_ext; @@ -3688,11 +3740,11 @@ int shl_and_scr_length (rtx insn) { rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); - int len = shift_insns[INTVAL (XEXP (set_src, 1)) & 31]; + int len = ashl_lshr_seq[INTVAL (XEXP (set_src, 1)) & 31].insn_count; rtx op = XEXP (set_src, 0); - len += shift_insns[INTVAL (XEXP (op, 1)) & 31] + 1; + len += ashl_lshr_seq[INTVAL (XEXP (op, 1)) & 31].insn_count + 1; op = XEXP (XEXP (op, 0), 0); - return len + shift_insns[INTVAL (XEXP (op, 1)) & 31]; + return len + ashl_lshr_seq[INTVAL (XEXP (op, 1)) & 31].insn_count; } /* Generate rtl for instructions for which shl_and_kind advised a particular @@ -3793,9 +3845,9 @@ gen_shl_and (rtx dest, rtx left_rtx, rtx mask_rtx, rtx source) int neg = 0; if (kind != 4 && total_shift < 16) { - neg = -ext_shift_amounts[total_shift][1]; + neg = -ext_ashl_lshr_seq[total_shift].amount[1]; if (neg > 0) - neg -= ext_shift_amounts[total_shift][2]; + neg -= ext_ashl_lshr_seq[total_shift].amount[2]; else neg = 0; } @@ -3842,11 +3894,13 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) gcc_assert (insize > 0); /* Default to left / right shift. */ kind = 0; - best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size]; + best_cost = ashl_lshr_seq[32 - insize].insn_count + + ashl_lshr_seq[32 - size].insn_count; if (size <= 16) { /* 16 bit shift / sign extend / 16 bit shift */ - cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size]; + cost = ashl_lshr_seq[16 - insize].insn_count + 1 + + ashl_lshr_seq[16 - size].insn_count; /* If ashiftrt_insns[16 - size] is 8, this choice will be overridden below, by alternative 3 or something even better. */ if (cost < best_cost) @@ -3860,7 +3914,8 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) { if (ext <= size) { - cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext]; + cost = ext_ashl_lshr_seq[ext - insize].insn_count + 1 + + ashl_lshr_seq[size - ext].insn_count; if (cost < best_cost) { kind = ext / (unsigned) 8; @@ -3870,12 +3925,14 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) /* Check if we can do a sloppy shift with a final signed shift restoring the sign. */ if (EXT_SHIFT_SIGNED (size - ext)) - cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1; + cost = ext_ashl_lshr_seq[ext - insize].insn_count + + ext_ashl_lshr_seq[size - ext].insn_count + 1; /* If not, maybe it's still cheaper to do the second shift sloppy, and do a final sign extend? */ else if (size <= 16) - cost = ext_shift_insns[ext - insize] + 1 - + ext_shift_insns[size > ext ? size - ext : ext - size] + 1; + cost = ext_ashl_lshr_seq[ext - insize].insn_count + 1 + + ext_ashl_lshr_seq[size > ext ? size - ext : ext - size].insn_count + + 1; else continue; if (cost < best_cost) @@ -3887,7 +3944,7 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) /* Check if we can sign extend in r0 */ if (insize < 8) { - cost = 3 + shift_insns[left]; + cost = 3 + ashl_lshr_seq[left].insn_count; if (cost < best_cost) { kind = 6; @@ -3896,7 +3953,7 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) /* Try the same with a final signed shift. */ if (left < 31) { - cost = 3 + ext_shift_insns[left + 1] + 1; + cost = 3 + ext_ashl_lshr_seq[left + 1].insn_count + 1; if (cost < best_cost) { kind = 7; @@ -3907,7 +3964,7 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp) if (TARGET_DYNSHIFT) { /* Try to use a dynamic shift. */ - cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST; + cost = ashl_lshr_seq[32 - insize].insn_count + 1 + SH_DYNAMIC_SHIFT_COST; if (cost < best_cost) { kind = 0; diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index e96ff7d..ffa899d 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3496,6 +3496,17 @@ label: if (TARGET_DYNSHIFT && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) operands[2] = force_reg (SImode, operands[2]); + + /* If the ashlsi3_* insn is going to clobber the T_REG it must be + expanded here. */ + if (CONST_INT_P (operands[2]) + && sh_ashlsi_clobbers_t_reg_p (operands[2]) + && ! sh_dynamicalize_shift_p (operands[2])) + { + emit_insn (gen_ashlsi3_n_clobbers_t (operands[0], operands[1], + operands[2])); + DONE; + } }) (define_insn "ashlsi3_k" @@ -3522,7 +3533,7 @@ label: emit_insn (gen_ashlsi3_k (operands[0], operands[1], operands[2])); DONE; } - else if (!satisfies_constraint_P27 (operands[2])) + else if (! satisfies_constraint_P27 (operands[2])) { /* This must happen before reload, otherwise the constant will be moved into a register due to the "r" constraint, after which this split @@ -3541,7 +3552,32 @@ label: [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "not_p27_shift_count_operand" "")))] - "TARGET_SH1" + "TARGET_SH1 && ! sh_ashlsi_clobbers_t_reg_p (operands[2])" + "#" + "&& (reload_completed + || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" + [(const_int 0)] +{ + 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. However, we must not + create a shift sequence that clobbers the T_REG. */ + 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; +}) + +(define_insn_and_split "ashlsi3_n_clobbers_t" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") + (match_operand:SI 2 "not_p27_shift_count_operand" ""))) + (clobber (reg:SI T_REG))] + "TARGET_SH1 && sh_ashlsi_clobbers_t_reg_p (operands[2])" "#" "&& (reload_completed || INTVAL (operands[2]) == 31 || (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))" |