diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-01-12 10:20:42 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-01-12 10:20:42 +0000 |
commit | 86ae8eb8e5ae4b6a5d485fdef4adf818847d0112 (patch) | |
tree | 21404f1aa1b04ea857b9994acd0df54c4c0131b5 | |
parent | fd4359f41f1f82ef7c07e73d69c522ace4945b54 (diff) | |
download | gcc-86ae8eb8e5ae4b6a5d485fdef4adf818847d0112.tar.gz |
PR rtl-optimization/83565
* rtlanal.c (nonzero_bits1): On WORD_REGISTER_OPERATIONS machines, do
not extend the result to a larger mode for rotate operations.
(num_sign_bit_copies1): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@256573 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/rtlanal.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20180112-1.c | 32 |
4 files changed, 57 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9c959c0765..3e8e313fbfe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-01-12 Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/83565 + * rtlanal.c (nonzero_bits1): On WORD_REGISTER_OPERATIONS machines, do + not extend the result to a larger mode for rotate operations. + (num_sign_bit_copies1): Likewise. + 2018-01-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> Backport from mainline diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index acb4230aac8..b93d19537bb 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -4312,7 +4312,7 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x, { unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode); unsigned HOST_WIDE_INT inner_nz; - enum rtx_code code; + enum rtx_code code = GET_CODE (x); machine_mode inner_mode; unsigned int mode_width = GET_MODE_PRECISION (mode); @@ -4335,18 +4335,18 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x, return nonzero; /* If MODE is wider than X, but both are a single word for both the host - and target machines, we can compute this from which bits of the - object might be nonzero in its own mode, taking into account the fact - that on many CISC machines, accessing an object in a wider mode - causes the high-order bits to become undefined. So they are - not known to be zero. */ - - if (!WORD_REGISTER_OPERATIONS - && GET_MODE (x) != VOIDmode + and target machines, we can compute this from which bits of the object + might be nonzero in its own mode, taking into account the fact that, on + CISC machines, accessing an object in a wider mode generally causes the + high-order bits to become undefined, so they are not known to be zero. + We extend this reasoning to RISC machines for rotate operations since the + semantics of the operations in the larger mode is not well defined. */ + if (GET_MODE (x) != VOIDmode && GET_MODE (x) != mode && GET_MODE_PRECISION (GET_MODE (x)) <= BITS_PER_WORD && GET_MODE_PRECISION (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT - && GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (GET_MODE (x))) + && GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (GET_MODE (x)) + && (!WORD_REGISTER_OPERATIONS || code == ROTATE)) { nonzero &= cached_nonzero_bits (x, GET_MODE (x), known_x, known_mode, known_ret); @@ -4356,7 +4356,6 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x, /* Please keep nonzero_bits_binary_arith_p above in sync with the code in the switch below. */ - code = GET_CODE (x); switch (code) { case REG: @@ -4873,8 +4872,10 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x, { /* If this machine does not do all register operations on the entire register and MODE is wider than the mode of X, we can say nothing - at all about the high-order bits. */ - if (!WORD_REGISTER_OPERATIONS) + at all about the high-order bits. We extend this reasoning to every + machine for rotate operations since the semantics of the operations + in the larger mode is not well defined. */ + if (!WORD_REGISTER_OPERATIONS || code == ROTATE || code == ROTATERT) return 1; /* Likewise on machines that do, if the mode of the object is smaller diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c2b1ee17db7..77e7915acd9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-01-12 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20180112-1.c: New test. + 2018-01-10 Steven G. Kargl <kargl@gcc.gnu.org> Backport from trunk diff --git a/gcc/testsuite/gcc.c-torture/execute/20180112-1.c b/gcc/testsuite/gcc.c-torture/execute/20180112-1.c new file mode 100644 index 00000000000..6752661ecb6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20180112-1.c @@ -0,0 +1,32 @@ +/* PR rtl-optimization/83565 */ +/* Testcase by Sergei Trofimovich <slyfox@inbox.ru> */ + +extern void abort (void); + +typedef unsigned int u32; + +u32 bug (u32 * result) __attribute__((noinline)); +u32 bug (u32 * result) +{ + volatile u32 ss = 0xFFFFffff; + volatile u32 d = 0xEEEEeeee; + u32 tt = d & 0x00800000; + u32 r = tt << 8; + + r = (r >> 31) | (r << 1); + + u32 u = r^ss; + u32 off = u >> 1; + + *result = tt; + return off; +} + +int main(void) +{ + u32 l; + u32 off = bug(&l); + if (off != 0x7fffffff) + abort (); + return 0; +} |