aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2008-03-22 19:37:53 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2008-03-22 19:37:53 +0000
commit18b526e806ab64557cd575ff407fcb1da16ee8fd (patch)
treebb912a45ce2ff3b1666c9a26271e0833dc4b7c16 /gcc/expmed.c
parent48e55066d5d0cd652b6527f08cb67768c4aaabe7 (diff)
downloadgcc-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.c60
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