aboutsummaryrefslogtreecommitdiff
path: root/gcc/simplify-rtx.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-07-08 10:48:40 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2013-07-08 10:48:40 +0200
commit8140c06592fe11cfb82c54f0dc467705381a8785 (patch)
tree38579d40ff3a272b2669af830c79e5de77e39b55 /gcc/simplify-rtx.c
parent78d432da45406aaeb97b7485f548d07fc3ca7049 (diff)
downloadgcc-8140c06592fe11cfb82c54f0dc467705381a8785.zip
gcc-8140c06592fe11cfb82c54f0dc467705381a8785.tar.gz
gcc-8140c06592fe11cfb82c54f0dc467705381a8785.tar.bz2
re PR target/57819 (Suboptimal shift patterns)
PR target/57819 * simplify-rtx.c (simplify_unary_operation_1) <case ZERO_EXTEND>: Simplify (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)). * combine.c (make_extraction): Create ZERO_EXTEND or SIGN_EXTEND using simplify_gen_unary instead of gen_rtx_*_EXTEND. * config/i386/i386.md (*jcc_bt<mode>_1): New define_insn_and_split. * gcc.target/i386/pr57819.c: New test. From-SVN: r200775
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r--gcc/simplify-rtx.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index be54db8..17a3d12 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1470,6 +1470,29 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
}
}
+ /* (zero_extend:M (subreg:N <X:O>)) is <X:O> (for M == O) or
+ (zero_extend:M <X:O>), if X doesn't have any non-zero bits outside
+ of mode N. E.g.
+ (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is
+ (and:SI (reg:SI) (const_int 63)). */
+ if (GET_CODE (op) == SUBREG
+ && GET_MODE_PRECISION (GET_MODE (op))
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+ && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+ <= HOST_BITS_PER_WIDE_INT
+ && GET_MODE_PRECISION (mode)
+ >= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+ && subreg_lowpart_p (op)
+ && (nonzero_bits (SUBREG_REG (op), GET_MODE (SUBREG_REG (op)))
+ & ~GET_MODE_MASK (GET_MODE (op))) == 0)
+ {
+ if (GET_MODE_PRECISION (mode)
+ == GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
+ return SUBREG_REG (op);
+ return simplify_gen_unary (ZERO_EXTEND, mode, SUBREG_REG (op),
+ GET_MODE (SUBREG_REG (op)));
+ }
+
#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
/* As we do not know which address space the pointer is referring to,
we can do this only if the target does not support different pointer