diff options
author | Richard Sandiford <rsandifo@nildram.co.uk> | 2008-03-22 19:37:53 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2008-03-22 19:37:53 +0000 |
commit | 18b526e806ab64557cd575ff407fcb1da16ee8fd (patch) | |
tree | bb912a45ce2ff3b1666c9a26271e0833dc4b7c16 /gcc/expmed.c | |
parent | 48e55066d5d0cd652b6527f08cb67768c4aaabe7 (diff) | |
download | gcc-18b526e806ab64557cd575ff407fcb1da16ee8fd.zip gcc-18b526e806ab64557cd575ff407fcb1da16ee8fd.tar.gz gcc-18b526e806ab64557cd575ff407fcb1da16ee8fd.tar.bz2 |
re PR rtl-optimization/33927 (replace_read in dse.c could handle cases where GET_MODE_CLASS (read_mode) != GET_MODE_CLASS (store_mode) (and the size is the same))
gcc/
PR rtl-optimization/33927
* Makefile.in (dse.o): Depend on $(TM_P_H).
* expr.h (extract_low_bits): Declare.
* expmed.c (extract_low_bits): New function.
* rtlhooks.c (gen_lowpart_general): Generalize SUBREG handling.
* dse.c: Include tm_p.h.
(find_shift_sequence): Remove the read_reg argument and return the
read value. Emit the instructions instead of returning them.
Iterate on new_mode rather than calculating it each time.
Check MODES_TIEABLE_P. Use simplify_gen_subreg to convert the
source to NEW_MODE and extract_low_bits to convert the shifted
value to READ_MODE.
(replace_read): Allow the load and store to have different mode
classes. Use extract_low_bits when SHIFT == 0. Create the shift
or extraction instructions before trying the replacement. Update
dump-file code accordingly, avoiding use of REGNO (store_info->rhs).
gcc/testsuite/
* gcc.target/mips/dse-1.c: Add checks for zeros.
From-SVN: r133452
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 04071d3..2f2e3cc 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -2098,6 +2098,66 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, NULL_RTX, 0); } +/* Try to read the low bits of SRC as an rvalue of mode MODE, preserving + the bit pattern. SRC_MODE is the mode of SRC; if this is smaller than + MODE, fill the upper bits with zeros. Fail if the layout of either + mode is unknown (as for CC modes) or if the extraction would involve + unprofitable mode punning. Return the value on success, otherwise + return null. + + This is different from gen_lowpart* in these respects: + + - the returned value must always be considered an rvalue + + - when MODE is wider than SRC_MODE, the extraction involves + a zero extension + + - when MODE is smaller than SRC_MODE, the extraction involves + a truncation (and is thus subject to TRULY_NOOP_TRUNCATION). + + In other words, this routine performs a computation, whereas the + gen_lowpart* routines are conceptually lvalue or rvalue subreg + operations. */ + +rtx +extract_low_bits (enum machine_mode mode, enum machine_mode src_mode, rtx src) +{ + enum machine_mode int_mode, src_int_mode; + + if (mode == src_mode) + return src; + + if (CONSTANT_P (src)) + return simplify_gen_subreg (mode, src, src_mode, + subreg_lowpart_offset (mode, src_mode)); + + if (GET_MODE_CLASS (mode) == MODE_CC || GET_MODE_CLASS (src_mode) == MODE_CC) + return NULL_RTX; + + if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (src_mode) + && MODES_TIEABLE_P (mode, src_mode)) + { + rtx x = gen_lowpart_common (mode, src); + if (x) + return x; + } + + src_int_mode = int_mode_for_mode (src_mode); + int_mode = int_mode_for_mode (mode); + if (src_int_mode == BLKmode || int_mode == BLKmode) + return NULL_RTX; + + if (!MODES_TIEABLE_P (src_int_mode, src_mode)) + return NULL_RTX; + if (!MODES_TIEABLE_P (int_mode, mode)) + return NULL_RTX; + + src = gen_lowpart (src_int_mode, src); + src = convert_modes (int_mode, src_int_mode, src, true); + src = gen_lowpart (mode, src); + return src; +} + /* Add INC into TARGET. */ void |