This patch just splits some code out of make_compound_operation_int
into a new function called make_compound_operation_and.  It is a
prerequisite for the fix for PR106594.

It might (or might not) make sense to put more of the existing
"and" handling into the new function, so that the subreg+lshiftrt
case can be handled through recursion rather than duplication.
But that's certainly not necessary to fix the bug, so is at
best stage 1 material.

No behavioural change intended.

gcc/
        * combine.cc (make_compound_operation_and): New function,
        split out from...
        (make_compound_operation_int): ...here.
---
 gcc/combine.cc | 84 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 54 insertions(+), 30 deletions(-)

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 053879500b7..7d446d02cb4 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -7952,6 +7952,56 @@ extract_left_shift (scalar_int_mode mode, rtx x, int 
count)
   return 0;
 }
 
+/* A subroutine of make_compound_operation_int.  Try to combine an outer
+   AND of X and MASK with a partnering inner operation to form a compound
+   operation.  Return the new X on success, otherwise return null.
+
+   MODE is the mode of X.  IN_CODE is as for make_compound_operation.
+   NEXT_CODE is the value of IN_CODE that should be used for (recursive)
+   calls to make_compound_operation.  */
+
+static rtx
+make_compound_operation_and (scalar_int_mode mode, rtx x,
+                            unsigned HOST_WIDE_INT mask,
+                            rtx_code in_code, rtx_code next_code)
+{
+  switch (GET_CODE (x))
+    {
+    case SUBREG:
+      /* If the operand is a paradoxical subreg of a register or memory
+        and MASK (limited to the smaller mode) has only zero bits where
+        the sub expression has known zero bits, this can be expressed as
+        a zero_extend.  */
+      {
+       rtx sub = XEXP (x, 0);
+       machine_mode sub_mode = GET_MODE (sub);
+       int sub_width;
+       if ((REG_P (sub) || MEM_P (sub))
+           && GET_MODE_PRECISION (sub_mode).is_constant (&sub_width)
+           && sub_width < GET_MODE_PRECISION (mode))
+         {
+           unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode);
+           unsigned HOST_WIDE_INT submask;
+
+           /* The shifted AND constant with all the known zero
+              bits set.  */
+           submask = mask | ~nonzero_bits (sub, sub_mode);
+           if ((submask & mode_mask) == mode_mask)
+             {
+               rtx new_rtx = make_compound_operation (sub, next_code);
+               return make_extraction (mode, new_rtx, 0, 0, sub_width,
+                                       1, 0, in_code == COMPARE);
+             }
+         }
+       break;
+      }
+
+    default:
+      break;
+    }
+  return NULL_RTX;
+}
+
 /* Subroutine of make_compound_operation.  *X_PTR is the rtx at the current
    level of the expression and MODE is its mode.  IN_CODE is as for
    make_compound_operation.  *NEXT_CODE_PTR is the value of IN_CODE
@@ -8184,36 +8234,10 @@ make_compound_operation_int (scalar_int_mode mode, rtx 
*x_ptr,
                                   make_compound_operation (XEXP (x, 0),
                                                            next_code),
                                   i, NULL_RTX, 1, 1, 0, 1);
-
-      /* If the one operand is a paradoxical subreg of a register or memory and
-        the constant (limited to the smaller mode) has only zero bits where
-        the sub expression has known zero bits, this can be expressed as
-        a zero_extend.  */
-      else if (GET_CODE (XEXP (x, 0)) == SUBREG)
-       {
-         rtx sub;
-
-         sub = XEXP (XEXP (x, 0), 0);
-         machine_mode sub_mode = GET_MODE (sub);
-         int sub_width;
-         if ((REG_P (sub) || MEM_P (sub))
-             && GET_MODE_PRECISION (sub_mode).is_constant (&sub_width)
-             && sub_width < mode_width)
-           {
-             unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode);
-             unsigned HOST_WIDE_INT mask;
-
-             /* original AND constant with all the known zero bits set */
-             mask = UINTVAL (XEXP (x, 1)) | (~nonzero_bits (sub, sub_mode));
-             if ((mask & mode_mask) == mode_mask)
-               {
-                 new_rtx = make_compound_operation (sub, next_code);
-                 new_rtx = make_extraction (mode, new_rtx, 0, 0, sub_width,
-                                            1, 0, in_code == COMPARE);
-               }
-           }
-       }
-
+      else
+       new_rtx = make_compound_operation_and (mode, XEXP (x, 0),
+                                              UINTVAL (XEXP (x, 1)),
+                                              in_code, next_code);
       break;
 
     case LSHIFTRT:
-- 
2.25.1

Reply via email to