Fix PR rtl-optimization/83565

Message ID 15313529.xjM19aB6vx@polaris
State New
Headers show
Series
  • Fix PR rtl-optimization/83565
Related show

Commit Message

Eric Botcazou Jan. 12, 2018, 10:20 a.m.
This fixes a regression present on the mainline and 7 branch for IA-64 whereby 
the combiner wrongly infers that some bits are zero after a rotate operation 
because nonzero_bits says so for WORD_REGISTER_OPERATIONS machines.

As discussed in the audit trail, WORD_REGISTER_OPERATIONS is ambiguous because 
it isn't fully clear which operations are covered.  But it seems sensible to 
say that rotate operations are not, since neither defining nor leveraging what 
happens for the upper bits of a register when the lower bits are rotated seems 
straightforward.  So the attached patch just implements that.

There are two versions of the patch: one for the 7 branch which only does that 
and one for the mainline which additionally handles ROTATERT in nonzero_bits1 
(the RTL operation is already handled in the twin num_sign_bit_copies1).

Tested on IA-64/Linux and SPARC64/Linux, applied on mainline and 7 branch.


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  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.c-torture/execute/20180112-1.c: New test.

Patch

Index: rtlanal.c
===================================================================
--- rtlanal.c	(revision 255413)
+++ rtlanal.c	(working copy)
@@ -4312,7 +4312,7 @@  nonzero_bits1 (const_rtx x, machine_mode
 {
   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
     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
 
   /* 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, machi
     {
       /* 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