re PR rtl-optimization/50489 ([UPC/IA64] mis-schedule of MEM ref with -ftree-vectorize and -fschedule-insns2)
PR target/50489 * config/sh/sh.md (rotcr, *rotcr, shar, shlr): New insns and splits. (ashrdi3_k, lshrdi3_k): Rewrite as insn_and_split. * config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p): New function. * config/sh/sh-protos.h (sh_lshrsi_clobbers_t_reg_p): Declare it. PR target/50489 * gcc.target/sh/pr54089-1.c: New. From-SVN: r190545
This commit is contained in:
parent
6774855070
commit
5592815a88
@ -1,3 +1,11 @@
|
||||
2012-08-20 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/50489
|
||||
* config/sh/sh.md (rotcr, *rotcr, shar, shlr): New insns and splits.
|
||||
(ashrdi3_k, lshrdi3_k): Rewrite as insn_and_split.
|
||||
* config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p): New function.
|
||||
* config/sh/sh-protos.h (sh_lshrsi_clobbers_t_reg_p): Declare it.
|
||||
|
||||
2012-08-20 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
|
@ -74,6 +74,7 @@ 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 bool sh_ashlsi_clobbers_t_reg_p (rtx);
|
||||
extern bool sh_lshrsi_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 *);
|
||||
|
@ -2892,6 +2892,14 @@ sh_ashlsi_clobbers_t_reg_p (rtx shift_amount)
|
||||
& ASHL_CLOBBERS_T) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
sh_lshrsi_clobbers_t_reg_p (rtx shift_amount)
|
||||
{
|
||||
gcc_assert (CONST_INT_P (shift_amount));
|
||||
return (ashl_lshr_seq[INTVAL (shift_amount) & 31].clobbers_t
|
||||
& LSHR_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? */
|
||||
|
@ -3827,6 +3827,100 @@ label:
|
||||
FAIL;
|
||||
})
|
||||
|
||||
;; The rotcr insn is used primarily in DImode right shifts (arithmetic
|
||||
;; and logical). It can also be used to implement things like
|
||||
;; bool t = a == b;
|
||||
;; int x = (y >> 1) | (t << 31);
|
||||
(define_insn "rotcr"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||
(const_int 1))
|
||||
(ashift:SI (match_operand:SI 2 "t_reg_operand")
|
||||
(const_int 31))))
|
||||
(set (reg:SI T_REG)
|
||||
(and:SI (match_dup 1) (const_int 1)))]
|
||||
"TARGET_SH1"
|
||||
"rotcr %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
;; Simplified rotcr version for combine, which allows arbitrary shift
|
||||
;; amounts for the reg. If the shift amount is '1' rotcr can be used
|
||||
;; directly. Otherwise we have to insert a shift in between.
|
||||
(define_insn_and_split "*rotcr"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(match_operand:SI 2 "const_int_operand"))
|
||||
(ashift:SI (match_operand:SI 3 "t_reg_operand")
|
||||
(const_int 31))))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(const_int 0)]
|
||||
{
|
||||
if (INTVAL (operands[2]) > 1)
|
||||
{
|
||||
/* use plus_constant function ?? */
|
||||
const int shift_count = INTVAL (operands[2]) - 1;
|
||||
const rtx shift_count_rtx = GEN_INT (shift_count);
|
||||
rtx shift_res = gen_reg_rtx (SImode);
|
||||
|
||||
rtx prev_set_t_insn = NULL_RTX;
|
||||
rtx tmp_t_reg = NULL_RTX;
|
||||
|
||||
/* If we're going to emit a shift sequence that clobbers the T_REG,
|
||||
try to find the previous insn that sets the T_REG and emit the
|
||||
shift insn before that insn, to remove the T_REG dependency.
|
||||
If the insn that sets the T_REG cannot be found, store the T_REG
|
||||
in a temporary reg and restore it after the shift. */
|
||||
if (sh_lshrsi_clobbers_t_reg_p (shift_count_rtx)
|
||||
&& ! sh_dynamicalize_shift_p (shift_count_rtx))
|
||||
{
|
||||
prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
|
||||
if (! (prev_set_t_insn != NULL_RTX
|
||||
&& reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
|
||||
&& ! reg_referenced_p (get_t_reg_rtx (),
|
||||
PATTERN (prev_set_t_insn))))
|
||||
{
|
||||
prev_set_t_insn = NULL_RTX;
|
||||
tmp_t_reg = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
|
||||
}
|
||||
}
|
||||
|
||||
rtx shift_rtx = gen_lshrsi3 (shift_res, operands[1], shift_count_rtx);
|
||||
operands[1] = shift_res;
|
||||
|
||||
/* Emit the shift insn before the insn that sets T_REG, if possible. */
|
||||
if (prev_set_t_insn != NULL_RTX)
|
||||
emit_insn_before (shift_rtx, prev_set_t_insn);
|
||||
else
|
||||
emit_insn (shift_rtx);
|
||||
|
||||
/* Restore T_REG if it has been saved before. */
|
||||
if (tmp_t_reg != NULL_RTX)
|
||||
emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
|
||||
}
|
||||
|
||||
emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; rotcr combine bridge pattern which will make combine try out more
|
||||
;; complex patterns.
|
||||
(define_insn_and_split "*rotcr"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& 1"
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(parallel [(set (match_dup 0)
|
||||
(ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
|
||||
(ashift:SI (match_dup 1) (const_int 31))))
|
||||
(set (reg:SI T_REG)
|
||||
(and:SI (match_dup 0) (const_int 1)))])])
|
||||
|
||||
;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
;; SImode shift left
|
||||
|
||||
@ -4146,6 +4240,16 @@ label:
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_insn "shar"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||
(const_int 1)))
|
||||
(set (reg:SI T_REG)
|
||||
(and:SI (match_dup 1) (const_int 1)))]
|
||||
"TARGET_SH1"
|
||||
"shar %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_insn "ashrsi3_k"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||
@ -4233,16 +4337,22 @@ label:
|
||||
FAIL;
|
||||
})
|
||||
|
||||
;; This should be a define_insn_and_split
|
||||
(define_insn "ashrdi3_k"
|
||||
(define_insn_and_split "ashrdi3_k"
|
||||
[(set (match_operand:DI 0 "arith_reg_dest" "=r")
|
||||
(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
|
||||
(const_int 1)))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"shar %S0\;rotcr %R0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "arith")])
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
rtx high = gen_highpart (SImode, operands[0]);
|
||||
rtx low = gen_lowpart (SImode, operands[0]);
|
||||
emit_insn (gen_shar (high, high));
|
||||
emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "ashrdi3_media"
|
||||
[(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
|
||||
@ -4322,6 +4432,16 @@ label:
|
||||
"shld %2,%0"
|
||||
[(set_attr "type" "dyn_shift")])
|
||||
|
||||
(define_insn "shlr"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
|
||||
(const_int 1)))
|
||||
(set (reg:SI T_REG)
|
||||
(and:SI (match_dup 1) (const_int 1)))]
|
||||
"TARGET_SH1"
|
||||
"shlr %0"
|
||||
[(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")
|
||||
@ -4384,16 +4504,22 @@ label:
|
||||
FAIL;
|
||||
})
|
||||
|
||||
;; This should be a define_insn_and_split
|
||||
(define_insn "lshrdi3_k"
|
||||
(define_insn_and_split "lshrdi3_k"
|
||||
[(set (match_operand:DI 0 "arith_reg_dest" "=r")
|
||||
(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
|
||||
(const_int 1)))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"shlr %S0\;rotcr %R0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "arith")])
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(const_int 0)]
|
||||
{
|
||||
rtx high = gen_highpart (SImode, operands[0]);
|
||||
rtx low = gen_lowpart (SImode, operands[0]);
|
||||
emit_insn (gen_shlr (high, high));
|
||||
emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "lshrdi3_media"
|
||||
[(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
|
||||
|
@ -1,3 +1,8 @@
|
||||
2012-08-20 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/50489
|
||||
* gcc.target/sh/pr54089-1.c: New.
|
||||
|
||||
2012-08-20 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
|
83
gcc/testsuite/gcc.target/sh/pr54089-1.c
Normal file
83
gcc/testsuite/gcc.target/sh/pr54089-1.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* Check that the rotcr instruction is generated. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
|
||||
/* { dg-final { scan-assembler-times "rotcr" 11 } } */
|
||||
|
||||
typedef char bool;
|
||||
|
||||
long long
|
||||
test_00 (long long a)
|
||||
{
|
||||
return a >> 1;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_01 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 1) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_02 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 2) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_03 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 3) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_04 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 4) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_05 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 5) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_06 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 6) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_07 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 7) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_08 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 8) | (r << 31));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
test_09 (unsigned int a, int b, int c)
|
||||
{
|
||||
bool r = b == c;
|
||||
return ((a >> 31) | (r << 31));
|
||||
}
|
||||
|
||||
int
|
||||
test_10 (int a, int b)
|
||||
{
|
||||
bool r = a == b;
|
||||
return r << 31;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user