]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/simplify-rtx.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / simplify-rtx.c
index eff1d07a2533c7bda5f0529cd318f08e6d5209d6..28c2dc69ae7de9bbfee8e8590fcbedea55350d98 100644 (file)
@@ -2215,6 +2215,53 @@ mask_to_comparison (int mask)
     }
 }
 
+/* Return true if CODE is valid for comparisons of mode MODE, false
+   otherwise.
+
+   It is always safe to return false, even if the code was valid for the
+   given mode as that will merely suppress optimizations.  */
+
+static bool
+comparison_code_valid_for_mode (enum rtx_code code, enum machine_mode mode)
+{
+  switch (code)
+    {
+      /* These are valid for integral, floating and vector modes.  */
+      case NE:
+      case EQ:
+      case GE:
+      case GT:
+      case LE:
+      case LT:
+       return (INTEGRAL_MODE_P (mode)
+               || FLOAT_MODE_P (mode)
+               || VECTOR_MODE_P (mode));
+
+      /* These are valid for floating point modes.  */
+      case LTGT:
+      case UNORDERED:
+      case ORDERED:
+      case UNEQ:
+      case UNGE:
+      case UNGT:
+      case UNLE:
+      case UNLT:
+       return FLOAT_MODE_P (mode);
+
+      /* These are filtered out in simplify_logical_operation, but
+        we check for them too as a matter of safety.   They are valid
+        for integral and vector modes.  */
+      case GEU:
+      case GTU:
+      case LEU:
+      case LTU:
+       return INTEGRAL_MODE_P (mode) || VECTOR_MODE_P (mode);
+
+      default:
+       gcc_unreachable ();
+    }
+}
+                                      
 /* Simplify a logical operation CODE with result mode MODE, operating on OP0
    and OP1, which should be both relational operations.  Return 0 if no such
    simplification is possible.  */
@@ -2252,6 +2299,10 @@ simplify_logical_relational_operation (enum rtx_code code, machine_mode mode,
 
   code = mask_to_comparison (mask);
 
+  /* Many comparison codes are only valid for certain mode classes.  */
+  if (!comparison_code_valid_for_mode (code, mode))
+    return 0;
+
   op0 = XEXP (op1, 0);
   op1 = XEXP (op1, 1);
 
@@ -3647,9 +3698,21 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
        {
          rtx tmp = gen_int_shift_amount
            (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1));
-         tmp = simplify_gen_binary (code, inner_mode,
-                                    XEXP (SUBREG_REG (op0), 0),
-                                    tmp);
+
+        /* Combine would usually zero out the value when combining two
+           local shifts and the range becomes larger or equal to the mode.
+           However since we fold away one of the shifts here combine won't
+           see it so we should immediately zero the result if it's out of
+           range.  */
+        if (code == LSHIFTRT
+            && INTVAL (tmp) >= GET_MODE_BITSIZE (inner_mode))
+         tmp = const0_rtx;
+        else
+          tmp = simplify_gen_binary (code,
+                                     inner_mode,
+                                     XEXP (SUBREG_REG (op0), 0),
+                                     tmp);
+
          return lowpart_subreg (int_mode, tmp, inner_mode);
        }