diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2015-11-11 15:09:30 +0100 |
---|---|---|
committer | Segher Boessenkool <segher@gcc.gnu.org> | 2015-11-11 15:09:30 +0100 |
commit | 3b1da8bb77bb07285272f2ad9e516197f3fe0835 (patch) | |
tree | c09f91af0c54de0985d5a415cf2c88fc2d1c1afd | |
parent | 7ad291c0e8e6a489d98741eb958736cc5f09d0b7 (diff) | |
download | gcc-3b1da8bb77bb07285272f2ad9e516197f3fe0835.zip gcc-3b1da8bb77bb07285272f2ad9e516197f3fe0835.tar.gz gcc-3b1da8bb77bb07285272f2ad9e516197f3fe0835.tar.bz2 |
simplify-rtx: Simplify trunc of and of shiftrt
If we have
(truncate:M1 (and:M2 (lshiftrt:M2 (x:M2) C) C2))
we can write it instead as
(and:M1 (lshiftrt:M1 (truncate:M1 (x:M2)) C) C2)
(if that is valid, of course), which has smaller modes for the
binary ops, and the truncate can often simplify further (if "x"
is a register, for example).
* gcc/simplify-rtx.c (simplify_truncation): Simplify TRUNCATE
of AND of [LA]SHIFTRT.
From-SVN: r230164
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 28 |
2 files changed, 33 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fb7e4f0..eb556d0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-11-11 Segher Boessenkool <segher@kernel.crashing.org> + + * gcc/simplify-rtx.c (simplify_truncation): Simplify TRUNCATE + of AND of [LA]SHIFTRT. + 2015-11-11 Martin Liska <mliska@suse.cz> Richard Biener <rguenther@suse.de> diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 17568ba..c4fc42a 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -714,6 +714,34 @@ simplify_truncation (machine_mode mode, rtx op, return simplify_gen_binary (ASHIFT, mode, XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + /* Likewise (truncate:QI (and:SI (lshiftrt:SI (x:SI) C) C2)) into + (and:QI (lshiftrt:QI (truncate:QI (x:SI)) C) C2) for suitable C + and C2. */ + if (GET_CODE (op) == AND + && (GET_CODE (XEXP (op, 0)) == LSHIFTRT + || GET_CODE (XEXP (op, 0)) == ASHIFTRT) + && CONST_INT_P (XEXP (XEXP (op, 0), 1)) + && CONST_INT_P (XEXP (op, 1))) + { + rtx op0 = (XEXP (XEXP (op, 0), 0)); + rtx shift_op = XEXP (XEXP (op, 0), 1); + rtx mask_op = XEXP (op, 1); + unsigned HOST_WIDE_INT shift = UINTVAL (shift_op); + unsigned HOST_WIDE_INT mask = UINTVAL (mask_op); + + if (shift < precision + /* If doing this transform works for an X with all bits set, + it works for any X. */ + && ((GET_MODE_MASK (mode) >> shift) & mask) + == ((GET_MODE_MASK (op_mode) >> shift) & mask) + && (op0 = simplify_gen_unary (TRUNCATE, mode, op0, op_mode)) + && (op0 = simplify_gen_binary (LSHIFTRT, mode, op0, shift_op))) + { + mask_op = GEN_INT (trunc_int_for_mode (mask, mode)); + return simplify_gen_binary (AND, mode, op0, mask_op); + } + } + /* Recognize a word extraction from a multi-word subreg. */ if ((GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) |