Commit 371ae937 by Eric Botcazou Committed by Eric Botcazou

re PR rtl-optimization/83565 (RTL combine pass yields wrong rotate result)

	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.

From-SVN: r256572
parent c574147e
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> 2018-01-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR target/40411 PR target/40411
......
...@@ -4429,7 +4429,7 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4429,7 +4429,7 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
{ {
unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode); unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
unsigned HOST_WIDE_INT inner_nz; unsigned HOST_WIDE_INT inner_nz;
enum rtx_code code; enum rtx_code code = GET_CODE (x);
machine_mode inner_mode; machine_mode inner_mode;
unsigned int inner_width; unsigned int inner_width;
scalar_int_mode xmode; scalar_int_mode xmode;
...@@ -4465,16 +4465,16 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4465,16 +4465,16 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
return nonzero; return nonzero;
/* If MODE is wider than X, but both are a single word for both the host /* 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 and target machines, we can compute this from which bits of the object
object might be nonzero in its own mode, taking into account the fact might be nonzero in its own mode, taking into account the fact that, on
that on many CISC machines, accessing an object in a wider mode CISC machines, accessing an object in a wider mode generally causes the
causes the high-order bits to become undefined. So they are high-order bits to become undefined, so they are not known to be zero.
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 (!WORD_REGISTER_OPERATIONS if (mode_width > xmode_width
&& mode_width > xmode_width
&& xmode_width <= BITS_PER_WORD && xmode_width <= BITS_PER_WORD
&& xmode_width <= HOST_BITS_PER_WIDE_INT) && xmode_width <= HOST_BITS_PER_WIDE_INT
&& (!WORD_REGISTER_OPERATIONS || code == ROTATE || code == ROTATERT))
{ {
nonzero &= cached_nonzero_bits (x, xmode, nonzero &= cached_nonzero_bits (x, xmode,
known_x, known_mode, known_ret); known_x, known_mode, known_ret);
...@@ -4484,7 +4484,6 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4484,7 +4484,6 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
/* Please keep nonzero_bits_binary_arith_p above in sync with /* Please keep nonzero_bits_binary_arith_p above in sync with
the code in the switch below. */ the code in the switch below. */
code = GET_CODE (x);
switch (code) switch (code)
{ {
case REG: case REG:
...@@ -4760,10 +4759,11 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4760,10 +4759,11 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
} }
break; break;
case ASHIFT:
case ASHIFTRT: case ASHIFTRT:
case LSHIFTRT: case LSHIFTRT:
case ASHIFT:
case ROTATE: case ROTATE:
case ROTATERT:
/* The nonzero bits are in two classes: any bits within MODE /* The nonzero bits are in two classes: any bits within MODE
that aren't in xmode are always significant. The rest of the that aren't in xmode are always significant. The rest of the
nonzero bits are those that are significant in the operand of nonzero bits are those that are significant in the operand of
...@@ -4786,10 +4786,17 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4786,10 +4786,17 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
if (mode_width > xmode_width) if (mode_width > xmode_width)
outer = (op_nonzero & nonzero & ~mode_mask); outer = (op_nonzero & nonzero & ~mode_mask);
if (code == LSHIFTRT) switch (code)
inner >>= count;
else if (code == ASHIFTRT)
{ {
case ASHIFT:
inner <<= count;
break;
case LSHIFTRT:
inner >>= count;
break;
case ASHIFTRT:
inner >>= count; inner >>= count;
/* If the sign bit may have been nonzero before the shift, we /* If the sign bit may have been nonzero before the shift, we
...@@ -4798,13 +4805,23 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4798,13 +4805,23 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
if (inner & (HOST_WIDE_INT_1U << (xmode_width - 1 - count))) if (inner & (HOST_WIDE_INT_1U << (xmode_width - 1 - count)))
inner |= (((HOST_WIDE_INT_1U << count) - 1) inner |= (((HOST_WIDE_INT_1U << count) - 1)
<< (xmode_width - count)); << (xmode_width - count));
break;
case ROTATE:
inner = (inner << (count % xmode_width)
| (inner >> (xmode_width - (count % xmode_width))))
& mode_mask;
break;
case ROTATERT:
inner = (inner >> (count % xmode_width)
| (inner << (xmode_width - (count % xmode_width))))
& mode_mask;
break;
default:
gcc_unreachable ();
} }
else if (code == ASHIFT)
inner <<= count;
else
inner = ((inner << (count % xmode_width)
| (inner >> (xmode_width - (count % xmode_width))))
& mode_mask);
nonzero &= (outer | inner); nonzero &= (outer | inner);
} }
...@@ -4992,8 +5009,10 @@ num_sign_bit_copies1 (const_rtx x, scalar_int_mode mode, const_rtx known_x, ...@@ -4992,8 +5009,10 @@ num_sign_bit_copies1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
{ {
/* If this machine does not do all register operations on the entire /* 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 register and MODE is wider than the mode of X, we can say nothing
at all about the high-order bits. */ at all about the high-order bits. We extend this reasoning to every
if (!WORD_REGISTER_OPERATIONS) 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; return 1;
/* Likewise on machines that do, if the mode of the object is smaller /* Likewise on machines that do, if the mode of the object is smaller
......
2018-01-12 Eric Botcazou <ebotcazou@adacore.com>
* gcc.c-torture/execute/20180112-1.c: New test.
2018-01-12 Tom de Vries <tom@codesourcery.com> 2018-01-12 Tom de Vries <tom@codesourcery.com>
* g++.dg/ext/label13.C: Add dg-require-effective-target indirect_jumps. * g++.dg/ext/label13.C: Add dg-require-effective-target indirect_jumps.
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment