aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2007-09-16 21:02:54 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2007-09-16 21:02:54 +0000
commit348eea5f00fe47fa13c235e9e93c082b8b285f97 (patch)
tree24f70bdc3e262c76611c228272c31e27b2f21f85 /gcc
parent0ee3f0a892918371a5245de973480bc443126558 (diff)
downloadgcc-348eea5f00fe47fa13c235e9e93c082b8b285f97.zip
gcc-348eea5f00fe47fa13c235e9e93c082b8b285f97.tar.gz
gcc-348eea5f00fe47fa13c235e9e93c082b8b285f97.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/dse.c31
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/mips/dse-1.c36
4 files changed, 70 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index db1ef1c..60bd52d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
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.
(SUBDI): New mode iterator. Extend the shift-and-truncate insns
to QImode and HImode.
diff --git a/gcc/dse.c b/gcc/dse.c
index e04e7e8..1aa1598 100644
--- a/gcc/dse.c
+++ b/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",
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d99cdad..1fea6a1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.target/mips/dse-1.c b/gcc/testsuite/gcc.target/mips/dse-1.c
new file mode 100644
index 0000000..a2b8445
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dse-1.c
@@ -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" } } */