diff options
author | Dominik Vogt <vogt@linux.vnet.ibm.com> | 2016-05-27 11:38:59 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2016-05-27 11:38:59 +0000 |
commit | 6a813c9659aec29ba18173f5d070c846a0919d60 (patch) | |
tree | 0fff9490dbeec47e35828223b26554340ab7390f /gcc/combine.c | |
parent | 4bc72f35f3322302a0672165bc9dc90ca0fc4b97 (diff) | |
download | gcc-6a813c9659aec29ba18173f5d070c846a0919d60.zip gcc-6a813c9659aec29ba18173f5d070c846a0919d60.tar.gz gcc-6a813c9659aec29ba18173f5d070c846a0919d60.tar.bz2 |
combine: Take known zero bits into account when checking extraction.
gcc/ChangeLog:
* combine.c (make_compound_operation): Take known zero bits into
account when checking for possible zero_extend.
gcc/testsuite/ChangeLog:
* gcc.dg/zero_bits_compound-1.c: New test.
* gcc.dg/zero_bits_compound-2.c: New test.
From-SVN: r236813
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index cd864cc..4db11b0 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7988,6 +7988,34 @@ make_compound_operation (rtx x, enum rtx_code in_code) next_code), i, NULL_RTX, 1, 1, 0, 1); + /* If the one operand is a paradoxical subreg of a register or memory and + the constant (limited to the smaller mode) has only zero bits where + the sub expression has known zero bits, this can be expressed as + a zero_extend. */ + else if (GET_CODE (XEXP (x, 0)) == SUBREG) + { + rtx sub; + + sub = XEXP (XEXP (x, 0), 0); + machine_mode sub_mode = GET_MODE (sub); + if ((REG_P (sub) || MEM_P (sub)) + && GET_MODE_PRECISION (sub_mode) < mode_width) + { + unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode); + unsigned HOST_WIDE_INT mask; + + /* original AND constant with all the known zero bits set */ + mask = UINTVAL (XEXP (x, 1)) | (~nonzero_bits (sub, sub_mode)); + if ((mask & mode_mask) == mode_mask) + { + new_rtx = make_compound_operation (sub, next_code); + new_rtx = make_extraction (mode, new_rtx, 0, 0, + GET_MODE_PRECISION (sub_mode), + 1, 0, in_code == COMPARE); + } + } + } + break; case LSHIFTRT: |