combine: Convert subreg-of-lshiftrt to zero_extract properly (PR78390)
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 23 Nov 2016 14:33:13 +0000 (15:33 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 23 Nov 2016 14:33:13 +0000 (15:33 +0100)
r242414, for PR77881, introduces some bugs (PR78390, PR78438, PR78477).
It all has the same root cause: that patch makes combine convert every
lowpart subreg of a logical shift right to a zero_extract.  This cannot
work at all if it is not a constant shift, and it has to be a bit more
careful exactly which bits it extracts.

PR target/77881
PR bootstrap/78390
PR target/78438
PR bootstrap/78477
* combine.c (make_compound_operation_int): Do not convert a subreg of
a non-constant logical shift right to a zero_extract.  Handle the case
where some zero bits have been shifted into the range covered by that
subreg.

From-SVN: r242757

gcc/ChangeLog
gcc/combine.c

index aa1d22f92d7b19449df3e965e13fe3fa5db91eda..9f1a5c2e0ba7174622fcd7887e66769bd43059d4 100644 (file)
@@ -1,3 +1,14 @@
+2016-11-23  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR target/77881
+       PR bootstrap/78390
+       PR target/78438
+       PR bootstrap/78477
+       * combine.c (make_compound_operation_int): Do not convert a subreg of
+       a non-constant logical shift right to a zero_extract.  Handle the case
+       where some zero bits have been shifted into the range covered by that
+       subreg.
+
 2016-11-23  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 93621bd02fbb61ac7634f82ccf28e20d331bd23b..ae25ef35ed9b985ae64f916e1e124c82420c3522 100644 (file)
@@ -8089,12 +8089,17 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
        /* If the SUBREG is masking of a logical right shift,
           make an extraction.  */
        if (GET_CODE (inner) == LSHIFTRT
+           && CONST_INT_P (XEXP (inner, 1))
            && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
            && subreg_lowpart_p (x))
          {
            new_rtx = make_compound_operation (XEXP (inner, 0), next_code);
+           int width = GET_MODE_PRECISION (GET_MODE (inner))
+                       - INTVAL (XEXP (inner, 1));
+           if (width > mode_width)
+             width = mode_width;
            new_rtx = make_extraction (mode, new_rtx, 0, XEXP (inner, 1),
-                                      mode_width, 1, 0, in_code == COMPARE);
+                                      width, 1, 0, in_code == COMPARE);
            break;
          }