mirror of git://gcc.gnu.org/git/gcc.git
re PR target/54089 ([SH] Refactor shift patterns)
PR target/54089 * config/sh/predicates (p27_rshift_count_operand, not_p27_rshift_count_operand): New predicates. * config/sh/sh.c (sh_ashlsi_clobbers_t_reg_p, sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p): Handle special case when shift amount is 31. (gen_ashift): Emit gen_shlr instead of gen_lshrsi3_m. * config/sh/sh.md (ashlsi3_d): Set type to 'dyn_shift' instead of 'arith'. (ashlsi_c): Rename to shll. Adapt calls to gen_ashlsi_c throughout the file. (lshrsi3): Remove clobber from expander. Use shift_count_operand instead of nonmemory_operand predicate for second operand. Add handling of case lshrsi3_n_clobbers_t. (lshrsi3_k): Use p27_rshift_count_operand for second operand. (lshrsi3_d): Make insn_and_split. Split dynamic shift to constant shift sequences if beneficial. (lshrsi3_n): Make insn_and_split. Split constant shift sequence to dynamic shift if beneficial. (lshrsi3_n_clobbers_t): New insn_and_split. (lshrsi3_m): Delete. PR target/54089 * gcc.target/sh/pr54089-2.c: New. From-SVN: r190603
This commit is contained in:
parent
131db6b8b2
commit
6e01d52651
|
|
@ -1,3 +1,27 @@
|
||||||
|
2012-08-22 Oleg Endo <olegendo@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR target/54089
|
||||||
|
* config/sh/predicates (p27_rshift_count_operand,
|
||||||
|
not_p27_rshift_count_operand): New predicates.
|
||||||
|
* config/sh/sh.c (sh_ashlsi_clobbers_t_reg_p,
|
||||||
|
sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p): Handle special
|
||||||
|
case when shift amount is 31.
|
||||||
|
(gen_ashift): Emit gen_shlr instead of gen_lshrsi3_m.
|
||||||
|
* config/sh/sh.md (ashlsi3_d): Set type to 'dyn_shift' instead
|
||||||
|
of 'arith'.
|
||||||
|
(ashlsi_c): Rename to shll. Adapt calls to gen_ashlsi_c throughout
|
||||||
|
the file.
|
||||||
|
(lshrsi3): Remove clobber from expander. Use shift_count_operand
|
||||||
|
instead of nonmemory_operand predicate for second operand. Add
|
||||||
|
handling of case lshrsi3_n_clobbers_t.
|
||||||
|
(lshrsi3_k): Use p27_rshift_count_operand for second operand.
|
||||||
|
(lshrsi3_d): Make insn_and_split. Split dynamic shift to constant
|
||||||
|
shift sequences if beneficial.
|
||||||
|
(lshrsi3_n): Make insn_and_split. Split constant shift sequence to
|
||||||
|
dynamic shift if beneficial.
|
||||||
|
(lshrsi3_n_clobbers_t): New insn_and_split.
|
||||||
|
(lshrsi3_m): Delete.
|
||||||
|
|
||||||
2012-08-22 Steven Bosscher <steven@gcc.gnu.org>
|
2012-08-22 Steven Bosscher <steven@gcc.gnu.org>
|
||||||
|
|
||||||
* tracer.c (mark_bb_seen): Use SBITMAP_SIZE.
|
* tracer.c (mark_bb_seen): Use SBITMAP_SIZE.
|
||||||
|
|
|
||||||
|
|
@ -825,6 +825,8 @@
|
||||||
return arith_reg_operand (op, mode);
|
return arith_reg_operand (op, mode);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
;; Predicates for matching operands that are constant shift
|
||||||
|
;; amounts 1, 2, 8, 16.
|
||||||
(define_predicate "p27_shift_count_operand"
|
(define_predicate "p27_shift_count_operand"
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "satisfies_constraint_P27 (op)")))
|
(match_test "satisfies_constraint_P27 (op)")))
|
||||||
|
|
@ -833,6 +835,19 @@
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "! satisfies_constraint_P27 (op)")))
|
(match_test "! satisfies_constraint_P27 (op)")))
|
||||||
|
|
||||||
|
;; For right shifts the constant 1 is a special case because the shlr insn
|
||||||
|
;; clobbers the T_REG and is handled by the T_REG clobbering version of the
|
||||||
|
;; insn, which is also used for non-P27 shift sequences.
|
||||||
|
(define_predicate "p27_rshift_count_operand"
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "satisfies_constraint_P27 (op)")
|
||||||
|
(match_test "! satisfies_constraint_M (op)")))
|
||||||
|
|
||||||
|
(define_predicate "not_p27_rshift_count_operand"
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(ior (match_test "! satisfies_constraint_P27 (op)")
|
||||||
|
(match_test "satisfies_constraint_M (op)"))))
|
||||||
|
|
||||||
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
||||||
|
|
||||||
(define_predicate "shift_operator"
|
(define_predicate "shift_operator"
|
||||||
|
|
|
||||||
|
|
@ -2840,6 +2840,11 @@ static const struct ashl_lshr_sequence ashl_lshr_seq[32] =
|
||||||
{ 4, { 16, 8, 2, 2 }, 0 },
|
{ 4, { 16, 8, 2, 2 }, 0 },
|
||||||
{ 4, { 16, -1, -2, 16 }, ASHL_CLOBBERS_T },
|
{ 4, { 16, -1, -2, 16 }, ASHL_CLOBBERS_T },
|
||||||
{ 3, { 16, -2, 16 }, 0 },
|
{ 3, { 16, -2, 16 }, 0 },
|
||||||
|
|
||||||
|
/* For a right shift by 31 a 2 insn shll-movt sequence can be used.
|
||||||
|
For a left shift by 31 a 2 insn and-rotl sequences can be used.
|
||||||
|
However, the shift-and combiner code needs this entry here to be in
|
||||||
|
terms of real shift insns. */
|
||||||
{ 3, { 16, -1, 16 }, ASHL_CLOBBERS_T }
|
{ 3, { 16, -1, 16 }, ASHL_CLOBBERS_T }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2888,7 +2893,14 @@ bool
|
||||||
sh_ashlsi_clobbers_t_reg_p (rtx shift_amount)
|
sh_ashlsi_clobbers_t_reg_p (rtx shift_amount)
|
||||||
{
|
{
|
||||||
gcc_assert (CONST_INT_P (shift_amount));
|
gcc_assert (CONST_INT_P (shift_amount));
|
||||||
return (ashl_lshr_seq[INTVAL (shift_amount) & 31].clobbers_t
|
|
||||||
|
const int shift_amount_i = INTVAL (shift_amount) & 31;
|
||||||
|
|
||||||
|
/* Special case for shift count of 31: use and-rotl sequence. */
|
||||||
|
if (shift_amount_i == 31)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (ashl_lshr_seq[shift_amount_i].clobbers_t
|
||||||
& ASHL_CLOBBERS_T) != 0;
|
& ASHL_CLOBBERS_T) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2896,10 +2908,39 @@ bool
|
||||||
sh_lshrsi_clobbers_t_reg_p (rtx shift_amount)
|
sh_lshrsi_clobbers_t_reg_p (rtx shift_amount)
|
||||||
{
|
{
|
||||||
gcc_assert (CONST_INT_P (shift_amount));
|
gcc_assert (CONST_INT_P (shift_amount));
|
||||||
return (ashl_lshr_seq[INTVAL (shift_amount) & 31].clobbers_t
|
|
||||||
|
const int shift_amount_i = INTVAL (shift_amount) & 31;
|
||||||
|
|
||||||
|
/* Special case for shift count of 31: use shll-movt sequence. */
|
||||||
|
if (shift_amount_i == 31)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (ashl_lshr_seq[shift_amount_i].clobbers_t
|
||||||
& LSHR_CLOBBERS_T) != 0;
|
& LSHR_CLOBBERS_T) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if it is potentially beneficial to use a dynamic shift
|
||||||
|
instruction (shad / shar) instead of a combination of 1/2/8/16
|
||||||
|
shift instructions for the specified shift count.
|
||||||
|
If dynamic shifts are not available, always return false. */
|
||||||
|
bool
|
||||||
|
sh_dynamicalize_shift_p (rtx count)
|
||||||
|
{
|
||||||
|
gcc_assert (CONST_INT_P (count));
|
||||||
|
|
||||||
|
const int shift_amount_i = INTVAL (count) & 31;
|
||||||
|
int insn_count;
|
||||||
|
|
||||||
|
/* For left and right shifts, there are shorter 2 insn sequences for
|
||||||
|
shift amounts of 31. */
|
||||||
|
if (shift_amount_i == 31)
|
||||||
|
insn_count = 2;
|
||||||
|
else
|
||||||
|
insn_count = ashl_lshr_seq[shift_amount_i].insn_count;
|
||||||
|
|
||||||
|
return TARGET_DYNSHIFT && (insn_count > 1 + SH_DYNAMIC_SHIFT_COST);
|
||||||
|
}
|
||||||
|
|
||||||
/* Assuming we have a value that has been sign-extended by at least one bit,
|
/* 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
|
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? */
|
to shift it by N without data loss, and quicker than by other means? */
|
||||||
|
|
@ -3385,7 +3426,7 @@ gen_ashift (int type, int n, rtx reg)
|
||||||
break;
|
break;
|
||||||
case LSHIFTRT:
|
case LSHIFTRT:
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
emit_insn (gen_lshrsi3_m (reg, reg, n_rtx));
|
emit_insn (gen_shlr (reg, reg));
|
||||||
else
|
else
|
||||||
emit_insn (gen_lshrsi3_k (reg, reg, n_rtx));
|
emit_insn (gen_lshrsi3_k (reg, reg, n_rtx));
|
||||||
break;
|
break;
|
||||||
|
|
@ -3596,19 +3637,6 @@ expand_ashiftrt (rtx *operands)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if it is potentially beneficial to use a dynamic shift
|
|
||||||
instruction (shad / shar) instead of a combination of 1/2/8/16
|
|
||||||
shift instructions for the specified shift count.
|
|
||||||
If dynamic shifts are not available, always return false. */
|
|
||||||
bool
|
|
||||||
sh_dynamicalize_shift_p (rtx count)
|
|
||||||
{
|
|
||||||
int insn_count;
|
|
||||||
gcc_assert (CONST_INT_P (count));
|
|
||||||
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
|
/* Try to find a good way to implement the combiner pattern
|
||||||
[(set (match_operand:SI 0 "register_operand" "r")
|
[(set (match_operand:SI 0 "register_operand" "r")
|
||||||
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
|
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
|
||||||
|
|
|
||||||
|
|
@ -4058,7 +4058,7 @@ label:
|
||||||
|
|
||||||
FAIL;
|
FAIL;
|
||||||
}
|
}
|
||||||
[(set_attr "type" "arith")])
|
[(set_attr "type" "dyn_shift")])
|
||||||
|
|
||||||
(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")
|
||||||
|
|
@ -4116,7 +4116,7 @@ label:
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
(define_insn "ashlsi_c"
|
(define_insn "shll"
|
||||||
[(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") (const_int 1)))
|
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
|
||||||
(set (reg:SI T_REG)
|
(set (reg:SI T_REG)
|
||||||
|
|
@ -4142,7 +4142,7 @@ label:
|
||||||
&& peep2_reg_dead_p (2, operands[1])"
|
&& peep2_reg_dead_p (2, operands[1])"
|
||||||
[(const_int 0)]
|
[(const_int 0)]
|
||||||
{
|
{
|
||||||
emit_insn (gen_ashlsi_c (operands[1], operands[1]));
|
emit_insn (gen_shll (operands[1], operands[1]));
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -4349,7 +4349,7 @@ label:
|
||||||
"&& 1"
|
"&& 1"
|
||||||
[(const_int 0)]
|
[(const_int 0)]
|
||||||
{
|
{
|
||||||
emit_insn (gen_ashlsi_c (operands[0], operands[1]));
|
emit_insn (gen_shll (operands[0], operands[1]));
|
||||||
emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
|
emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
@ -4463,12 +4463,10 @@ label:
|
||||||
;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||||
;; SImode logical shift right
|
;; SImode logical shift right
|
||||||
|
|
||||||
;; Only the single bit shift clobbers the T bit.
|
|
||||||
(define_expand "lshrsi3"
|
(define_expand "lshrsi3"
|
||||||
[(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
|
[(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
|
(lshiftrt: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)
|
||||||
|
|
@ -4476,29 +4474,137 @@ label:
|
||||||
emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
|
emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
|
||||||
DONE;
|
DONE;
|
||||||
}
|
}
|
||||||
if (CONST_INT_P (operands[2])
|
|
||||||
&& sh_dynamicalize_shift_p (operands[2]))
|
/* If a dynamic shift is supposed to be used, expand the lshrsi3_d insn
|
||||||
operands[2] = force_reg (SImode, operands[2]);
|
here, otherwise the pattern will never match due to the shift amount reg
|
||||||
|
negation. */
|
||||||
if (TARGET_DYNSHIFT
|
if (TARGET_DYNSHIFT
|
||||||
&& arith_reg_operand (operands[2], GET_MODE (operands[2])))
|
&& CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
|
||||||
{
|
{
|
||||||
rtx count = copy_to_mode_reg (SImode, operands[2]);
|
rtx neg_count = force_reg (SImode,
|
||||||
emit_insn (gen_negsi2 (count, count));
|
gen_int_mode (- INTVAL (operands[2]), SImode));
|
||||||
emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
|
emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TARGET_DYNSHIFT && ! CONST_INT_P (operands[2]))
|
||||||
|
{
|
||||||
|
rtx neg_count = gen_reg_rtx (SImode);
|
||||||
|
emit_insn (gen_negsi2 (neg_count, operands[2]));
|
||||||
|
emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the lshrsi3_* insn is going to clobber the T_REG it must be
|
||||||
|
expanded here. */
|
||||||
|
if (CONST_INT_P (operands[2])
|
||||||
|
&& sh_lshrsi_clobbers_t_reg_p (operands[2])
|
||||||
|
&& ! sh_dynamicalize_shift_p (operands[2]))
|
||||||
|
{
|
||||||
|
emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1],
|
||||||
|
operands[2]));
|
||||||
DONE;
|
DONE;
|
||||||
}
|
}
|
||||||
if (! immediate_operand (operands[2], GET_MODE (operands[2])))
|
|
||||||
FAIL;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
(define_insn "lshrsi3_d"
|
(define_insn "lshrsi3_k"
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||||
(neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
|
(match_operand:SI 2 "p27_rshift_count_operand" "P27")))]
|
||||||
|
"TARGET_SH1"
|
||||||
|
"shlr%O2 %0"
|
||||||
|
[(set_attr "type" "arith")])
|
||||||
|
|
||||||
|
(define_insn_and_split "lshrsi3_d"
|
||||||
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||||
|
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||||
|
(neg:SI (match_operand:SI 2 "shift_count_operand" "r"))))]
|
||||||
"TARGET_DYNSHIFT"
|
"TARGET_DYNSHIFT"
|
||||||
"shld %2,%0"
|
"shld %2,%0"
|
||||||
|
"&& CONST_INT_P (operands[2]) && ! sh_dynamicalize_shift_p (operands[2])
|
||||||
|
&& ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
|
||||||
|
[(const_int 0)]
|
||||||
|
{
|
||||||
|
if (satisfies_constraint_P27 (operands[2]))
|
||||||
|
{
|
||||||
|
/* This will not be done for a shift amount of 1, because it would
|
||||||
|
clobber the T_REG. */
|
||||||
|
emit_insn (gen_lshrsi3_k (operands[0], operands[1], operands[2]));
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
cannot be done anymore.
|
||||||
|
Unfortunately the move insn will not always be eliminated.
|
||||||
|
Also, here we must not create a shift sequence that clobbers the
|
||||||
|
T_REG. */
|
||||||
|
emit_move_insn (operands[0], operands[1]);
|
||||||
|
gen_shifty_op (LSHIFTRT, operands);
|
||||||
|
DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FAIL;
|
||||||
|
}
|
||||||
[(set_attr "type" "dyn_shift")])
|
[(set_attr "type" "dyn_shift")])
|
||||||
|
|
||||||
|
(define_insn_and_split "lshrsi3_n"
|
||||||
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||||
|
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||||
|
(match_operand:SI 2 "not_p27_rshift_count_operand")))]
|
||||||
|
"TARGET_SH1 && ! sh_lshrsi_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. */
|
||||||
|
operands[2] = force_reg (SImode,
|
||||||
|
gen_int_mode (- INTVAL (operands[2]), SImode));
|
||||||
|
emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gen_shifty_op (LSHIFTRT, operands);
|
||||||
|
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
;; The lshrsi3_n_clobbers_t pattern also works as a simplified version of
|
||||||
|
;; the shlr pattern.
|
||||||
|
(define_insn_and_split "lshrsi3_n_clobbers_t"
|
||||||
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||||
|
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||||
|
(match_operand:SI 2 "not_p27_rshift_count_operand")))
|
||||||
|
(clobber (reg:SI T_REG))]
|
||||||
|
"TARGET_SH1 && sh_lshrsi_clobbers_t_reg_p (operands[2])"
|
||||||
|
"#"
|
||||||
|
"&& (reload_completed || INTVAL (operands[2]) == 31
|
||||||
|
|| (sh_dynamicalize_shift_p (operands[2]) && can_create_pseudo_p ()))"
|
||||||
|
[(const_int 0)]
|
||||||
|
{
|
||||||
|
if (INTVAL (operands[2]) == 31)
|
||||||
|
{
|
||||||
|
emit_insn (gen_shll (operands[0], operands[1]));
|
||||||
|
emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
gen_int_mode (- INTVAL (operands[2]), SImode));
|
||||||
|
emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gen_shifty_op (LSHIFTRT, operands);
|
||||||
|
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
(define_insn "shlr"
|
(define_insn "shlr"
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||||
|
|
@ -4509,38 +4615,6 @@ label:
|
||||||
"shlr %0"
|
"shlr %0"
|
||||||
[(set_attr "type" "arith")])
|
[(set_attr "type" "arith")])
|
||||||
|
|
||||||
(define_insn "lshrsi3_m"
|
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
|
||||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
|
||||||
(match_operand:SI 2 "const_int_operand" "M")))
|
|
||||||
(clobber (reg:SI T_REG))]
|
|
||||||
"TARGET_SH1 && satisfies_constraint_M (operands[2])"
|
|
||||||
"shlr %0"
|
|
||||||
[(set_attr "type" "arith")])
|
|
||||||
|
|
||||||
(define_insn "lshrsi3_k"
|
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
|
||||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
|
||||||
(match_operand:SI 2 "const_int_operand" "P27")))]
|
|
||||||
"TARGET_SH1 && satisfies_constraint_P27 (operands[2])
|
|
||||||
&& ! satisfies_constraint_M (operands[2])"
|
|
||||||
"shlr%O2 %0"
|
|
||||||
[(set_attr "type" "arith")])
|
|
||||||
|
|
||||||
(define_insn_and_split "lshrsi3_n"
|
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
|
||||||
(lshiftrt: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])"
|
|
||||||
"#"
|
|
||||||
"TARGET_SH1 && reload_completed"
|
|
||||||
[(use (reg:SI R0_REG))]
|
|
||||||
{
|
|
||||||
gen_shifty_op (LSHIFTRT, operands);
|
|
||||||
DONE;
|
|
||||||
})
|
|
||||||
|
|
||||||
(define_insn "lshrsi3_media"
|
(define_insn "lshrsi3_media"
|
||||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
|
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
|
||||||
(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
|
(lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-08-22 Oleg Endo <olegendo@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR target/54089
|
||||||
|
* gcc.target/sh/pr54089-2.c: New.
|
||||||
|
|
||||||
2012-08-22 H.J. Lu <hongjiu.lu@intel.com>
|
2012-08-22 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* gcc.target/i386/long-double-64-1.c: New file.
|
* gcc.target/i386/long-double-64-1.c: New file.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* Check that for dynamic logical right shifts with a constant the negated
|
||||||
|
constant is loaded directly, instead of loading the postitive constant
|
||||||
|
and negating it separately. This was a case that happened at optimization
|
||||||
|
level -O2 and looked like:
|
||||||
|
cmp/eq r6,r5
|
||||||
|
mov #30,r1
|
||||||
|
neg r1,r1
|
||||||
|
shld r1,r4
|
||||||
|
mov r4,r0
|
||||||
|
rts
|
||||||
|
rotcr r0 */
|
||||||
|
/* { dg-do compile { target "sh*-*-*" } } */
|
||||||
|
/* { dg-options "-O2" } */
|
||||||
|
/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m3* -m2a* -m4*" } } */
|
||||||
|
/* { dg-final { scan-assembler-not "neg" } } */
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
test (unsigned int a, int b, int c)
|
||||||
|
{
|
||||||
|
unsigned char r = b == c;
|
||||||
|
return ((a >> 31) | (r << 31));
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue