coarray_data_1.f90: Link against libatomic if target libatomic_available.
[gcc.git] / gcc / fold-const.c
index 8476c223e4f2de35f7a4c1773d81eb65d3a97dba..571566aa6bca91e20153d7bfa4d6cfcd897cd97b 100644 (file)
@@ -1,5 +1,5 @@
 /* Fold a constant sub-tree into a single node for C-compiler
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -735,7 +735,7 @@ fold_negate_expr (location_t loc, tree t)
   return fold_convert_loc (loc, type, tem);
 }
 
-/* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T can not be
+/* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T cannot be
    negated in a simpler way.  Also allow for T to be NULL_TREE, in which case
    return NULL_TREE. */
 
@@ -966,21 +966,17 @@ int_binop_types_match_p (enum tree_code code, const_tree type1, const_tree type2
         && TYPE_MODE (type1) == TYPE_MODE (type2);
 }
 
-/* Subroutine of int_const_binop_1 that handles two INTEGER_CSTs.  */
+/* Combine two wide ints ARG1 and ARG2 under operation CODE to produce
+   a new constant in RES.  Return FALSE if we don't know how to
+   evaluate CODE at compile-time.  */
 
-static tree
-int_const_binop_2 (enum tree_code code, const_tree parg1, const_tree parg2,
-                  int overflowable)
+bool
+wide_int_binop (wide_int &res,
+               enum tree_code code, const wide_int &arg1, const wide_int &arg2,
+               signop sign, wi::overflow_type *overflow)
 {
-  wide_int res;
-  tree t;
-  tree type = TREE_TYPE (parg1);
-  signop sign = TYPE_SIGN (type);
-  bool overflow = false;
-
-  wi::tree_to_wide_ref arg1 = wi::to_wide (parg1);
-  wide_int arg2 = wi::to_wide (parg2, TYPE_PRECISION (type));
-
+  wide_int tmp;
+  *overflow = wi::OVF_NONE;
   switch (code)
     {
     case BIT_IOR_EXPR:
@@ -999,49 +995,53 @@ int_const_binop_2 (enum tree_code code, const_tree parg1, const_tree parg2,
     case LSHIFT_EXPR:
       if (wi::neg_p (arg2))
        {
-         arg2 = -arg2;
+         tmp = -arg2;
          if (code == RSHIFT_EXPR)
            code = LSHIFT_EXPR;
          else
            code = RSHIFT_EXPR;
        }
+      else
+        tmp = arg2;
 
       if (code == RSHIFT_EXPR)
        /* It's unclear from the C standard whether shifts can overflow.
           The following code ignores overflow; perhaps a C standard
           interpretation ruling is needed.  */
-       res = wi::rshift (arg1, arg2, sign);
+       res = wi::rshift (arg1, tmp, sign);
       else
-       res = wi::lshift (arg1, arg2);
+       res = wi::lshift (arg1, tmp);
       break;
 
     case RROTATE_EXPR:
     case LROTATE_EXPR:
       if (wi::neg_p (arg2))
        {
-         arg2 = -arg2;
+         tmp = -arg2;
          if (code == RROTATE_EXPR)
            code = LROTATE_EXPR;
          else
            code = RROTATE_EXPR;
        }
+      else
+        tmp = arg2;
 
       if (code == RROTATE_EXPR)
-       res = wi::rrotate (arg1, arg2);
+       res = wi::rrotate (arg1, tmp);
       else
-       res = wi::lrotate (arg1, arg2);
+       res = wi::lrotate (arg1, tmp);
       break;
 
     case PLUS_EXPR:
-      res = wi::add (arg1, arg2, sign, &overflow);
+      res = wi::add (arg1, arg2, sign, overflow);
       break;
 
     case MINUS_EXPR:
-      res = wi::sub (arg1, arg2, sign, &overflow);
+      res = wi::sub (arg1, arg2, sign, overflow);
       break;
 
     case MULT_EXPR:
-      res = wi::mul (arg1, arg2, sign, &overflow);
+      res = wi::mul (arg1, arg2, sign, overflow);
       break;
 
     case MULT_HIGHPART_EXPR:
@@ -1051,50 +1051,50 @@ int_const_binop_2 (enum tree_code code, const_tree parg1, const_tree parg2,
     case TRUNC_DIV_EXPR:
     case EXACT_DIV_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::div_trunc (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::div_trunc (arg1, arg2, sign, overflow);
       break;
 
     case FLOOR_DIV_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::div_floor (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::div_floor (arg1, arg2, sign, overflow);
       break;
 
     case CEIL_DIV_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::div_ceil (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::div_ceil (arg1, arg2, sign, overflow);
       break;
 
     case ROUND_DIV_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::div_round (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::div_round (arg1, arg2, sign, overflow);
       break;
 
     case TRUNC_MOD_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::mod_trunc (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::mod_trunc (arg1, arg2, sign, overflow);
       break;
 
     case FLOOR_MOD_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::mod_floor (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::mod_floor (arg1, arg2, sign, overflow);
       break;
 
     case CEIL_MOD_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::mod_ceil (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::mod_ceil (arg1, arg2, sign, overflow);
       break;
 
     case ROUND_MOD_EXPR:
       if (arg2 == 0)
-       return NULL_TREE;
-      res = wi::mod_round (arg1, arg2, sign, &overflow);
+       return false;
+      res = wi::mod_round (arg1, arg2, sign, overflow);
       break;
 
     case MIN_EXPR:
@@ -1106,89 +1106,94 @@ int_const_binop_2 (enum tree_code code, const_tree parg1, const_tree parg2,
       break;
 
     default:
-      return NULL_TREE;
+      return false;
     }
-
-  t = force_fit_type (type, res, overflowable,
-                     (((sign == SIGNED || overflowable == -1)
-                       && overflow)
-                      | TREE_OVERFLOW (parg1) | TREE_OVERFLOW (parg2)));
-
-  return t;
+  return true;
 }
 
-/* Combine two integer constants PARG1 and PARG2 under operation CODE
-   to produce a new constant.  Return NULL_TREE if we don't know how
+/* Combine two poly int's ARG1 and ARG2 under operation CODE to
+   produce a new constant in RES.  Return FALSE if we don't know how
    to evaluate CODE at compile-time.  */
 
-static tree
-int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
-                  int overflowable)
+static bool
+poly_int_binop (poly_wide_int &res, enum tree_code code,
+               const_tree arg1, const_tree arg2,
+               signop sign, wi::overflow_type *overflow)
 {
-  if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
-    return int_const_binop_2 (code, arg1, arg2, overflowable);
-
   gcc_assert (NUM_POLY_INT_COEFFS != 1);
-
-  if (poly_int_tree_p (arg1) && poly_int_tree_p (arg2))
+  gcc_assert (poly_int_tree_p (arg1) && poly_int_tree_p (arg2));
+  switch (code)
     {
-      poly_wide_int res;
-      bool overflow;
-      tree type = TREE_TYPE (arg1);
-      signop sign = TYPE_SIGN (type);
-      switch (code)
-       {
-       case PLUS_EXPR:
-         res = wi::add (wi::to_poly_wide (arg1),
-                        wi::to_poly_wide (arg2), sign, &overflow);
-         break;
+    case PLUS_EXPR:
+      res = wi::add (wi::to_poly_wide (arg1),
+                    wi::to_poly_wide (arg2), sign, overflow);
+      break;
 
-       case MINUS_EXPR:
-         res = wi::sub (wi::to_poly_wide (arg1),
-                        wi::to_poly_wide (arg2), sign, &overflow);
-         break;
+    case MINUS_EXPR:
+      res = wi::sub (wi::to_poly_wide (arg1),
+                    wi::to_poly_wide (arg2), sign, overflow);
+      break;
 
-       case MULT_EXPR:
-         if (TREE_CODE (arg2) == INTEGER_CST)
-           res = wi::mul (wi::to_poly_wide (arg1),
-                          wi::to_wide (arg2), sign, &overflow);
-         else if (TREE_CODE (arg1) == INTEGER_CST)
-           res = wi::mul (wi::to_poly_wide (arg2),
-                          wi::to_wide (arg1), sign, &overflow);
-         else
-           return NULL_TREE;
-         break;
+    case MULT_EXPR:
+      if (TREE_CODE (arg2) == INTEGER_CST)
+       res = wi::mul (wi::to_poly_wide (arg1),
+                      wi::to_wide (arg2), sign, overflow);
+      else if (TREE_CODE (arg1) == INTEGER_CST)
+       res = wi::mul (wi::to_poly_wide (arg2),
+                      wi::to_wide (arg1), sign, overflow);
+      else
+       return NULL_TREE;
+      break;
 
-       case LSHIFT_EXPR:
-         if (TREE_CODE (arg2) == INTEGER_CST)
-           res = wi::to_poly_wide (arg1) << wi::to_wide (arg2);
-         else
-           return NULL_TREE;
-         break;
+    case LSHIFT_EXPR:
+      if (TREE_CODE (arg2) == INTEGER_CST)
+       res = wi::to_poly_wide (arg1) << wi::to_wide (arg2);
+      else
+       return false;
+      break;
 
-       case BIT_IOR_EXPR:
-         if (TREE_CODE (arg2) != INTEGER_CST
-             || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2),
-                            &res))
-           return NULL_TREE;
-         break;
+    case BIT_IOR_EXPR:
+      if (TREE_CODE (arg2) != INTEGER_CST
+         || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2),
+                        &res))
+       return false;
+      break;
 
-       default:
-         return NULL_TREE;
-       }
-      return force_fit_type (type, res, overflowable,
-                            (((sign == SIGNED || overflowable == -1)
-                              && overflow)
-                             | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
+    default:
+      return false;
     }
-
-  return NULL_TREE;
+  return true;
 }
 
+/* Combine two integer constants ARG1 and ARG2 under operation CODE to
+   produce a new constant.  Return NULL_TREE if we don't know how to
+   evaluate CODE at compile-time.  */
+
 tree
-int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
+int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2,
+                int overflowable)
 {
-  return int_const_binop_1 (code, arg1, arg2, 1);
+  bool success = false;
+  poly_wide_int poly_res;
+  tree type = TREE_TYPE (arg1);
+  signop sign = TYPE_SIGN (type);
+  wi::overflow_type overflow = wi::OVF_NONE;
+
+  if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST)
+    {
+      wide_int warg1 = wi::to_wide (arg1), res;
+      wide_int warg2 = wi::to_wide (arg2, TYPE_PRECISION (type));
+      success = wide_int_binop (res, code, warg1, warg2, sign, &overflow);
+      poly_res = res;
+    }
+  else if (poly_int_tree_p (arg1) && poly_int_tree_p (arg2))
+    success = poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow);
+  if (success)
+    return force_fit_type (type, poly_res, overflowable,
+                          (((sign == SIGNED || overflowable == -1)
+                            && overflow)
+                           | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
+  return NULL_TREE;
 }
 
 /* Return true if binary operation OP distributes over addition in operand
@@ -1906,26 +1911,30 @@ size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1)
       /* And some specific cases even faster than that.  */
       if (code == PLUS_EXPR)
        {
-         if (integer_zerop (arg0) && !TREE_OVERFLOW (arg0))
+         if (integer_zerop (arg0)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
            return arg1;
-         if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+         if (integer_zerop (arg1)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
            return arg0;
        }
       else if (code == MINUS_EXPR)
        {
-         if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+         if (integer_zerop (arg1)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
            return arg0;
        }
       else if (code == MULT_EXPR)
        {
-         if (integer_onep (arg0) && !TREE_OVERFLOW (arg0))
+         if (integer_onep (arg0)
+             && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
            return arg1;
        }
 
       /* Handle general case of two integer constants.  For sizetype
          constant calculations we always want to know about overflow,
         even in the unsigned case.  */
-      tree res = int_const_binop_1 (code, arg0, arg1, -1);
+      tree res = int_const_binop (code, arg0, arg1, -1);
       if (res != NULL_TREE)
        return res;
     }
@@ -2787,6 +2796,22 @@ compcode_to_comparison (enum comparison_code code)
     }
 }
 
+/* Return true if COND1 tests the opposite condition of COND2.  */
+
+bool
+inverse_conditions_p (const_tree cond1, const_tree cond2)
+{
+  return (COMPARISON_CLASS_P (cond1)
+         && COMPARISON_CLASS_P (cond2)
+         && (invert_tree_comparison
+             (TREE_CODE (cond1),
+              HONOR_NANS (TREE_OPERAND (cond1, 0))) == TREE_CODE (cond2))
+         && operand_equal_p (TREE_OPERAND (cond1, 0),
+                             TREE_OPERAND (cond2, 0), 0)
+         && operand_equal_p (TREE_OPERAND (cond1, 1),
+                             TREE_OPERAND (cond2, 1), 0));
+}
+
 /* Return a tree for the comparison which is the combination of
    doing the AND or OR (depending on CODE) of the two operations LCODE
    and RCODE on the identical operands LL_ARG and LR_ARG.  Take into account
@@ -2917,6 +2942,9 @@ combine_comparisons (location_t loc,
 int
 operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 {
+  STRIP_ANY_LOCATION_WRAPPER (arg0);
+  STRIP_ANY_LOCATION_WRAPPER (arg1);
+
   /* When checking, verify at the outermost operand_equal_p call that
      if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
      hash value.  */
@@ -3430,7 +3458,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
     case tcc_declaration:
       /* Consider __builtin_sqrt equal to sqrt.  */
       return (TREE_CODE (arg0) == FUNCTION_DECL
-             && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
+             && fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1)
              && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
              && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
 
@@ -4252,7 +4280,7 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
      There are problems with FP fields since the type_for_size call
      below can fail for, e.g., XFmode.  */
   if (! INTEGRAL_TYPE_P (TREE_TYPE (exp)))
-    return 0;
+    return NULL_TREE;
 
   /* We are interested in the bare arrangement of bits, so strip everything
      that doesn't affect the machine mode.  However, record the type of the
@@ -4268,7 +4296,7 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
       exp = TREE_OPERAND (exp, 0);
       STRIP_NOPS (exp); STRIP_NOPS (and_mask);
       if (TREE_CODE (and_mask) != INTEGER_CST)
-       return 0;
+       return NULL_TREE;
     }
 
   poly_int64 poly_bitsize, poly_bitpos;
@@ -4284,7 +4312,11 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
       || (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
          && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
                               *pbitpos + *pbitsize) < 0))
-    return 0;
+    return NULL_TREE;
+
+  unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
+  if (unsigned_type == NULL_TREE)
+    return NULL_TREE;
 
   *exp_ = exp;
 
@@ -4295,7 +4327,6 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
     *punsignedp = TYPE_UNSIGNED (outer_type);
 
   /* Compute the mask to access the bitfield.  */
-  unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
   mask = build_int_cst_type (unsigned_type, -1);
@@ -4935,8 +4966,8 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
   /* Disable this optimization for function pointer expressions
      on targets that require function pointer canonicalization.  */
   if (targetm.have_canonicalize_funcptr_for_compare ()
-      && TREE_CODE (etype) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+      && POINTER_TYPE_P (etype)
+      && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (etype)))
     return NULL_TREE;
 
   if (! in_p)
@@ -5551,12 +5582,15 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
   /* On machines where the branch cost is expensive, if this is a
      short-circuited branch and the underlying object on both sides
      is the same, make a non-short-circuit operation.  */
-  else if (LOGICAL_OP_NON_SHORT_CIRCUIT
-          && !flag_sanitize_coverage
-          && lhs != 0 && rhs != 0
-          && (code == TRUTH_ANDIF_EXPR
-              || code == TRUTH_ORIF_EXPR)
-          && operand_equal_p (lhs, rhs, 0))
+  bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
+  if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
+    logical_op_non_short_circuit
+      = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
+  if (logical_op_non_short_circuit
+      && !flag_sanitize_coverage
+      && lhs != 0 && rhs != 0
+      && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
+      && operand_equal_p (lhs, rhs, 0))
     {
       /* If simple enough, just rewrite.  Otherwise, make a SAVE_EXPR
         unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
@@ -5988,12 +6022,13 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
     }
 
   /* If the right sides are not constant, do the same for it.  Also,
-     disallow this optimization if a size or signedness mismatch occurs
-     between the left and right sides.  */
+     disallow this optimization if a size, signedness or storage order
+     mismatch occurs between the left and right sides.  */
   if (l_const == 0)
     {
       if (ll_bitsize != lr_bitsize || rl_bitsize != rr_bitsize
          || ll_unsignedp != lr_unsignedp || rl_unsignedp != rr_unsignedp
+         || ll_reversep != lr_reversep
          /* Make sure the two fields on the right
             correspond to the left without being swapped.  */
          || ll_bitpos - rl_bitpos != lr_bitpos - rr_bitpos)
@@ -6486,14 +6521,14 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       if (tcode == code)
        {
          bool overflow_p = false;
-         bool overflow_mul_p;
+         wi::overflow_type overflow_mul;
          signop sign = TYPE_SIGN (ctype);
          unsigned prec = TYPE_PRECISION (ctype);
          wide_int mul = wi::mul (wi::to_wide (op1, prec),
                                  wi::to_wide (c, prec),
-                                 sign, &overflow_mul_p);
+                                 sign, &overflow_mul);
          overflow_p = TREE_OVERFLOW (c) | TREE_OVERFLOW (op1);
-         if (overflow_mul_p
+         if (overflow_mul
              && ((sign == UNSIGNED && tcode != MULT_EXPR) || sign == SIGNED))
            overflow_p = true;
          if (!overflow_p)
@@ -6587,6 +6622,13 @@ fold_binary_op_with_conditional_arg (location_t loc,
   tree rhs = NULL_TREE;
   enum tree_code cond_code = COND_EXPR;
 
+  /* Do not move possibly trapping operations into the conditional as this
+     pessimizes code and causes gimplification issues when applied late.  */
+  if (operation_could_trap_p (code, FLOAT_TYPE_P (type),
+                             ANY_INTEGRAL_TYPE_P (type)
+                             && TYPE_OVERFLOW_TRAPS (type), op1))
+    return NULL_TREE;
+
   if (TREE_CODE (cond) == COND_EXPR
       || TREE_CODE (cond) == VEC_COND_EXPR)
     {
@@ -6705,7 +6747,7 @@ fold_div_compare (enum tree_code code, tree c1, tree c2, tree *lo,
 {
   tree prod, tmp, type = TREE_TYPE (c1);
   signop sign = TYPE_SIGN (type);
-  bool overflow;
+  wi::overflow_type overflow;
 
   /* We have to do this the hard way to detect unsigned overflow.
      prod = int_const_binop (MULT_EXPR, c1, c2);  */
@@ -7115,7 +7157,7 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
   if (!same)
     return NULL_TREE;
 
-  if (! INTEGRAL_TYPE_P (type)
+  if (! ANY_INTEGRAL_TYPE_P (type)
       || TYPE_OVERFLOW_WRAPS (type)
       /* We are neither factoring zero nor minus one.  */
       || TREE_CODE (same) == INTEGER_CST)
@@ -8200,7 +8242,11 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
   if ((tem = fold_truth_andor_1 (loc, code, type, arg0, arg1)) != 0)
     return tem;
 
-  if (LOGICAL_OP_NON_SHORT_CIRCUIT
+  bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
+  if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
+    logical_op_non_short_circuit
+      = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
+  if (logical_op_non_short_circuit
       && !flag_sanitize_coverage
       && (code == TRUTH_AND_EXPR
           || code == TRUTH_ANDIF_EXPR
@@ -8376,7 +8422,7 @@ maybe_canonicalize_comparison (location_t loc, enum tree_code code, tree type,
 
 /* Return whether BASE + OFFSET + BITPOS may wrap around the address
    space.  This is used to avoid issuing overflow warnings for
-   expressions like &p->x which can not wrap.  */
+   expressions like &p->x which cannot wrap.  */
 
 static bool
 pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos)
@@ -8396,7 +8442,7 @@ pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos)
   else
     wi_offset = wi::to_poly_wide (offset);
 
-  bool overflow;
+  wi::overflow_type overflow;
   poly_wide_int units = wi::shwi (bits_to_bytes_round_down (bitpos),
                                  precision);
   poly_wide_int total = wi::add (wi_offset, units, UNSIGNED, &overflow);
@@ -9227,7 +9273,7 @@ bool
 expr_not_equal_to (tree t, const wide_int &w)
 {
   wide_int min, max, nz;
-  value_range_type rtype;
+  value_range_kind rtype;
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
@@ -10236,121 +10282,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
            }
        }
 
-      /* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
-        ((A & N) + B) & M -> (A + B) & M
-        Similarly if (N & M) == 0,
-        ((A | N) + B) & M -> (A + B) & M
-        and for - instead of + (or unary - instead of +)
-        and/or ^ instead of |.
-        If B is constant and (B & M) == 0, fold into A & M.  */
-      if (TREE_CODE (arg1) == INTEGER_CST)
-       {
-         wi::tree_to_wide_ref cst1 = wi::to_wide (arg1);
-         if ((~cst1 != 0) && (cst1 & (cst1 + 1)) == 0
-             && INTEGRAL_TYPE_P (TREE_TYPE (arg0))
-             && (TREE_CODE (arg0) == PLUS_EXPR
-                 || TREE_CODE (arg0) == MINUS_EXPR
-                 || TREE_CODE (arg0) == NEGATE_EXPR)
-             && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
-                 || TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE))
-           {
-             tree pmop[2];
-             int which = 0;
-             wide_int cst0;
-
-             /* Now we know that arg0 is (C + D) or (C - D) or
-                -C and arg1 (M) is == (1LL << cst) - 1.
-                Store C into PMOP[0] and D into PMOP[1].  */
-             pmop[0] = TREE_OPERAND (arg0, 0);
-             pmop[1] = NULL;
-             if (TREE_CODE (arg0) != NEGATE_EXPR)
-               {
-                 pmop[1] = TREE_OPERAND (arg0, 1);
-                 which = 1;
-               }
-
-             if ((wi::max_value (TREE_TYPE (arg0)) & cst1) != cst1)
-               which = -1;
-
-             for (; which >= 0; which--)
-               switch (TREE_CODE (pmop[which]))
-                 {
-                 case BIT_AND_EXPR:
-                 case BIT_IOR_EXPR:
-                 case BIT_XOR_EXPR:
-                   if (TREE_CODE (TREE_OPERAND (pmop[which], 1))
-                       != INTEGER_CST)
-                     break;
-                   cst0 = wi::to_wide (TREE_OPERAND (pmop[which], 1)) & cst1;
-                   if (TREE_CODE (pmop[which]) == BIT_AND_EXPR)
-                     {
-                       if (cst0 != cst1)
-                         break;
-                     }
-                   else if (cst0 != 0)
-                     break;
-                   /* If C or D is of the form (A & N) where
-                      (N & M) == M, or of the form (A | N) or
-                      (A ^ N) where (N & M) == 0, replace it with A.  */
-                   pmop[which] = TREE_OPERAND (pmop[which], 0);
-                   break;
-                 case INTEGER_CST:
-                   /* If C or D is a N where (N & M) == 0, it can be
-                      omitted (assumed 0).  */
-                   if ((TREE_CODE (arg0) == PLUS_EXPR
-                        || (TREE_CODE (arg0) == MINUS_EXPR && which == 0))
-                       && (cst1 & wi::to_wide (pmop[which])) == 0)
-                     pmop[which] = NULL;
-                   break;
-                 default:
-                   break;
-                 }
-
-             /* Only build anything new if we optimized one or both arguments
-                above.  */
-             if (pmop[0] != TREE_OPERAND (arg0, 0)
-                 || (TREE_CODE (arg0) != NEGATE_EXPR
-                     && pmop[1] != TREE_OPERAND (arg0, 1)))
-               {
-                 tree utype = TREE_TYPE (arg0);
-                 if (! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
-                   {
-                     /* Perform the operations in a type that has defined
-                        overflow behavior.  */
-                     utype = unsigned_type_for (TREE_TYPE (arg0));
-                     if (pmop[0] != NULL)
-                       pmop[0] = fold_convert_loc (loc, utype, pmop[0]);
-                     if (pmop[1] != NULL)
-                       pmop[1] = fold_convert_loc (loc, utype, pmop[1]);
-                   }
-
-                 if (TREE_CODE (arg0) == NEGATE_EXPR)
-                   tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[0]);
-                 else if (TREE_CODE (arg0) == PLUS_EXPR)
-                   {
-                     if (pmop[0] != NULL && pmop[1] != NULL)
-                       tem = fold_build2_loc (loc, PLUS_EXPR, utype,
-                                              pmop[0], pmop[1]);
-                     else if (pmop[0] != NULL)
-                       tem = pmop[0];
-                     else if (pmop[1] != NULL)
-                       tem = pmop[1];
-                     else
-                       return build_int_cst (type, 0);
-                   }
-                 else if (pmop[0] == NULL)
-                   tem = fold_build1_loc (loc, NEGATE_EXPR, utype, pmop[1]);
-                 else
-                   tem = fold_build2_loc (loc, MINUS_EXPR, utype,
-                                          pmop[0], pmop[1]);
-                 /* TEM is now the new binary +, - or unary - replacement.  */
-                 tem = fold_build2_loc (loc, BIT_AND_EXPR, utype, tem,
-                                        fold_convert_loc (loc, utype, arg1));
-                 return fold_convert_loc (loc, type, tem);
-               }
-           }
-       }
-
       /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char.  */
       if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
          && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
@@ -10748,28 +10679,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
            }
        }
 
-      /* If this is an NE or EQ comparison of zero against the result of a
-        signed MOD operation whose second operand is a power of 2, make
-        the MOD operation unsigned since it is simpler and equivalent.  */
-      if (integer_zerop (arg1)
-         && !TYPE_UNSIGNED (TREE_TYPE (arg0))
-         && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
-             || TREE_CODE (arg0) == CEIL_MOD_EXPR
-             || TREE_CODE (arg0) == FLOOR_MOD_EXPR
-             || TREE_CODE (arg0) == ROUND_MOD_EXPR)
-         && integer_pow2p (TREE_OPERAND (arg0, 1)))
-       {
-         tree newtype = unsigned_type_for (TREE_TYPE (arg0));
-         tree newmod = fold_build2_loc (loc, TREE_CODE (arg0), newtype,
-                                    fold_convert_loc (loc, newtype,
-                                                      TREE_OPERAND (arg0, 0)),
-                                    fold_convert_loc (loc, newtype,
-                                                      TREE_OPERAND (arg0, 1)));
-
-         return fold_build2_loc (loc, code, type, newmod,
-                             fold_convert_loc (loc, newtype, arg1));
-       }
-
       /* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
         C1 is a valid shift constant, and C2 is a power of two, i.e.
         a single bit.  */
@@ -10834,21 +10743,24 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
                strlen(ptr) != 0   =>  *ptr != 0
         Other cases should reduce to one of these two (or a constant)
         due to the return value of strlen being unsigned.  */
-      if (TREE_CODE (arg0) == CALL_EXPR
-         && integer_zerop (arg1))
+      if (TREE_CODE (arg0) == CALL_EXPR && integer_zerop (arg1))
        {
          tree fndecl = get_callee_fndecl (arg0);
 
          if (fndecl
-             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+             && fndecl_built_in_p (fndecl, BUILT_IN_STRLEN)
              && call_expr_nargs (arg0) == 1
-             && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
+             && (TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0)))
+                 == POINTER_TYPE))
            {
-             tree iref = build_fold_indirect_ref_loc (loc,
-                                                  CALL_EXPR_ARG (arg0, 0));
+             tree ptrtype
+               = build_pointer_type (build_qualified_type (char_type_node,
+                                                           TYPE_QUAL_CONST));
+             tree ptr = fold_convert_loc (loc, ptrtype,
+                                          CALL_EXPR_ARG (arg0, 0));
+             tree iref = build_fold_indirect_ref_loc (loc, ptr);
              return fold_build2_loc (loc, code, type, iref,
-                                 build_int_cst (TREE_TYPE (iref), 0));
+                                     build_int_cst (TREE_TYPE (iref), 0));
            }
        }
 
@@ -11264,6 +11176,100 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
     } /* switch (code) */
 }
 
+/* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
+   ((A & N) + B) & M -> (A + B) & M
+   Similarly if (N & M) == 0,
+   ((A | N) + B) & M -> (A + B) & M
+   and for - instead of + (or unary - instead of +)
+   and/or ^ instead of |.
+   If B is constant and (B & M) == 0, fold into A & M.
+
+   This function is a helper for match.pd patterns.  Return non-NULL
+   type in which the simplified operation should be performed only
+   if any optimization is possible.
+
+   ARG1 is M above, ARG00 is left operand of +/-, if CODE00 is BIT_*_EXPR,
+   then ARG00{0,1} are operands of that bitop, otherwise CODE00 is ERROR_MARK.
+   Similarly for ARG01, CODE01 and ARG01{0,1}, just for the right operand of
+   +/-.  */
+tree
+fold_bit_and_mask (tree type, tree arg1, enum tree_code code,
+                  tree arg00, enum tree_code code00, tree arg000, tree arg001,
+                  tree arg01, enum tree_code code01, tree arg010, tree arg011,
+                  tree *pmop)
+{
+  gcc_assert (TREE_CODE (arg1) == INTEGER_CST);
+  gcc_assert (code == PLUS_EXPR || code == MINUS_EXPR || code == NEGATE_EXPR);
+  wi::tree_to_wide_ref cst1 = wi::to_wide (arg1);
+  if (~cst1 == 0
+      || (cst1 & (cst1 + 1)) != 0
+      || !INTEGRAL_TYPE_P (type)
+      || (!TYPE_OVERFLOW_WRAPS (type)
+         && TREE_CODE (type) != INTEGER_TYPE)
+      || (wi::max_value (type) & cst1) != cst1)
+    return NULL_TREE;
+
+  enum tree_code codes[2] = { code00, code01 };
+  tree arg0xx[4] = { arg000, arg001, arg010, arg011 };
+  int which = 0;
+  wide_int cst0;
+
+  /* Now we know that arg0 is (C + D) or (C - D) or -C and
+     arg1 (M) is == (1LL << cst) - 1.
+     Store C into PMOP[0] and D into PMOP[1].  */
+  pmop[0] = arg00;
+  pmop[1] = arg01;
+  which = code != NEGATE_EXPR;
+
+  for (; which >= 0; which--)
+    switch (codes[which])
+      {
+      case BIT_AND_EXPR:
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+       gcc_assert (TREE_CODE (arg0xx[2 * which + 1]) == INTEGER_CST);
+       cst0 = wi::to_wide (arg0xx[2 * which + 1]) & cst1;
+       if (codes[which] == BIT_AND_EXPR)
+         {
+           if (cst0 != cst1)
+             break;
+         }
+       else if (cst0 != 0)
+         break;
+       /* If C or D is of the form (A & N) where
+          (N & M) == M, or of the form (A | N) or
+          (A ^ N) where (N & M) == 0, replace it with A.  */
+       pmop[which] = arg0xx[2 * which];
+       break;
+      case ERROR_MARK:
+       if (TREE_CODE (pmop[which]) != INTEGER_CST)
+         break;
+       /* If C or D is a N where (N & M) == 0, it can be
+          omitted (replaced with 0).  */
+       if ((code == PLUS_EXPR
+            || (code == MINUS_EXPR && which == 0))
+           && (cst1 & wi::to_wide (pmop[which])) == 0)
+         pmop[which] = build_int_cst (type, 0);
+       /* Similarly, with C - N where (-N & M) == 0.  */
+       if (code == MINUS_EXPR
+           && which == 1
+           && (cst1 & -wi::to_wide (pmop[which])) == 0)
+         pmop[which] = build_int_cst (type, 0);
+       break;
+      default:
+       gcc_unreachable ();
+      }
+
+  /* Only build anything new if we optimized one or both arguments above.  */
+  if (pmop[0] == arg00 && pmop[1] == arg01)
+    return NULL_TREE;
+
+  if (TYPE_OVERFLOW_WRAPS (type))
+    return type;
+  else
+    return unsigned_type_for (type);
+}
+
 /* Used by contains_label_[p1].  */
 
 struct contains_label_data
@@ -11601,10 +11607,16 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          && integer_pow2p (arg1)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
          && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
-                             arg1, OEP_ONLY_CONST))
+                             arg1, OEP_ONLY_CONST)
+         /* operand_equal_p compares just value, not precision, so e.g.
+            arg1 could be 8-bit -128 and be power of two, but BIT_AND_EXPR
+            second operand 32-bit -128, which is not a power of two (or vice
+            versa.  */
+         && integer_pow2p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)))
        return pedantic_non_lvalue_loc (loc,
-                                   fold_convert_loc (loc, type,
-                                                     TREE_OPERAND (arg0, 0)));
+                                       fold_convert_loc (loc, type,
+                                                         TREE_OPERAND (arg0,
+                                                                       0)));
 
       /* Disable the transformations below for vectors, since
         fold_binary_op_with_conditional_arg may undo them immediately,
@@ -12100,7 +12112,7 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
 {
   const tree_node **slot;
   enum tree_code code;
-  union tree_node buf;
+  union tree_node *buf;
   int i, len;
 
  recursive_label:
@@ -12115,10 +12127,13 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
       && HAS_DECL_ASSEMBLER_NAME_P (expr))
     {
       /* Allow DECL_ASSEMBLER_NAME and symtab_node to be modified.  */
-      memcpy ((char *) &buf, expr, tree_size (expr));
-      SET_DECL_ASSEMBLER_NAME ((tree)&buf, NULL);
-      buf.decl_with_vis.symtab_node = NULL;
-      expr = (tree) &buf;
+      size_t sz = tree_size (expr);
+      buf = XALLOCAVAR (union tree_node, sz);
+      memcpy ((char *) buf, expr, sz);
+      SET_DECL_ASSEMBLER_NAME ((tree) buf, NULL);
+      buf->decl_with_vis.symtab_node = NULL;
+      buf->base.nowarning_flag = 0;
+      expr = (tree) buf;
     }
   else if (TREE_CODE_CLASS (code) == tcc_type
           && (TYPE_POINTER_TO (expr)
@@ -12130,8 +12145,10 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
     {
       /* Allow these fields to be modified.  */
       tree tmp;
-      memcpy ((char *) &buf, expr, tree_size (expr));
-      expr = tmp = (tree) &buf;
+      size_t sz = tree_size (expr);
+      buf = XALLOCAVAR (union tree_node, sz);
+      memcpy ((char *) buf, expr, sz);
+      expr = tmp = (tree) buf;
       TYPE_CONTAINS_PLACEHOLDER_INTERNAL (tmp) = 0;
       TYPE_POINTER_TO (tmp) = NULL;
       TYPE_REFERENCE_TO (tmp) = NULL;
@@ -12143,6 +12160,16 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
          TYPE_CACHED_VALUES (tmp) = NULL;
        }
     }
+  else if (TREE_NO_WARNING (expr) && (DECL_P (expr) || EXPR_P (expr)))
+    {
+      /* Allow TREE_NO_WARNING to be set.  Perhaps we shouldn't allow that
+        and change builtins.c etc. instead - see PR89543.  */
+      size_t sz = tree_size (expr);
+      buf = XALLOCAVAR (union tree_node, sz);
+      memcpy ((char *) buf, expr, sz);
+      buf->base.nowarning_flag = 0;
+      expr = (tree) buf;
+    }
   md5_process_bytes (expr, tree_size (expr), ctx);
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
@@ -13683,6 +13710,8 @@ integer_valued_real_p (tree t, int depth)
   if (t == error_mark_node)
     return false;
 
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
   tree_code code = TREE_CODE (t);
   switch (TREE_CODE_CLASS (code))
     {
@@ -13773,7 +13802,7 @@ fold_read_from_constant_string (tree exp)
       location_t loc = EXPR_LOCATION (exp);
 
       if (TREE_CODE (exp) == INDIRECT_REF)
-       string = string_constant (exp1, &index);
+       string = string_constant (exp1, &index, NULL, NULL);
       else
        {
          tree low_bound = array_ref_low_bound (exp);
@@ -13841,7 +13870,7 @@ fold_negate_const (tree arg0, tree type)
     default:
       if (poly_int_tree_p (arg0))
        {
-         bool overflow;
+         wi::overflow_type overflow;
          poly_wide_int res = wi::neg (wi::to_poly_wide (arg0), &overflow);
          t = force_fit_type (type, res, 1,
                              (overflow && ! TYPE_UNSIGNED (type))
@@ -13872,7 +13901,7 @@ fold_abs_const (tree arg0, tree type)
         /* If the value is unsigned or non-negative, then the absolute value
           is the same as the ordinary value.  */
        wide_int val = wi::to_wide (arg0);
-       bool overflow = false;
+       wi::overflow_type overflow = wi::OVF_NONE;
        if (!wi::neg_p (val, TYPE_SIGN (TREE_TYPE (arg0))))
          ;
 
@@ -14567,21 +14596,23 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
                          ptr, size_int (off));
 }
 
-/* Return a char pointer for a C string if it is a string constant
-   or sum of string constant and integer constant.  We only support
-   string constants properly terminated with '\0' character.
-   If STRLEN is a valid pointer, length (including terminating character)
-   of returned string is stored to the argument.  */
+/* Return a pointer P to a NUL-terminated string representing the sequence
+   of constant characters referred to by SRC (or a subsequence of such
+   characters within it if SRC is a reference to a string plus some
+   constant offset).  If STRLEN is non-null, store the number of bytes
+   in the string constant including the terminating NUL char.  *STRLEN is
+   typically strlen(P) + 1 in the absence of embedded NUL characters.  */
 
 const char *
-c_getstr (tree src, unsigned HOST_WIDE_INT *strlen)
+c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */)
 {
   tree offset_node;
+  tree mem_size;
 
   if (strlen)
     *strlen = 0;
 
-  src = string_constant (src, &offset_node);
+  src = string_constant (src, &offset_node, &mem_size, NULL);
   if (src == 0)
     return NULL;
 
@@ -14594,18 +14625,49 @@ c_getstr (tree src, unsigned HOST_WIDE_INT *strlen)
        offset = tree_to_uhwi (offset_node);
     }
 
+  if (!tree_fits_uhwi_p (mem_size))
+    return NULL;
+
+  /* STRING_LENGTH is the size of the string literal, including any
+     embedded NULs.  STRING_SIZE is the size of the array the string
+     literal is stored in.  */
   unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src);
+  unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size);
+
+  /* Ideally this would turn into a gcc_checking_assert over time.  */
+  if (string_length > string_size)
+    string_length = string_size;
+
   const char *string = TREE_STRING_POINTER (src);
 
-  /* Support only properly null-terminated strings.  */
+  /* Ideally this would turn into a gcc_checking_assert over time.  */
+  if (string_length > string_size)
+    string_length = string_size;
+
   if (string_length == 0
-      || string[string_length - 1] != '\0'
-      || offset >= string_length)
+      || offset >= string_size)
     return NULL;
 
   if (strlen)
-    *strlen = string_length - offset;
-  return string + offset;
+    {
+      /* Compute and store the length of the substring at OFFSET.
+        All offsets past the initial length refer to null strings.  */
+      if (offset < string_length)
+       *strlen = string_length - offset;
+      else
+       *strlen = 1;
+    }
+  else
+    {
+      tree eltype = TREE_TYPE (TREE_TYPE (src));
+      /* Support only properly NUL-terminated single byte strings.  */
+      if (tree_to_uhwi (TYPE_SIZE_UNIT (eltype)) != 1)
+       return NULL;
+      if (string[string_length - 1] != '\0')
+       return NULL;
+    }
+
+  return offset < string_length ? string + offset : "";
 }
 
 /* Given a tree T, compute which bits in T may be nonzero.  */