From: Richard Sandiford Date: Sun, 16 Sep 2007 21:02:54 +0000 (+0000) Subject: dse.c (find_shift_sequence): Allow word as well as subword shifts. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=348eea5f00fe47fa13c235e9e93c082b8b285f97;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db1ef1ca73f..60bd52db87f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-09-16 Richard Sandiford + + * 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 * config/mips/mips.md (SHORT): Fix long line. diff --git a/gcc/dse.c b/gcc/dse.c index e04e7e820ad..1aa1598e6b4 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 d99cdad1941..1fea6a1daaf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-09-16 Richard Sandiford + + * gcc.target/mips/dse-1.c: New test. + 2007-09-16 Nathan Sidwell 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 00000000000..a2b84450968 --- /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" } } */