diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2015-08-08 03:51:27 +0200 |
---|---|---|
committer | Segher Boessenkool <segher@gcc.gnu.org> | 2015-08-08 03:51:27 +0200 |
commit | 1aeec6dc1f26657cc32ed107b3de255566fcca41 (patch) | |
tree | e9ec333a8008794cd08d520fb3cdb36ff0415fbd /gcc/combine.c | |
parent | 0fa95f4ead2faf03bde6bb5c458e06f197b34ca2 (diff) | |
download | gcc-1aeec6dc1f26657cc32ed107b3de255566fcca41.zip gcc-1aeec6dc1f26657cc32ed107b3de255566fcca41.tar.gz gcc-1aeec6dc1f26657cc32ed107b3de255566fcca41.tar.bz2 |
re PR rtl-optimization/67028 (combine bug. Different assumptions about subreg in different places.)
PR rtl-optimization/67028
* combine.c (simplify_comparison): Fix comment. Rearrange code.
Add test to see if a const_int fits in the new mode.
gcc/testsuite/
PR rtl-optimization/67028
* gcc.dg/pr67028.c: New testcase.
From-SVN: r226731
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index 4a92f55..8f98cbb 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -12057,14 +12057,15 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) continue; } - /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 + /* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1 fits in both M1 and M2 and the SUBREG is either paradoxical or represents the low part, permute the SUBREG and the AND and try again. */ - if (GET_CODE (XEXP (op0, 0)) == SUBREG) + if (GET_CODE (XEXP (op0, 0)) == SUBREG + && CONST_INT_P (XEXP (op0, 1))) { - unsigned HOST_WIDE_INT c1; tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0))); + unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1)); /* Require an integral mode, to avoid creating something like (AND:SF ...). */ if (SCALAR_INT_MODE_P (tmode) @@ -12074,16 +12075,20 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) have a defined value due to the AND operation. However, if we commute the AND inside the SUBREG then they no longer have defined values and the meaning of - the code has been changed. */ + the code has been changed. + Also C1 should not change value in the smaller mode, + see PR67028 (a positive C1 can become negative in the + smaller mode, so that the AND does no longer mask the + upper bits). */ && ((WORD_REGISTER_OPERATIONS && mode_width > GET_MODE_PRECISION (tmode) - && mode_width <= BITS_PER_WORD) + && mode_width <= BITS_PER_WORD + && trunc_int_for_mode (c1, tmode) == (HOST_WIDE_INT) c1) || (mode_width <= GET_MODE_PRECISION (tmode) && subreg_lowpart_p (XEXP (op0, 0)))) - && CONST_INT_P (XEXP (op0, 1)) && mode_width <= HOST_BITS_PER_WIDE_INT && HWI_COMPUTABLE_MODE_P (tmode) - && ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0 + && (c1 & ~mask) == 0 && (c1 & ~GET_MODE_MASK (tmode)) == 0 && c1 != mask && c1 != GET_MODE_MASK (tmode)) |