dse.c (find_shift_sequence): Allow word as well as subword shifts.
gcc/ * dse.c (find_shift_sequence): Allow word as well as subword shifts. Do the tentative shift expansion with the DF_NO_INSN_RESCAN flag set. Fix the call to insn_rtx_cost. Skip access sizes that require a real truncation of the store register. Use convert_move instead of gen_lowpart when narrowing the result. (replace_read): Use convert_move instead of gen_lowpart when narrowing the store rhs. gcc/testsuite/ * gcc.target/mips/dse-1.c: New test. From-SVN: r128530
This commit is contained in:
parent
0ee3f0a892
commit
348eea5f00
@ -1,3 +1,13 @@
|
||||
2007-09-16 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* dse.c (find_shift_sequence): Allow word as well as subword shifts.
|
||||
Do the tentative shift expansion with the DF_NO_INSN_RESCAN flag set.
|
||||
Fix the call to insn_rtx_cost. Skip access sizes that require a
|
||||
real truncation of the store register. Use convert_move instead
|
||||
of gen_lowpart when narrowing the result.
|
||||
(replace_read): Use convert_move instead of gen_lowpart when
|
||||
narrowing the store rhs.
|
||||
|
||||
2007-09-16 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* config/mips/mips.md (SHORT): Fix long line.
|
||||
|
31
gcc/dse.c
31
gcc/dse.c
@ -1407,21 +1407,31 @@ find_shift_sequence (rtx read_reg,
|
||||
justify the value we want to read but is available in one insn on
|
||||
the machine. */
|
||||
|
||||
while (access_size < UNITS_PER_WORD)
|
||||
for (; access_size <= UNITS_PER_WORD; access_size *= 2)
|
||||
{
|
||||
rtx target;
|
||||
enum machine_mode new_mode
|
||||
= smallest_mode_for_size (access_size * BITS_PER_UNIT,
|
||||
GET_MODE_CLASS (read_mode));
|
||||
rtx new_reg = gen_reg_rtx (new_mode);
|
||||
rtx target, new_reg;
|
||||
enum machine_mode new_mode;
|
||||
|
||||
/* Try a wider mode if truncating the store mode to ACCESS_SIZE
|
||||
bytes requires a real instruction. */
|
||||
if (access_size < GET_MODE_SIZE (store_mode)
|
||||
&& !TRULY_NOOP_TRUNCATION (access_size * BITS_PER_UNIT,
|
||||
GET_MODE_BITSIZE (store_mode)))
|
||||
continue;
|
||||
|
||||
new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
|
||||
GET_MODE_CLASS (read_mode));
|
||||
new_reg = gen_reg_rtx (new_mode);
|
||||
|
||||
start_sequence ();
|
||||
|
||||
/* In theory we could also check for an ashr. Ian Taylor knows
|
||||
of one dsp where the cost of these two was not the same. But
|
||||
this really is a rare case anyway. */
|
||||
df_set_flags (DF_NO_INSN_RESCAN);
|
||||
target = expand_binop (new_mode, lshr_optab, new_reg,
|
||||
GEN_INT (shift), new_reg, 1, OPTAB_DIRECT);
|
||||
df_clear_flags (DF_NO_INSN_RESCAN);
|
||||
|
||||
if (target == new_reg)
|
||||
{
|
||||
@ -1436,7 +1446,8 @@ find_shift_sequence (rtx read_reg,
|
||||
rtx insn;
|
||||
|
||||
for (insn = shift_seq; insn != NULL_RTX; insn = NEXT_INSN (insn))
|
||||
cost += insn_rtx_cost (insn);
|
||||
if (INSN_P (insn))
|
||||
cost += insn_rtx_cost (PATTERN (insn));
|
||||
|
||||
/* The computation up to here is essentially independent
|
||||
of the arguments and could be precomputed. It may
|
||||
@ -1455,7 +1466,7 @@ find_shift_sequence (rtx read_reg,
|
||||
start_sequence ();
|
||||
emit_move_insn (new_reg, gen_lowpart (new_mode, store_info->rhs));
|
||||
emit_insn (shift_seq);
|
||||
emit_move_insn (read_reg, gen_lowpart (read_mode, new_reg));
|
||||
convert_move (read_reg, new_reg, 1);
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
@ -1480,8 +1491,6 @@ find_shift_sequence (rtx read_reg,
|
||||
else
|
||||
/* End the sequence. */
|
||||
end_sequence ();
|
||||
|
||||
access_size = access_size * 2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -1595,7 +1604,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn,
|
||||
place, we need to extract the value in the right from the
|
||||
rhs of the store. */
|
||||
start_sequence ();
|
||||
emit_move_insn (read_reg, gen_lowpart (read_mode, store_info->rhs));
|
||||
convert_move (read_reg, store_info->rhs, 1);
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " -- adding extract insn r%d:%s = r%d:%s\n",
|
||||
|
@ -1,3 +1,7 @@
|
||||
2007-09-16 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* gcc.target/mips/dse-1.c: New test.
|
||||
|
||||
2007-09-16 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/32756
|
||||
|
36
gcc/testsuite/gcc.target/mips/dse-1.c
Normal file
36
gcc/testsuite/gcc.target/mips/dse-1.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* { dg-mips-options "-mgp64 -O" } */
|
||||
|
||||
#define TEST(ID, TYPE1, TYPE2) \
|
||||
union { \
|
||||
TYPE1 m1[sizeof (TYPE2) / sizeof (TYPE1)]; \
|
||||
TYPE2 m2; \
|
||||
} u##ID; \
|
||||
\
|
||||
/* The MIPS16 versions of the shifts we need are too \
|
||||
expensive. */ \
|
||||
TYPE1 __attribute__((nomips16)) \
|
||||
f##ID (TYPE2 x) \
|
||||
{ \
|
||||
u##ID.m2 = x; \
|
||||
return (u##ID.m1[0] \
|
||||
+ u##ID.m1[sizeof (TYPE2) / sizeof (TYPE1) - 1]); \
|
||||
}
|
||||
|
||||
TEST (1, unsigned int, unsigned long long);
|
||||
TEST (2, int, long long);
|
||||
TEST (3, unsigned short, unsigned long long);
|
||||
TEST (4, short, long long);
|
||||
TEST (5, unsigned char, unsigned long long);
|
||||
TEST (6, signed char, long long);
|
||||
|
||||
TEST (7, unsigned short, unsigned int);
|
||||
TEST (8, short, int);
|
||||
TEST (9, unsigned char, unsigned int);
|
||||
TEST (10, signed char, int);
|
||||
|
||||
/* DSE isn't yet read to consider stores of subregs, so the corresponding
|
||||
(char, short) tests won't pass. */
|
||||
|
||||
/* { dg-final { scan-assembler-not "\tlh\t" } } */
|
||||
/* { dg-final { scan-assembler-not "\tlw\t" } } */
|
||||
/* { dg-final { scan-assembler-not "\tlb\t" } } */
|
Loading…
Reference in New Issue
Block a user