Commit 348eea5f by Richard Sandiford Committed by Richard Sandiford

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
parent 0ee3f0a8
2007-09-16 Richard Sandiford <rsandifo@nildram.co.uk> 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. * config/mips/mips.md (SHORT): Fix long line.
(SUBDI): New mode iterator. Extend the shift-and-truncate insns (SUBDI): New mode iterator. Extend the shift-and-truncate insns
to QImode and HImode. to QImode and HImode.
...@@ -1407,21 +1407,31 @@ find_shift_sequence (rtx read_reg, ...@@ -1407,21 +1407,31 @@ find_shift_sequence (rtx read_reg,
justify the value we want to read but is available in one insn on justify the value we want to read but is available in one insn on
the machine. */ the machine. */
while (access_size < UNITS_PER_WORD) for (; access_size <= UNITS_PER_WORD; access_size *= 2)
{ {
rtx target; rtx target, new_reg;
enum machine_mode new_mode enum machine_mode new_mode;
= smallest_mode_for_size (access_size * BITS_PER_UNIT,
GET_MODE_CLASS (read_mode)); /* Try a wider mode if truncating the store mode to ACCESS_SIZE
rtx new_reg = gen_reg_rtx (new_mode); 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 (); start_sequence ();
/* In theory we could also check for an ashr. Ian Taylor knows /* 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 of one dsp where the cost of these two was not the same. But
this really is a rare case anyway. */ this really is a rare case anyway. */
df_set_flags (DF_NO_INSN_RESCAN);
target = expand_binop (new_mode, lshr_optab, new_reg, target = expand_binop (new_mode, lshr_optab, new_reg,
GEN_INT (shift), new_reg, 1, OPTAB_DIRECT); GEN_INT (shift), new_reg, 1, OPTAB_DIRECT);
df_clear_flags (DF_NO_INSN_RESCAN);
if (target == new_reg) if (target == new_reg)
{ {
...@@ -1436,7 +1446,8 @@ find_shift_sequence (rtx read_reg, ...@@ -1436,7 +1446,8 @@ find_shift_sequence (rtx read_reg,
rtx insn; rtx insn;
for (insn = shift_seq; insn != NULL_RTX; insn = NEXT_INSN (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 /* The computation up to here is essentially independent
of the arguments and could be precomputed. It may of the arguments and could be precomputed. It may
...@@ -1455,7 +1466,7 @@ find_shift_sequence (rtx read_reg, ...@@ -1455,7 +1466,7 @@ find_shift_sequence (rtx read_reg,
start_sequence (); start_sequence ();
emit_move_insn (new_reg, gen_lowpart (new_mode, store_info->rhs)); emit_move_insn (new_reg, gen_lowpart (new_mode, store_info->rhs));
emit_insn (shift_seq); 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) if (dump_file)
{ {
...@@ -1480,8 +1491,6 @@ find_shift_sequence (rtx read_reg, ...@@ -1480,8 +1491,6 @@ find_shift_sequence (rtx read_reg,
else else
/* End the sequence. */ /* End the sequence. */
end_sequence (); end_sequence ();
access_size = access_size * 2;
} }
return NULL; return NULL;
...@@ -1595,7 +1604,7 @@ replace_read (store_info_t store_info, insn_info_t store_insn, ...@@ -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 place, we need to extract the value in the right from the
rhs of the store. */ rhs of the store. */
start_sequence (); 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) if (dump_file)
fprintf (dump_file, " -- adding extract insn r%d:%s = r%d:%s\n", fprintf (dump_file, " -- adding extract insn r%d:%s = r%d:%s\n",
......
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> 2007-09-16 Nathan Sidwell <nathan@codesourcery.com>
PR c++/32756 PR c++/32756
/* { 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" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment