Index: gcc/params.def
===================================================================
--- gcc/params.def	2015-10-05 20:45:49.164957708 +0100
+++ gcc/params.def	2015-10-08 10:59:12.904576852 +0100
@@ -1152,6 +1152,12 @@ DEFPARAM (PARAM_PARLOOPS_CHUNK_SIZE,
 	  "parloops-chunk-size",
 	  "Chunk size of omp schedule for loops parallelized by parloops",
 	  0, 0, 0)
+
+DEFPARAM (PARAM_MAX_SSA_NAME_QUERY_DEPTH,
+	  "max-ssa-name-query-depth",
+	  "Maximum recursion depth allowed when querying a property of an"
+	  " SSA name",
+	  2, 1, 0)
 /*
 
 Local variables:
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	2015-10-07 09:07:20.758346426 +0100
+++ gcc/doc/invoke.texi	2015-10-08 10:59:12.904576852 +0100
@@ -11132,6 +11132,10 @@ automaton.  The default is 50.
 Chunk size of omp schedule for loops parallelized by parloops.  The default
 is 0.
 
+@item max-ssa-name-query-depth
+Maximum depth of recursion when querying properties of SSA names in things
+like fold routines.  One level of recursion corresponds to following a
+use-def chain.
 @end table
 @end table
 
Index: gcc/fold-const.h
===================================================================
--- gcc/fold-const.h	2015-09-25 12:49:13.080824131 +0100
+++ gcc/fold-const.h	2015-10-08 10:59:12.904576852 +0100
@@ -132,11 +132,13 @@ extern bool tree_unary_nonzero_warnv_p (
 extern bool tree_binary_nonzero_warnv_p (enum tree_code, tree, tree, tree op1,
                                          bool *);
 extern bool tree_single_nonzero_warnv_p (tree, bool *);
-extern bool tree_unary_nonnegative_warnv_p (enum tree_code, tree, tree, bool *);
+extern bool tree_unary_nonnegative_warnv_p (enum tree_code, tree, tree,
+					    bool *, int);
 extern bool tree_binary_nonnegative_warnv_p (enum tree_code, tree, tree, tree,
-                                             bool *);
-extern bool tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
-extern bool tree_call_nonnegative_warnv_p (tree, tree, tree, tree, bool *);
+					     bool *, int);
+extern bool tree_single_nonnegative_warnv_p (tree, bool *, int);
+extern bool tree_call_nonnegative_warnv_p (tree, tree, tree, tree, bool *,
+					   int);
 
 extern bool fold_real_zero_addition_p (const_tree, const_tree, int);
 extern tree combine_comparisons (location_t, enum tree_code, enum tree_code,
@@ -160,7 +162,7 @@ #define non_lvalue(T) non_lvalue_loc (UN
 extern tree non_lvalue_loc (location_t, tree);
 
 extern bool tree_expr_nonnegative_p (tree);
-extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
+extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
 extern tree make_range (tree, int *, tree *, tree *, bool *);
 extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
 			     tree *, tree *, int *, bool *);
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2015-10-05 12:31:58.565944573 +0100
+++ gcc/fold-const.c	2015-10-08 10:59:12.904576852 +0100
@@ -77,6 +77,8 @@ Software Foundation; either version 3, o
 #include "cgraph.h"
 #include "generic-match.h"
 #include "optabs-query.h"
+#include "gimple-fold.h"
+#include "params.h"
 
 #ifndef LOAD_EXTEND_OP
 #define LOAD_EXTEND_OP(M) UNKNOWN
@@ -12749,6 +12751,12 @@ multiple_of_p (tree type, const_tree top
     }
 }
 
+#define tree_expr_nonnegative_warnv_p(X, Y) \
+  _Pragma ("GCC error \"Use RECURSE for recursive calls\"") 0
+
+#define RECURSE(X) \
+  ((tree_expr_nonnegative_warnv_p) (X, strict_overflow_p, depth + 1))
+
 /* Return true if CODE or TYPE is known to be non-negative. */
 
 static bool
@@ -12765,11 +12773,11 @@ tree_simple_nonnegative_warnv_p (enum tr
 /* Return true if (CODE OP0) is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 bool
 tree_unary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
-				bool *strict_overflow_p)
+				bool *strict_overflow_p, int depth)
 {
   if (TYPE_UNSIGNED (type))
     return true;
@@ -12791,8 +12799,7 @@ tree_unary_nonnegative_warnv_p (enum tre
     case NON_LVALUE_EXPR:
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
-      return tree_expr_nonnegative_warnv_p (op0,
-					    strict_overflow_p);
+      return RECURSE (op0);
 
     CASE_CONVERT:
       {
@@ -12802,21 +12809,18 @@ tree_unary_nonnegative_warnv_p (enum tre
 	if (TREE_CODE (outer_type) == REAL_TYPE)
 	  {
 	    if (TREE_CODE (inner_type) == REAL_TYPE)
-	      return tree_expr_nonnegative_warnv_p (op0,
-						    strict_overflow_p);
+	      return RECURSE (op0);
 	    if (INTEGRAL_TYPE_P (inner_type))
 	      {
 		if (TYPE_UNSIGNED (inner_type))
 		  return true;
-		return tree_expr_nonnegative_warnv_p (op0,
-						      strict_overflow_p);
+		return RECURSE (op0);
 	      }
 	  }
 	else if (INTEGRAL_TYPE_P (outer_type))
 	  {
 	    if (TREE_CODE (inner_type) == REAL_TYPE)
-	      return tree_expr_nonnegative_warnv_p (op0,
-						    strict_overflow_p);
+	      return RECURSE (op0);
 	    if (INTEGRAL_TYPE_P (inner_type))
 	      return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
 		      && TYPE_UNSIGNED (inner_type);
@@ -12835,11 +12839,12 @@ tree_unary_nonnegative_warnv_p (enum tre
 /* Return true if (CODE OP0 OP1) is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 bool
 tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
-				      tree op1, bool *strict_overflow_p)
+				 tree op1, bool *strict_overflow_p,
+				 int depth)
 {
   if (TYPE_UNSIGNED (type))
     return true;
@@ -12849,10 +12854,7 @@ tree_binary_nonnegative_warnv_p (enum tr
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (FLOAT_TYPE_P (type))
-	return (tree_expr_nonnegative_warnv_p (op0,
-					       strict_overflow_p)
-		&& tree_expr_nonnegative_warnv_p (op1,
-						  strict_overflow_p));
+	return RECURSE (op0) && RECURSE (op1);
 
       /* zero_extend(x) + zero_extend(y) is non-negative if x and y are
 	 both unsigned and at least 2 bits shorter than the result.  */
@@ -12878,8 +12880,7 @@ tree_binary_nonnegative_warnv_p (enum tr
 	  /* x * x is always non-negative for floating point x
 	     or without overflow.  */
 	  if (operand_equal_p (op0, op1, 0)
-	      || (tree_expr_nonnegative_warnv_p (op0, strict_overflow_p)
-		  && tree_expr_nonnegative_warnv_p (op1, strict_overflow_p)))
+	      || (RECURSE (op0) && RECURSE (op1)))
 	    {
 	      if (ANY_INTEGRAL_TYPE_P (type)
 		  && TYPE_OVERFLOW_UNDEFINED (type))
@@ -12928,10 +12929,7 @@ tree_binary_nonnegative_warnv_p (enum tr
 
     case BIT_AND_EXPR:
     case MAX_EXPR:
-      return (tree_expr_nonnegative_warnv_p (op0,
-					     strict_overflow_p)
-	      || tree_expr_nonnegative_warnv_p (op1,
-						strict_overflow_p));
+      return RECURSE (op0) || RECURSE (op1);
 
     case BIT_IOR_EXPR:
     case BIT_XOR_EXPR:
@@ -12941,17 +12939,14 @@ tree_binary_nonnegative_warnv_p (enum tr
     case CEIL_DIV_EXPR:
     case FLOOR_DIV_EXPR:
     case ROUND_DIV_EXPR:
-      return (tree_expr_nonnegative_warnv_p (op0,
-					     strict_overflow_p)
-	      && tree_expr_nonnegative_warnv_p (op1,
-						strict_overflow_p));
+      return RECURSE (op0) && RECURSE (op1);
 
     case TRUNC_MOD_EXPR:
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
-      return tree_expr_nonnegative_warnv_p (op0,
-					    strict_overflow_p);
+      return RECURSE (op0);
+
     default:
       return tree_simple_nonnegative_warnv_p (code, type);
     }
@@ -12960,13 +12955,32 @@ tree_binary_nonnegative_warnv_p (enum tr
   return false;
 }
 
+/* Return true if SSA name T is known to be non-negative.  If the return
+   value is based on the assumption that signed overflow is undefined,
+   set *STRICT_OVERFLOW_P to true; otherwise, don't change
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
+
+static bool
+tree_ssa_name_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth)
+{
+  /* Limit the depth of recursion to avoid quadratic behavior.
+     This is expected to catch almost all occurrences in practice.
+     If this code misses important cases that unbounded recursion
+     would not, passes that need this information could be revised
+     to provide it through dataflow propagation.  */
+  if (depth < PARAM_VALUE (PARAM_MAX_SSA_NAME_QUERY_DEPTH))
+    return gimple_stmt_nonnegative_warnv_p (SSA_NAME_DEF_STMT (t),
+					    strict_overflow_p, depth);
+  return tree_simple_nonnegative_warnv_p (TREE_CODE (t), TREE_TYPE (t));
+}
+
 /* Return true if T is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 bool
-tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
+tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth)
 {
   if (TYPE_UNSIGNED (TREE_TYPE (t)))
     return true;
@@ -12983,26 +12997,24 @@ tree_single_nonnegative_warnv_p (tree t,
       return ! FIXED_VALUE_NEGATIVE (TREE_FIXED_CST (t));
 
     case COND_EXPR:
-      return (tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
-					     strict_overflow_p)
-	      && tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 2),
-						strict_overflow_p));
+      return RECURSE (TREE_OPERAND (t, 1)) && RECURSE (TREE_OPERAND (t, 2));
+
+    case SSA_NAME:
+      return tree_ssa_name_nonnegative_warnv_p (t, strict_overflow_p, depth);
+
     default:
-      return tree_simple_nonnegative_warnv_p (TREE_CODE (t),
-						   TREE_TYPE (t));
+      return tree_simple_nonnegative_warnv_p (TREE_CODE (t), TREE_TYPE (t));
     }
-  /* We don't know sign of `t', so be conservative and return false.  */
-  return false;
 }
 
 /* Return true if T is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 bool
-tree_call_nonnegative_warnv_p (tree type, tree fndecl,
-			       tree arg0, tree arg1, bool *strict_overflow_p)
+tree_call_nonnegative_warnv_p (tree type, tree fndecl, tree arg0, tree arg1,
+			       bool *strict_overflow_p, int depth)
 {
   if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (fndecl))
@@ -13033,8 +13045,7 @@ tree_call_nonnegative_warnv_p (tree type
 	/* sqrt(-0.0) is -0.0.  */
 	if (!HONOR_SIGNED_ZEROS (element_mode (type)))
 	  return true;
-	return tree_expr_nonnegative_warnv_p (arg0,
-					      strict_overflow_p);
+	return RECURSE (arg0);
 
 	CASE_FLT_FN (BUILT_IN_ASINH):
 	CASE_FLT_FN (BUILT_IN_ATAN):
@@ -13072,27 +13083,19 @@ tree_call_nonnegative_warnv_p (tree type
 	CASE_FLT_FN (BUILT_IN_TANH):
 	CASE_FLT_FN (BUILT_IN_TRUNC):
 	/* True if the 1st argument is nonnegative.  */
-	return tree_expr_nonnegative_warnv_p (arg0,
-					      strict_overflow_p);
+	return RECURSE (arg0);
 
 	CASE_FLT_FN (BUILT_IN_FMAX):
 	/* True if the 1st OR 2nd arguments are nonnegative.  */
-	return (tree_expr_nonnegative_warnv_p (arg0,
-					       strict_overflow_p)
-		|| (tree_expr_nonnegative_warnv_p (arg1,
-						   strict_overflow_p)));
+	return RECURSE (arg0) || RECURSE (arg1);
 
 	CASE_FLT_FN (BUILT_IN_FMIN):
 	/* True if the 1st AND 2nd arguments are nonnegative.  */
-	return (tree_expr_nonnegative_warnv_p (arg0,
-					       strict_overflow_p)
-		&& (tree_expr_nonnegative_warnv_p (arg1,
-						   strict_overflow_p)));
+	return RECURSE (arg0) && RECURSE (arg1);
 
 	CASE_FLT_FN (BUILT_IN_COPYSIGN):
 	/* True if the 2nd argument is nonnegative.  */
-	return tree_expr_nonnegative_warnv_p (arg1,
-					      strict_overflow_p);
+	return RECURSE (arg1);
 
 	CASE_FLT_FN (BUILT_IN_POWI):
 	/* True if the 1st argument is nonnegative or the second
@@ -13100,8 +13103,7 @@ tree_call_nonnegative_warnv_p (tree type
 	if (TREE_CODE (arg1) == INTEGER_CST
 	    && (TREE_INT_CST_LOW (arg1) & 1) == 0)
 	  return true;
-	return tree_expr_nonnegative_warnv_p (arg0,
-					      strict_overflow_p);
+	return RECURSE (arg0);
 
 	CASE_FLT_FN (BUILT_IN_POW):
 	/* True if the 1st argument is nonnegative or the second
@@ -13121,23 +13123,21 @@ tree_call_nonnegative_warnv_p (tree type
 		  return true;
 	      }
 	  }
-	return tree_expr_nonnegative_warnv_p (arg0,
-					      strict_overflow_p);
+	return RECURSE (arg0);
 
       default:
 	break;
       }
-  return tree_simple_nonnegative_warnv_p (CALL_EXPR,
-					  type);
+  return tree_simple_nonnegative_warnv_p (CALL_EXPR, type);
 }
 
 /* Return true if T is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 static bool
-tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
+tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth)
 {
   enum tree_code code = TREE_CODE (t);
   if (TYPE_UNSIGNED (TREE_TYPE (t)))
@@ -13153,7 +13153,7 @@ tree_invalid_nonnegative_warnv_p (tree t
 	/* If the initializer is non-void, then it's a normal expression
 	   that will be assigned to the slot.  */
 	if (!VOID_TYPE_P (t))
-	  return tree_expr_nonnegative_warnv_p (t, strict_overflow_p);
+	  return RECURSE (t);
 
 	/* Otherwise, the initializer sets the slot in some way.  One common
 	   way is an assignment statement at the end of the initializer.  */
@@ -13171,8 +13171,7 @@ tree_invalid_nonnegative_warnv_p (tree t
 	  }
 	if (TREE_CODE (t) == MODIFY_EXPR
 	    && TREE_OPERAND (t, 0) == temp)
-	  return tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
-						strict_overflow_p);
+	  return RECURSE (TREE_OPERAND (t, 1));
 
 	return false;
       }
@@ -13186,35 +13185,33 @@ tree_invalid_nonnegative_warnv_p (tree t
 					      get_callee_fndecl (t),
 					      arg0,
 					      arg1,
-					      strict_overflow_p);
+					      strict_overflow_p, depth);
       }
     case COMPOUND_EXPR:
     case MODIFY_EXPR:
-      return tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 1),
-					    strict_overflow_p);
+      return RECURSE (TREE_OPERAND (t, 1));
+
     case BIND_EXPR:
-      return tree_expr_nonnegative_warnv_p (expr_last (TREE_OPERAND (t, 1)),
-					    strict_overflow_p);
+      return RECURSE (expr_last (TREE_OPERAND (t, 1)));
+
     case SAVE_EXPR:
-      return tree_expr_nonnegative_warnv_p (TREE_OPERAND (t, 0),
-					    strict_overflow_p);
+      return RECURSE (TREE_OPERAND (t, 0));
 
     default:
-      return tree_simple_nonnegative_warnv_p (TREE_CODE (t),
-						   TREE_TYPE (t));
+      return tree_simple_nonnegative_warnv_p (TREE_CODE (t), TREE_TYPE (t));
     }
-
-  /* We don't know sign of `t', so be conservative and return false.  */
-  return false;
 }
 
+#undef RECURSE
+#undef tree_expr_nonnegative_warnv_p
+
 /* Return true if T is known to be non-negative.  If the return
    value is based on the assumption that signed overflow is undefined,
    set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.  */
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
 
 bool
-tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
+tree_expr_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth)
 {
   enum tree_code code;
   if (t == error_mark_node)
@@ -13229,18 +13226,18 @@ tree_expr_nonnegative_warnv_p (tree t, b
 					      TREE_TYPE (t),
 					      TREE_OPERAND (t, 0),
 					      TREE_OPERAND (t, 1),
-					      strict_overflow_p);
+					      strict_overflow_p, depth);
 
     case tcc_unary:
       return tree_unary_nonnegative_warnv_p (TREE_CODE (t),
 					     TREE_TYPE (t),
 					     TREE_OPERAND (t, 0),
-					     strict_overflow_p);
+					     strict_overflow_p, depth);
 
     case tcc_constant:
     case tcc_declaration:
     case tcc_reference:
-      return tree_single_nonnegative_warnv_p (t, strict_overflow_p);
+      return tree_single_nonnegative_warnv_p (t, strict_overflow_p, depth);
 
     default:
       break;
@@ -13255,12 +13252,12 @@ tree_expr_nonnegative_warnv_p (tree t, b
 					      TREE_TYPE (t),
 					      TREE_OPERAND (t, 0),
 					      TREE_OPERAND (t, 1),
-					      strict_overflow_p);
+					      strict_overflow_p, depth);
     case TRUTH_NOT_EXPR:
       return tree_unary_nonnegative_warnv_p (TREE_CODE (t),
 					     TREE_TYPE (t),
 					     TREE_OPERAND (t, 0),
-					     strict_overflow_p);
+					     strict_overflow_p, depth);
 
     case COND_EXPR:
     case CONSTRUCTOR:
@@ -13269,10 +13266,10 @@ tree_expr_nonnegative_warnv_p (tree t, b
     case ADDR_EXPR:
     case WITH_SIZE_EXPR:
     case SSA_NAME:
-      return tree_single_nonnegative_warnv_p (t, strict_overflow_p);
+      return tree_single_nonnegative_warnv_p (t, strict_overflow_p, depth);
 
     default:
-      return tree_invalid_nonnegative_warnv_p (t, strict_overflow_p);
+      return tree_invalid_nonnegative_warnv_p (t, strict_overflow_p, depth);
     }
 }
 
Index: gcc/gimple-fold.h
===================================================================
--- gcc/gimple-fold.h	2015-09-25 12:49:13.928814656 +0100
+++ gcc/gimple-fold.h	2015-10-08 10:59:12.904576852 +0100
@@ -48,7 +48,6 @@ extern tree gimple_get_virt_method_for_b
 extern tree gimple_get_virt_method_for_vtable (HOST_WIDE_INT, tree,
 					       unsigned HOST_WIDE_INT,
 					       bool *can_refer = NULL);
-extern bool gimple_val_nonnegative_real_p (tree);
 extern tree gimple_fold_indirect_ref (tree);
 extern bool arith_code_with_undefined_signed_overflow (tree_code);
 extern gimple_seq rewrite_to_defined_overflow (gimple *);
@@ -113,6 +112,8 @@ gimple_convert (gimple_seq *seq, tree ty
   return gimple_convert (seq, UNKNOWN_LOCATION, type, op);
 }
 
+extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);
+
 /* In gimple-match.c.  */
 extern tree gimple_simplify (enum tree_code, tree, tree,
 			     gimple_seq *, tree (*)(tree));
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	2015-10-05 20:45:48.964959975 +0100
+++ gcc/tree-vrp.c	2015-10-08 10:59:12.908576806 +0100
@@ -1007,80 +1007,6 @@ usable_range_p (value_range *vr, bool *s
   return true;
 }
 
-
-/* Return true if the result of assignment STMT is know to be non-negative.
-   If the return value is based on the assumption that signed overflow is
-   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.*/
-
-static bool
-gimple_assign_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p)
-{
-  enum tree_code code = gimple_assign_rhs_code (stmt);
-  switch (get_gimple_rhs_class (code))
-    {
-    case GIMPLE_UNARY_RHS:
-      return tree_unary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
-					     gimple_expr_type (stmt),
-					     gimple_assign_rhs1 (stmt),
-					     strict_overflow_p);
-    case GIMPLE_BINARY_RHS:
-      return tree_binary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
-					      gimple_expr_type (stmt),
-					      gimple_assign_rhs1 (stmt),
-					      gimple_assign_rhs2 (stmt),
-					      strict_overflow_p);
-    case GIMPLE_TERNARY_RHS:
-      return false;
-    case GIMPLE_SINGLE_RHS:
-      return tree_single_nonnegative_warnv_p (gimple_assign_rhs1 (stmt),
-					      strict_overflow_p);
-    case GIMPLE_INVALID_RHS:
-      gcc_unreachable ();
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return true if return value of call STMT is know to be non-negative.
-   If the return value is based on the assumption that signed overflow is
-   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.*/
-
-static bool
-gimple_call_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p)
-{
-  tree arg0 = gimple_call_num_args (stmt) > 0 ?
-    gimple_call_arg (stmt, 0) : NULL_TREE;
-  tree arg1 = gimple_call_num_args (stmt) > 1 ?
-    gimple_call_arg (stmt, 1) : NULL_TREE;
-
-  return tree_call_nonnegative_warnv_p (gimple_expr_type (stmt),
-					gimple_call_fndecl (stmt),
-					arg0,
-					arg1,
-					strict_overflow_p);
-}
-
-/* Return true if STMT is know to compute a non-negative value.
-   If the return value is based on the assumption that signed overflow is
-   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
-   *STRICT_OVERFLOW_P.*/
-
-static bool
-gimple_stmt_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p)
-{
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_ASSIGN:
-      return gimple_assign_nonnegative_warnv_p (stmt, strict_overflow_p);
-    case GIMPLE_CALL:
-      return gimple_call_nonnegative_warnv_p (stmt, strict_overflow_p);
-    default:
-      gcc_unreachable ();
-    }
-}
-
 /* Return true if the result of assignment STMT is know to be non-zero.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
@@ -6858,12 +6784,9 @@ remove_range_assertions (void)
 	    tree lhs = gimple_assign_lhs (stmt);
 	    tree rhs = gimple_assign_rhs1 (stmt);
 	    tree var;
-	    tree cond = fold (ASSERT_EXPR_COND (rhs));
 	    use_operand_p use_p;
 	    imm_use_iterator iter;
 
-	    gcc_assert (cond != boolean_false_node);
-
 	    var = ASSERT_EXPR_VAR (rhs);
 	    gcc_assert (TREE_CODE (var) == SSA_NAME);
 
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	2015-10-07 09:07:21.198341367 +0100
+++ gcc/gimple-fold.c	2015-10-08 10:59:12.904576852 +0100
@@ -5773,137 +5773,6 @@ gimple_get_virt_method_for_binfo (HOST_W
   return gimple_get_virt_method_for_vtable (token, v, offset, can_refer);
 }
 
-/* Return true iff VAL is a gimple expression that is known to be
-   non-negative.  Restricted to floating-point inputs.  */
-
-bool
-gimple_val_nonnegative_real_p (tree val)
-{
-  gimple *def_stmt;
-
-  gcc_assert (val && SCALAR_FLOAT_TYPE_P (TREE_TYPE (val)));
-
-  /* Use existing logic for non-gimple trees.  */
-  if (tree_expr_nonnegative_p (val))
-    return true;
-
-  if (TREE_CODE (val) != SSA_NAME)
-    return false;
-
-  /* Currently we look only at the immediately defining statement
-     to make this determination, since recursion on defining 
-     statements of operands can lead to quadratic behavior in the
-     worst case.  This is expected to catch almost all occurrences
-     in practice.  It would be possible to implement limited-depth
-     recursion if important cases are lost.  Alternatively, passes
-     that need this information (such as the pow/powi lowering code
-     in the cse_sincos pass) could be revised to provide it through
-     dataflow propagation.  */
-
-  def_stmt = SSA_NAME_DEF_STMT (val);
-
-  if (is_gimple_assign (def_stmt))
-    {
-      tree op0, op1;
-
-      /* See fold-const.c:tree_expr_nonnegative_p for additional
-	 cases that could be handled with recursion.  */
-
-      switch (gimple_assign_rhs_code (def_stmt))
-	{
-	case ABS_EXPR:
-	  /* Always true for floating-point operands.  */
-	  return true;
-
-	case MULT_EXPR:
-	  /* True if the two operands are identical (since we are
-	     restricted to floating-point inputs).  */
-	  op0 = gimple_assign_rhs1 (def_stmt);
-	  op1 = gimple_assign_rhs2 (def_stmt);
-
-	  if (op0 == op1
-	      || operand_equal_p (op0, op1, 0))
-	    return true;
-
-	default:
-	  return false;
-	}
-    }
-  else if (is_gimple_call (def_stmt))
-    {
-      tree fndecl = gimple_call_fndecl (def_stmt);
-      if (fndecl
-	  && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
-	{
-	  tree arg1;
-
-	  switch (DECL_FUNCTION_CODE (fndecl))
-	    {
-	    CASE_FLT_FN (BUILT_IN_ACOS):
-	    CASE_FLT_FN (BUILT_IN_ACOSH):
-	    CASE_FLT_FN (BUILT_IN_CABS):
-	    CASE_FLT_FN (BUILT_IN_COSH):
-	    CASE_FLT_FN (BUILT_IN_ERFC):
-	    CASE_FLT_FN (BUILT_IN_EXP):
-	    CASE_FLT_FN (BUILT_IN_EXP10):
-	    CASE_FLT_FN (BUILT_IN_EXP2):
-	    CASE_FLT_FN (BUILT_IN_FABS):
-	    CASE_FLT_FN (BUILT_IN_FDIM):
-	    CASE_FLT_FN (BUILT_IN_HYPOT):
-	    CASE_FLT_FN (BUILT_IN_POW10):
-	      return true;
-
-	    CASE_FLT_FN (BUILT_IN_SQRT):
-	      /* sqrt(-0.0) is -0.0, and sqrt is not defined over other
-		 nonnegative inputs.  */
-	      if (!HONOR_SIGNED_ZEROS (val))
-		return true;
-
-	      break;
-
-	    CASE_FLT_FN (BUILT_IN_POWI):
-	      /* True if the second argument is an even integer.  */
-	      arg1 = gimple_call_arg (def_stmt, 1);
-
-	      if (TREE_CODE (arg1) == INTEGER_CST
-		  && (TREE_INT_CST_LOW (arg1) & 1) == 0)
-		return true;
-
-	      break;
-	      
-	    CASE_FLT_FN (BUILT_IN_POW):
-	      /* True if the second argument is an even integer-valued
-		 real.  */
-	      arg1 = gimple_call_arg (def_stmt, 1);
-
-	      if (TREE_CODE (arg1) == REAL_CST)
-		{
-		  REAL_VALUE_TYPE c;
-		  HOST_WIDE_INT n;
-
-		  c = TREE_REAL_CST (arg1);
-		  n = real_to_integer (&c);
-
-		  if ((n & 1) == 0)
-		    {
-		      REAL_VALUE_TYPE cint;
-		      real_from_integer (&cint, VOIDmode, n, SIGNED);
-		      if (real_identical (&c, &cint))
-			return true;
-		    }
-		}
-
-	      break;
-
-	    default:
-	      return false;
-	    }
-	}
-    }
-
-  return false;
-}
-
 /* Given a pointer value OP0, return a simplified version of an
    indirection through OP0, or NULL_TREE if no simplification is
    possible.  Note that the resulting type may be different from
@@ -6280,3 +6149,80 @@ gimple_convert (gimple_seq *seq, locatio
     return op;
   return gimple_build (seq, loc, NOP_EXPR, type, op);
 }
+
+/* Return true if the result of assignment STMT is known to be non-negative.
+   If the return value is based on the assumption that signed overflow is
+   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
+
+static bool
+gimple_assign_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p,
+				   int depth)
+{
+  enum tree_code code = gimple_assign_rhs_code (stmt);
+  switch (get_gimple_rhs_class (code))
+    {
+    case GIMPLE_UNARY_RHS:
+      return tree_unary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
+					     gimple_expr_type (stmt),
+					     gimple_assign_rhs1 (stmt),
+					     strict_overflow_p, depth);
+    case GIMPLE_BINARY_RHS:
+      return tree_binary_nonnegative_warnv_p (gimple_assign_rhs_code (stmt),
+					      gimple_expr_type (stmt),
+					      gimple_assign_rhs1 (stmt),
+					      gimple_assign_rhs2 (stmt),
+					      strict_overflow_p, depth);
+    case GIMPLE_TERNARY_RHS:
+      return false;
+    case GIMPLE_SINGLE_RHS:
+      return tree_single_nonnegative_warnv_p (gimple_assign_rhs1 (stmt),
+					      strict_overflow_p, depth);
+    case GIMPLE_INVALID_RHS:
+      break;
+    }
+  gcc_unreachable ();
+}
+
+/* Return true if return value of call STMT is known to be non-negative.
+   If the return value is based on the assumption that signed overflow is
+   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
+
+static bool
+gimple_call_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p,
+				 int depth)
+{
+  tree arg0 = gimple_call_num_args (stmt) > 0 ?
+    gimple_call_arg (stmt, 0) : NULL_TREE;
+  tree arg1 = gimple_call_num_args (stmt) > 1 ?
+    gimple_call_arg (stmt, 1) : NULL_TREE;
+
+  return tree_call_nonnegative_warnv_p (gimple_expr_type (stmt),
+					gimple_call_fndecl (stmt),
+					arg0,
+					arg1,
+					strict_overflow_p, depth);
+}
+
+/* Return true if STMT is known to compute a non-negative value.
+   If the return value is based on the assumption that signed overflow is
+   undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
+   *STRICT_OVERFLOW_P.  DEPTH is the current nesting depth of the query.  */
+
+bool
+gimple_stmt_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p,
+				 int depth)
+{
+  switch (gimple_code (stmt))
+    {
+    case GIMPLE_ASSIGN:
+      return gimple_assign_nonnegative_warnv_p (stmt, strict_overflow_p,
+						depth);
+    case GIMPLE_CALL:
+      return gimple_call_nonnegative_warnv_p (stmt, strict_overflow_p,
+					      depth);
+    default:
+      return false;
+    }
+}
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c	2015-10-05 12:34:55.923949581 +0100
+++ gcc/tree-ssa-math-opts.c	2015-10-08 10:59:12.908576806 +0100
@@ -1526,7 +1526,7 @@ gimple_expand_builtin_pow (gimple_stmt_i
 
   if (flag_unsafe_math_optimizations
       && cbrtfn
-      && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode))
+      && (!HONOR_NANS (mode) || tree_expr_nonnegative_p (arg0))
       && real_equal (&c, &dconst1_3))
     return build_and_insert_call (gsi, loc, cbrtfn, arg0);
   
@@ -1538,7 +1538,7 @@ gimple_expand_builtin_pow (gimple_stmt_i
   if (flag_unsafe_math_optimizations
       && sqrtfn
       && cbrtfn
-      && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode))
+      && (!HONOR_NANS (mode) || tree_expr_nonnegative_p (arg0))
       && speed_p
       && hw_sqrt_exists
       && real_equal (&c, &dconst1_6))
@@ -1594,7 +1594,7 @@ gimple_expand_builtin_pow (gimple_stmt_i
 
   if (flag_unsafe_math_optimizations
       && cbrtfn
-      && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode))
+      && (!HONOR_NANS (mode) || tree_expr_nonnegative_p (arg0))
       && real_identical (&c2, &c)
       && !c2_is_int
       && optimize_function_for_speed_p (cfun)
