OSDN Git Service

PR debug/42897
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index d754bee..292b89f 100644 (file)
@@ -206,15 +206,9 @@ fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
 {
   unsigned HOST_WIDE_INT low0 = l1;
   HOST_WIDE_INT high0 = h1;
-  unsigned int prec;
+  unsigned int prec = TYPE_PRECISION (type);
   int sign_extended_type;
 
-  if (POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
-    prec = POINTER_SIZE;
-  else
-    prec = TYPE_PRECISION (type);
-
   /* Size types *are* sign extended.  */
   sign_extended_type = (!TYPE_UNSIGNED (type)
                        || (TREE_CODE (type) == INTEGER_TYPE
@@ -332,13 +326,17 @@ add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
   HOST_WIDE_INT h;
 
   l = l1 + l2;
-  h = h1 + h2 + (l < l1);
+  h = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) h1
+                      + (unsigned HOST_WIDE_INT) h2
+                      + (l < l1));
 
   *lv = l;
   *hv = h;
 
   if (unsigned_p)
-    return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1;
+    return ((unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1
+           || (h == h1
+               && l < l1));
   else
     return OVERFLOW_SUM_SIGN (h1, h2, h);
 }
@@ -887,22 +885,18 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
   HOST_WIDE_INT int1h, int2h;
   unsigned HOST_WIDE_INT quol, reml;
   HOST_WIDE_INT quoh, remh;
-  tree type = TREE_TYPE (arg1);
-  int uns = TYPE_UNSIGNED (type);
+  int uns;
+
+  /* The sign of the division is according to operand two, that
+     does the correct thing for POINTER_PLUS_EXPR where we want
+     a signed division.  */
+  uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
+  if (TREE_CODE (TREE_TYPE (arg2)) == INTEGER_TYPE
+      && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
+    uns = false;
 
   int1l = TREE_INT_CST_LOW (arg1);
   int1h = TREE_INT_CST_HIGH (arg1);
-  /* &obj[0] + -128 really should be compiled as &obj[-8] rather than
-     &obj[some_exotic_number].  */
-  if (POINTER_TYPE_P (type))
-    {
-      uns = false;
-      type = signed_type_for (type);
-      fit_double_type (int1l, int1h, &int1l, &int1h,
-                      type);
-    }
-  else
-    fit_double_type (int1l, int1h, &int1l, &int1h, type);
   int2l = TREE_INT_CST_LOW (arg2);
   int2h = TREE_INT_CST_HIGH (arg2);
 
@@ -911,7 +905,7 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
   if (remh != 0 || reml != 0)
     return NULL_TREE;
 
-  return build_int_cst_wide (type, quol, quoh);
+  return build_int_cst_wide (TREE_TYPE (arg1), quol, quoh);
 }
 \f
 /* This is nonzero if we should defer warnings about undefined
@@ -1070,7 +1064,7 @@ negate_mathfn_p (enum built_in_function code)
     CASE_FLT_FN (BUILT_IN_NEARBYINT):
     CASE_FLT_FN (BUILT_IN_RINT):
       return !flag_rounding_math;
-    
+
     default:
       break;
     }
@@ -1135,10 +1129,14 @@ negate_expr_p (tree t)
              && TYPE_OVERFLOW_WRAPS (type));
 
     case FIXED_CST:
-    case REAL_CST:
     case NEGATE_EXPR:
       return true;
 
+    case REAL_CST:
+      /* We want to canonicalize to positive real constants.  Pretend
+         that only negative ones can be easily negated.  */
+      return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
+
     case COMPLEX_CST:
       return negate_expr_p (TREE_REALPART (t))
             && negate_expr_p (TREE_IMAGPART (t));
@@ -1250,7 +1248,7 @@ fold_negate_expr (location_t loc, tree t)
         return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0),
                             build_int_cst (type, 1));
       break;
-      
+
     case INTEGER_CST:
       tem = fold_negate_const (t, type);
       if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
@@ -1288,7 +1286,7 @@ fold_negate_expr (location_t loc, tree t)
                            fold_negate_expr (loc, TREE_OPERAND (t, 0)),
                            fold_negate_expr (loc, TREE_OPERAND (t, 1)));
       break;
-      
+
     case CONJ_EXPR:
       if (negate_expr_p (t))
        return fold_build1_loc (loc, CONJ_EXPR, type,
@@ -1972,12 +1970,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        case MULT_EXPR:
-#ifdef HAVE_mpc
          if (COMPLEX_FLOAT_TYPE_P (type))
            return do_mpc_arg2 (arg1, arg2, type,
                                /* do_nonfinite= */ folding_initializer,
                                mpc_mul);
-#endif
 
          real = const_binop (MINUS_EXPR,
                              const_binop (MULT_EXPR, r1, r2, notrunc),
@@ -1990,14 +1986,11 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        case RDIV_EXPR:
-#ifdef HAVE_mpc
          if (COMPLEX_FLOAT_TYPE_P (type))
            return do_mpc_arg2 (arg1, arg2, type,
                                 /* do_nonfinite= */ folding_initializer,
                                mpc_div);
          /* Fallthru ... */
-#endif
-
        case TRUNC_DIV_EXPR:
        case CEIL_DIV_EXPR:
        case FLOOR_DIV_EXPR:
@@ -2037,10 +2030,10 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
               Expand complex division to scalars, modified algorithm to minimize
               overflow with wide input ranges.  */
-           tree inner_type = TREE_TYPE (type);
-           tree absr2 = fold_build1 (ABS_EXPR, inner_type, r2);
-           tree absi2 = fold_build1 (ABS_EXPR, inner_type, i2);
-           tree compare = fold_build2 (LT_EXPR, boolean_type_node, absr2, absi2);
+           tree compare = fold_build2 (LT_EXPR, boolean_type_node,
+                                       fold_abs_const (r2, TREE_TYPE (type)),
+                                       fold_abs_const (i2, TREE_TYPE (type)));
+
            if (integer_nonzerop (compare))
              {
                /* In the TRUE branch, we compute
@@ -2050,17 +2043,18 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                   ti = (ai * ratio) - ar;
                   tr = tr / div;
                   ti = ti / div;  */
-               tree ratio = fold_build2 (code, inner_type, r2, i2);
-               tree div = fold_build2 (PLUS_EXPR, inner_type, i2,
-                                       fold_build2 (MULT_EXPR, inner_type,
-                                                    r2, ratio));
-               real = fold_build2 (MULT_EXPR, inner_type, r1, ratio);
-               real = fold_build2 (PLUS_EXPR, inner_type, real, i1);
-               real = fold_build2 (code, inner_type, real, div);
-
-               imag = fold_build2 (MULT_EXPR, inner_type, i1, ratio);
-               imag = fold_build2 (MINUS_EXPR, inner_type, imag, r1);
-               imag = fold_build2 (code, inner_type, imag, div);
+               tree ratio = const_binop (code, r2, i2, notrunc);
+               tree div = const_binop (PLUS_EXPR, i2,
+                                       const_binop (MULT_EXPR, r2, ratio,
+                                                    notrunc),
+                                       notrunc);
+               real = const_binop (MULT_EXPR, r1, ratio, notrunc);
+               real = const_binop (PLUS_EXPR, real, i1, notrunc);
+               real = const_binop (code, real, div, notrunc);
+
+               imag = const_binop (MULT_EXPR, i1, ratio, notrunc);
+               imag = const_binop (MINUS_EXPR, imag, r1, notrunc);
+               imag = const_binop (code, imag, div, notrunc);
              }
            else
              {
@@ -2071,18 +2065,19 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                   ti = b - (a * ratio);
                   tr = tr / div;
                   ti = ti / div;  */
-               tree ratio = fold_build2 (code, inner_type, i2, r2);
-               tree div = fold_build2 (PLUS_EXPR, inner_type, r2,
-                                        fold_build2 (MULT_EXPR, inner_type,
-                                                     i2, ratio));
-
-               real = fold_build2 (MULT_EXPR, inner_type, i1, ratio);
-               real = fold_build2 (PLUS_EXPR, inner_type, real, r1);
-               real = fold_build2 (code, inner_type, real, div);
-
-               imag = fold_build2 (MULT_EXPR, inner_type, r1, ratio);
-               imag = fold_build2 (MINUS_EXPR, inner_type, i1, imag);
-               imag = fold_build2 (code, inner_type, imag, div);
+               tree ratio = const_binop (code, i2, r2, notrunc);
+               tree div = const_binop (PLUS_EXPR, r2,
+                                        const_binop (MULT_EXPR, i2, ratio,
+                                                    notrunc),
+                                       notrunc);
+
+               real = const_binop (MULT_EXPR, i1, ratio, notrunc);
+               real = const_binop (PLUS_EXPR, real, r1, notrunc);
+               real = const_binop (code, real, div, notrunc);
+
+               imag = const_binop (MULT_EXPR, r1, ratio, notrunc);
+               imag = const_binop (MINUS_EXPR, i1, imag, notrunc);
+               imag = const_binop (code, imag, div, notrunc);
              }
          }
          break;
@@ -2100,17 +2095,17 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       tree type = TREE_TYPE(arg1);
       int count = TYPE_VECTOR_SUBPARTS (type), i;
       tree elements1, elements2, list = NULL_TREE;
-      
+
       if(TREE_CODE(arg2) != VECTOR_CST)
         return NULL_TREE;
-        
+
       elements1 = TREE_VECTOR_CST_ELTS (arg1);
       elements2 = TREE_VECTOR_CST_ELTS (arg2);
 
       for (i = 0; i < count; i++)
        {
           tree elem1, elem2, elem;
-          
+
           /* The trailing elements can be empty and should be treated as 0 */
           if(!elements1)
             elem1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
@@ -2118,8 +2113,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
             {
               elem1 = TREE_VALUE(elements1);
               elements1 = TREE_CHAIN (elements1);
-            }  
-            
+            }
+
           if(!elements2)
             elem2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
           else
@@ -2127,17 +2122,17 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
               elem2 = TREE_VALUE(elements2);
               elements2 = TREE_CHAIN (elements2);
             }
-              
+
           elem = const_binop (code, elem1, elem2, notrunc);
-          
+
           /* It is possible that const_binop cannot handle the given
             code and return NULL_TREE */
           if(elem == NULL_TREE)
             return NULL_TREE;
-          
+
           list = tree_cons (NULL_TREE, elem, list);
        }
-      return build_vector(type, nreverse(list));  
+      return build_vector(type, nreverse(list));
     }
   return NULL_TREE;
 }
@@ -2577,7 +2572,7 @@ build_zero_vector (tree type)
 
   elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
   units = TYPE_VECTOR_SUBPARTS (type);
-  
+
   list = NULL_TREE;
   for (i = 0; i < units; i++)
     list = tree_cons (NULL_TREE, elem, list);
@@ -2647,8 +2642,16 @@ fold_convert_loc (location_t loc, tree type, tree arg)
 
   switch (TREE_CODE (type))
     {
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      /* Handle conversions between pointers to different address spaces.  */
+      if (POINTER_TYPE_P (orig)
+         && (TYPE_ADDR_SPACE (TREE_TYPE (type))
+             != TYPE_ADDR_SPACE (TREE_TYPE (orig))))
+       return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, arg);
+      /* fall through */
+
     case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
-    case POINTER_TYPE: case REFERENCE_TYPE:
     case OFFSET_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
@@ -2830,8 +2833,6 @@ maybe_lvalue_p (const_tree x)
   case TARGET_EXPR:
   case COND_EXPR:
   case BIND_EXPR:
-  case MIN_EXPR:
-  case MAX_EXPR:
     break;
 
   default:
@@ -3164,7 +3165,9 @@ int
 operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 {
   /* If either is ERROR_MARK, they aren't equal.  */
-  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK
+      || TREE_TYPE (arg0) == error_mark_node
+      || TREE_TYPE (arg1) == error_mark_node)
     return 0;
 
   /* Check equality of integer constants before bailing out due to
@@ -3181,6 +3184,12 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       || POINTER_TYPE_P (TREE_TYPE (arg0)) != POINTER_TYPE_P (TREE_TYPE (arg1)))
     return 0;
 
+  /* We cannot consider pointers to different address space equal.  */
+  if (POINTER_TYPE_P (TREE_TYPE (arg0)) && POINTER_TYPE_P (TREE_TYPE (arg1))
+      && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
+         != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
+    return 0;
+
   /* If both types don't have the same precision, then it is not safe
      to strip NOPs.  */
   if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1)))
@@ -3242,7 +3251,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                   TREE_REAL_CST (arg1)))
          return 1;
 
-       
+
        if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0))))
          {
            /* If we do not distinguish between signed and unsigned zero,
@@ -3401,7 +3410,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
        case COND_EXPR:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
-         
+
        default:
          return 0;
        }
@@ -4118,7 +4127,7 @@ make_bit_field_ref (location_t loc, tree inner, tree type,
       tree size = TYPE_SIZE (TREE_TYPE (inner));
       if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
           || POINTER_TYPE_P (TREE_TYPE (inner)))
-         && host_integerp (size, 0) 
+         && host_integerp (size, 0)
          && tree_low_cst (size, 0) == bitsize)
        return fold_convert_loc (loc, type, inner);
     }
@@ -5528,7 +5537,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
            tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
                                   fold_convert_loc (loc, TREE_TYPE (arg00),
                                                     arg2));
-           return pedantic_non_lvalue_loc (loc, 
+           return pedantic_non_lvalue_loc (loc,
                                            fold_convert_loc (loc, type, tem));
          }
        break;
@@ -6512,7 +6521,19 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       /* If this was a subtraction, negate OP1 and set it to be an addition.
         This simplifies the logic below.  */
       if (tcode == MINUS_EXPR)
-       tcode = PLUS_EXPR, op1 = negate_expr (op1);
+       {
+         tcode = PLUS_EXPR, op1 = negate_expr (op1);
+         /* If OP1 was not easily negatable, the constant may be OP0.  */
+         if (TREE_CODE (op0) == INTEGER_CST)
+           {
+             tree tem = op0;
+             op0 = op1;
+             op1 = tem;
+             tem = t1;
+             t1 = t2;
+             t2 = tem;
+           }
+       }
 
       if (TREE_CODE (op1) != INTEGER_CST)
        break;
@@ -7251,7 +7272,7 @@ fold_single_bit_test (location_t loc, enum tree_code code,
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
 #ifdef LOAD_EXTEND_OP
-      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND 
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
                      && !flag_syntax_only) ? 0 : 1;
 #else
       ops_unsigned = 1;
@@ -7536,7 +7557,7 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
 
       STRIP_NOPS (arg0);
       STRIP_NOPS (arg1);
-  
+
       if (TREE_CODE (arg0) == INTEGER_CST)
         {
           s = arg0;
@@ -7566,13 +7587,16 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
     {
       if (TREE_CODE (ref) == ARRAY_REF)
        {
+         tree domain;
+
          /* Remember if this was a multi-dimensional array.  */
          if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
            mdim = true;
 
-         itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
-         if (! itype)
+         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+         if (! domain)
            continue;
+         itype = TREE_TYPE (domain);
 
          step = array_ref_element_size (ref);
          if (TREE_CODE (step) != INTEGER_CST)
@@ -7599,18 +7623,17 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
              tree tmp;
 
              if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
-                 || !INTEGRAL_TYPE_P (itype)
-                 || !TYPE_MAX_VALUE (itype)
-                 || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
+                 || !TYPE_MAX_VALUE (domain)
+                 || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
                continue;
 
              tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
-                                fold_convert_loc (loc, itype,
-                                                  TREE_OPERAND (ref, 1)),
-                                fold_convert_loc (loc, itype, delta));
+                                    fold_convert_loc (loc, itype,
+                                                      TREE_OPERAND (ref, 1)),
+                                    fold_convert_loc (loc, itype, delta));
              if (!tmp
                  || TREE_CODE (tmp) != INTEGER_CST
-                 || tree_int_cst_lt (TYPE_MAX_VALUE (itype), tmp))
+                 || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
                continue;
            }
 
@@ -8425,7 +8448,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
     case FIX_TRUNC_EXPR:
       if (TREE_TYPE (op0) == type)
        return op0;
-      
+
       /* If we have (type) (a CMP b) and type is an integral type, return
          new expression involving the new type.  */
       if (COMPARISON_CLASS_P (op0) && INTEGRAL_TYPE_P (type))
@@ -8672,6 +8695,11 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
       tem = fold_convert_const (code, type, op0);
       return tem ? tem : NULL_TREE;
 
+    case ADDR_SPACE_CONVERT_EXPR:
+      if (integer_zerop (arg0))
+       return fold_convert_const (code, type, arg0);
+      return NULL_TREE;
+
     case FIXED_CONVERT_EXPR:
       tem = fold_convert_const (code, type, arg0);
       return tem ? tem : NULL_TREE;
@@ -8924,6 +8952,19 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
        }
       return NULL_TREE;
 
+    case INDIRECT_REF:
+      /* Fold *&X to X if X is an lvalue.  */
+      if (TREE_CODE (op0) == ADDR_EXPR)
+       {
+         tree op00 = TREE_OPERAND (op0, 0);
+         if ((TREE_CODE (op00) == VAR_DECL
+              || TREE_CODE (op00) == PARM_DECL
+              || TREE_CODE (op00) == RESULT_DECL)
+             && !TREE_READONLY (op00))
+           return op00;
+       }
+      return NULL_TREE;
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -9352,7 +9393,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
              && (code == EQ_EXPR
                  || code == NE_EXPR
                  || POINTER_TYPE_OVERFLOW_UNDEFINED))
-               
+
            {
              if (code != EQ_EXPR
                  && code != NE_EXPR
@@ -9627,7 +9668,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 
       /* Likewise, we can simplify a comparison of a real constant with
          a MINUS_EXPR whose first operand is also a real constant, i.e.
-         (c1 - x) < c2 becomes x > c1-c2.  Reordering is allowed on 
+         (c1 - x) < c2 becomes x > c1-c2.  Reordering is allowed on
          floating-point types only if -fassociative-math is set.  */
       if (flag_associative_math
          && TREE_CODE (arg1) == REAL_CST
@@ -9951,7 +9992,7 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
       tree op0, op1;
       unsigned HOST_WIDE_INT modulus;
       enum tree_code inner_code;
-      
+
       op0 = TREE_OPERAND (expr, 0);
       STRIP_NOPS (op0);
       modulus = get_pointer_modulus_and_residue (op0, residue,
@@ -9971,7 +10012,7 @@ get_pointer_modulus_and_residue (tree expr, unsigned HOST_WIDE_INT *residue,
          if (TREE_CODE (op1) == INTEGER_CST)
            {
              unsigned HOST_WIDE_INT align;
-             
+
              /* Compute the greatest power-of-2 divisor of op1.  */
              align = TREE_INT_CST_LOW (op1);
              align &= -align;
@@ -10124,7 +10165,6 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type,
                             fold_convert_loc (loc, TREE_TYPE (op0),
                                               TREE_OPERAND (arg0, 1)), op1);
-         protected_set_expr_location (tem, loc);
          tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), tem);
          goto fold_binary_exit;
        }
@@ -10134,7 +10174,6 @@ fold_binary_loc (location_t loc,
          tem = fold_build2_loc (loc, code, type, op0,
                             fold_convert_loc (loc, TREE_TYPE (op1),
                                               TREE_OPERAND (arg1, 1)));
-         protected_set_expr_location (tem, loc);
          tem = build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), tem);
          goto fold_binary_exit;
        }
@@ -10142,7 +10181,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
          tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
-                                                    arg0, arg1, 
+                                                    arg0, arg1,
                                                     /*cond_first_p=*/1);
          if (tem != NULL_TREE)
            return tem;
@@ -10151,7 +10190,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
          tem = fold_binary_op_with_conditional_arg (loc, code, type, op0, op1,
-                                                    arg1, arg0, 
+                                                    arg1, arg0,
                                                     /*cond_first_p=*/0);
          if (tem != NULL_TREE)
            return tem;
@@ -10433,7 +10472,7 @@ fold_binary_loc (location_t loc,
            return fold_build2_loc (loc, MULT_EXPR, type, arg0,
                                build_real (type, dconst2));
 
-          /* Convert a + (b*c + d*e) into (a + b*c) + d*e.  
+          /* Convert a + (b*c + d*e) into (a + b*c) + d*e.
              We associate floats only if the user has specified
              -fassociative-math.  */
           if (flag_associative_math
@@ -10450,7 +10489,7 @@ fold_binary_loc (location_t loc,
                   return fold_build2_loc (loc, PLUS_EXPR, type, tree0, tree11);
                 }
             }
-          /* Convert (b*c + d*e) + a into b*c + (d*e +a).  
+          /* Convert (b*c + d*e) + a into b*c + (d*e +a).
              We associate floats only if the user has specified
              -fassociative-math.  */
           if (flag_associative_math
@@ -10886,7 +10925,7 @@ fold_binary_loc (location_t loc,
              tree diff = build2 (MINUS_EXPR, type, op0, op1);
              return fold_build2_loc (loc, MULT_EXPR, type, diff,
                                  fold_convert_loc (loc, type, esz));
-                                 
+
            }
        }
 
@@ -11265,7 +11304,7 @@ fold_binary_loc (location_t loc,
 
          if (width > HOST_BITS_PER_WIDE_INT)
            {
-             mhi = (unsigned HOST_WIDE_INT) -1 
+             mhi = (unsigned HOST_WIDE_INT) -1
                    >> (2 * HOST_BITS_PER_WIDE_INT - width);
              mlo = -1;
            }
@@ -11452,7 +11491,7 @@ fold_binary_loc (location_t loc,
                            fold_convert_loc (loc, type, t1));
          return t1;
        }
-       
+
       /* Convert ~X ^ ~Y to X ^ Y.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && TREE_CODE (arg1) == BIT_NOT_EXPR)
@@ -11482,7 +11521,7 @@ fold_binary_loc (location_t loc,
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
          tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type, 
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
                              fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
                              fold_convert_loc (loc, type, arg1));
        }
@@ -11601,7 +11640,7 @@ fold_binary_loc (location_t loc,
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
        {
          tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-         return fold_build2_loc (loc, BIT_AND_EXPR, type, 
+         return fold_build2_loc (loc, BIT_AND_EXPR, type,
                              fold_build1_loc (loc, BIT_NOT_EXPR, type, tem),
                              fold_convert_loc (loc, type, arg1));
        }
@@ -11866,7 +11905,7 @@ fold_binary_loc (location_t loc,
                }
            }
        }
-      /* Convert A/B/C to A/(B*C).  */ 
+      /* Convert A/B/C to A/(B*C).  */
       if (flag_reciprocal_math
          && TREE_CODE (arg0) == RDIV_EXPR)
        return fold_build2_loc (loc, RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -12604,6 +12643,11 @@ fold_binary_loc (location_t loc,
         return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
                            fold_convert_loc (loc, type, arg0));
 
+      /* !exp != 0 becomes !exp */
+      if (TREE_CODE (arg0) == TRUTH_NOT_EXPR && integer_zerop (arg1)
+         && code == NE_EXPR)
+        return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+
       /* If this is an equality comparison of the address of two non-weak,
         unaliased symbols neither of which are extern (since we do not
         have access to attributes for externs), then we know the result.  */
@@ -14194,7 +14238,7 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
   enum tree_code code;
   union tree_node buf;
   int i, len;
-  
+
 recursive_label:
 
   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
@@ -14304,7 +14348,7 @@ recursive_label:
        }
       if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
        fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
-         
+
       if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON))
        {
          fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
@@ -14349,7 +14393,7 @@ debug_fold_checksum (const_tree t)
   unsigned char checksum[16];
   struct md5_ctx ctx;
   htab_t ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (t, &ctx, ht);
   md5_finish_ctx (&ctx, checksum);
@@ -14384,14 +14428,14 @@ fold_build1_stat_loc (location_t loc,
   md5_finish_ctx (&ctx, checksum_before);
   htab_empty (ht);
 #endif
-  
+
   tem = fold_unary_loc (loc, code, type, op0);
   if (!tem)
     {
       tem = build1_stat (code, type, op0 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-  
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14442,7 +14486,7 @@ fold_build2_stat_loc (location_t loc,
       tem = build2_stat (code, type, op0, op1 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-  
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14451,7 +14495,7 @@ fold_build2_stat_loc (location_t loc,
 
   if (memcmp (checksum_before_op0, checksum_after_op0, 16))
     fold_check_failed (op0, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op1, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op1);
@@ -14507,7 +14551,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
       tem =  build3_stat (code, type, op0, op1, op2 PASS_MEM_STAT);
       SET_EXPR_LOCATION (tem, loc);
     }
-      
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (op0, &ctx, ht);
@@ -14516,7 +14560,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
 
   if (memcmp (checksum_before_op0, checksum_after_op0, 16))
     fold_check_failed (op0, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op1, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op1);
@@ -14524,7 +14568,7 @@ fold_build3_stat_loc (location_t loc, enum tree_code code, tree type,
 
   if (memcmp (checksum_before_op1, checksum_after_op1, 16))
     fold_check_failed (op1, tem);
-  
+
   md5_init_ctx (&ctx);
   fold_checksum_tree (op2, &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_op2);
@@ -14569,7 +14613,7 @@ fold_build_call_array_loc (location_t loc, tree type, tree fn,
 #endif
 
   tem = fold_builtin_call_array (loc, type, fn, nargs, argarray);
-      
+
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
   fold_checksum_tree (fn, &ctx, ht);
@@ -14578,7 +14622,7 @@ fold_build_call_array_loc (location_t loc, tree type, tree fn,
 
   if (memcmp (checksum_before_fn, checksum_after_fn, 16))
     fold_check_failed (fn, tem);
-  
+
   md5_init_ctx (&ctx);
   for (i = 0; i < nargs; i++)
     fold_checksum_tree (argarray[i], &ctx, ht);
@@ -14924,10 +14968,10 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
          && (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
          && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
        {
-         tree inner0 = (TREE_CODE (op0) == NOP_EXPR) 
+         tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
            ? TREE_TYPE (TREE_OPERAND (op0, 0))
            : TREE_TYPE (op0);
-         tree inner1 = (TREE_CODE (op1) == NOP_EXPR) 
+         tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
            ? TREE_TYPE (TREE_OPERAND (op1, 0))
            : TREE_TYPE (op1);
 
@@ -15975,7 +16019,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
       if (!TREE_SIDE_EFFECTS (op))
         return expr;
     }
-  
+
   return build1 (CLEANUP_POINT_EXPR, type, expr);
 }
 
@@ -16039,17 +16083,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
   /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
-    { 
+    {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
       tree op00type;
-      
+
       STRIP_NOPS (op00);
       op00type = TREE_TYPE (op00);
       if (TREE_CODE (op00) == ADDR_EXPR
           && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
           && type == TREE_TYPE (TREE_TYPE (op00type)))
-       { 
+       {
          HOST_WIDE_INT offset = tree_low_cst (op01, 0);
          tree part_width = TYPE_SIZE (type);
          unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
@@ -16060,7 +16104,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
            return fold_build3_loc (loc,
                                BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
                                part_width, index);
-        
+
        }
     }
 
@@ -16085,7 +16129,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
                                TREE_OPERAND (op00, 0));
        }
     }
-  
+
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
       && type == TREE_TYPE (TREE_TYPE (subtype)))
@@ -16409,7 +16453,7 @@ fold_strip_sign_ops (tree exp)
       if (arg1)
        return fold_build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (exp), arg0, arg1);
       break;
-      
+
     case COND_EXPR:
       arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
       arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 2));
@@ -16419,7 +16463,7 @@ fold_strip_sign_ops (tree exp)
                            arg0 ? arg0 : TREE_OPERAND (exp, 1),
                            arg1 ? arg1 : TREE_OPERAND (exp, 2));
       break;
-      
+
     case CALL_EXPR:
       {
        const enum built_in_function fcode = builtin_mathfn_code (exp);