From patchwork Tue Nov 5 13:15:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 1189698 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-512483-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="aS8rxTmA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 476qsw6hNsz9sNT for ; Wed, 6 Nov 2019 00:15:47 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=F1jk6j/moQt1uU5bDti1EQA68bqWZQGqZht7lU+DSY2nQs0lB0 KhWgMf3d6DBNGS93jXpb+n6tF2gHO2FibVEw63+9Fb6BElg4H6oc+nB5UmHlzBPg 6ba2fZqHnYk4plgtULGXiuKjnBa1cxpIUQSRujluxvXBSFrwiYTMRZeL8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=rGMME9Yz6u+S/xPS3V2UFi3SHN8=; b=aS8rxTmA6UUbWplirH/u G8ezHBhJexII2EOu8US/i9RXbFklnHqauGiWDoBus8aU7jOxUjTNs7mkyj7BBdFG FgoU8jMln6lLXwaZlBe6HOn+ROR7B7WNwMQJoFqOCYW8mNqnkgdCr5xCEMMxbccC UP+J6yNmJBfuD6aXDEegE+k= Received: (qmail 128535 invoked by alias); 5 Nov 2019 13:15:39 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 128518 invoked by uid 89); 5 Nov 2019 13:15:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=vr, speak, cycle, promoting X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 05 Nov 2019 13:15:36 +0000 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1E9068831D for ; Tue, 5 Nov 2019 13:15:35 +0000 (UTC) Received: by mail-wm1-f72.google.com with SMTP id z5so7709561wma.5 for ; Tue, 05 Nov 2019 05:15:35 -0800 (PST) Received: from abulafia.quesejoda.com (149.red-81-32-135.dynamicip.rima-tde.net. [81.32.135.149]) by smtp.gmail.com with ESMTPSA id x8sm20831559wrr.43.2019.11.05.05.15.32 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 05 Nov 2019 05:15:32 -0800 (PST) From: Aldy Hernandez Subject: make range_int_cst_p work with any numeric range (VR_ANTI_RANGE, etc) To: Andrew MacLeod Cc: gcc-patches , Martin Sebor Message-ID: <1da55be1-7511-d303-c6d2-e49cfb0ae5b3@redhat.com> Date: Tue, 5 Nov 2019 14:15:31 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.1.1 MIME-Version: 1.0 X-IsSubscribed: yes The function range_int_cst_p only works with VR_RANGE's at the moment. This is silly because VR_ANTI_RANGE and even VR_VARYING can contain numeric bounds. I have fixed this oversight and have made the function return the bounds in MIN/MAX. This simplifies a lot of code, because there is no longer a need to special case VR_VARYING and VR_ANTI_RANGE, as well as pick at the individual range components outside of the API. The patch has the pleasant side-effect of bringing more things into the API fold. Basically, any access to either value_range::min(), max(), or kind(), is suspect and a big hint that the code should be rewritten to use the API (contains_p, varying_p, zero_p, etc). One of the primary culprits of API noncompliance is the sprintf and strlen warning code. Mind you, not due to negligence on the author, but because we had no value-range API when Martin added the passes. I realize it's nobody's responsibility to fix older value-range code, and I'll probably end up doing it myself (next cycle??), but I could definitely use a hand from the experts, as it's intricate and delicate code. Speak of which, in converting dump_strlen_info() to use the new range_int_cst_p, I noticed a lot of the code disappeared if we used the API. Martin, if you'd prefer not to dump varying, undefined, etc, let me know and we can gate that call to vr.dump(). I took the liberty because it was simple, clean, and hidden away in an internal debugging helper. OK for trunk? commit cba4b59ef2e0e6821d63cfa959d201f22534eb69 Author: Aldy Hernandez Date: Tue Nov 5 10:54:22 2019 +0100 Make range_int_cst_p work with any numeric range, not just VR_RANGE. This includes VR_ANTI_RANGE as well as VR_VARYING, as they can also have numeric bounds. Add two new arguments to return the MIN/MAX bounds. Remove the now redundant range_has_numeric_bounds_p. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 562b69d1aab..5f12d166176 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -48,6 +48,30 @@ * fold-const.c (operand_compare::hash_operand): Remove FIELD_DECL handling. +2019-11-05 Aldy Hernandez + + * gimple-ssa-sprintf.c (get_int_range): Call range_int_cst_p with + min/max arguments. + (format_integer): Same. + (handle_printf_call): Same. + * tree-ssa-strlen.c (compare_nonzero_chars): Same. + (dump_strlen_info): Same. + (get_range_strlen_dynamic): Same. + (count_nonzero_bytes): Same. + * tree-vrp.c (range_has_numeric_bounds_p): Remove. + (extract_range_from_pointer_plus_expr): Call range_int_cst_p with + min/max arguments. + (value_range_base::normalize_addresses): Use range_int_cst_p + instead of removed range_has_numeric_bounds_p. + (range_int_cst_p): New MIN/MAX arguments. + * tree-vrp.h (range_int_cst_p): Add two new arguments. + * vr-values.c (r_values::check_for_binary_op_overflow): Call + range_int_cst_p with min/max arguments. + (vr_values::simplify_div_or_mod_using_ranges): Same. + (vr_set_zero_nonzero_bits): Same. + (range_fits_type_p): Use value_range_base::supports_type_p instead + of open-coding the test. + 2019-11-05 Aldy Hernandez * tree-vrp.h (vrp_bitmap_equal_p): Remove. diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index b548bbd95e3..0029cfc258c 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -1023,18 +1023,12 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, /* Try to determine the range of values of the integer argument. */ const value_range *vr = CONST_CAST (class vr_values *, vr_values)->get_value_range (arg); + tree min, max; - if (range_int_cst_p (vr)) + if (!vr->varying_p () && range_int_cst_p (vr, &min, &max)) { - HOST_WIDE_INT type_min - = (TYPE_UNSIGNED (argtype) - ? tree_to_uhwi (TYPE_MIN_VALUE (argtype)) - : tree_to_shwi (TYPE_MIN_VALUE (argtype))); - - HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); - - *pmin = TREE_INT_CST_LOW (vr->min ()); - *pmax = TREE_INT_CST_LOW (vr->max ()); + *pmin = TREE_INT_CST_LOW (min); + *pmax = TREE_INT_CST_LOW (max); if (*pmin < *pmax) { @@ -1044,8 +1038,12 @@ get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, and its upper bound is in excess of TYPE_MAX. In that (invalid) case disregard the range and use that of the expected type instead. */ + HOST_WIDE_INT type_min + = (TYPE_UNSIGNED (argtype) + ? tree_to_uhwi (TYPE_MIN_VALUE (argtype)) + : tree_to_shwi (TYPE_MIN_VALUE (argtype))); + HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); knownrange = type_min < *pmin || *pmax < type_max; - unknown = false; } } @@ -1326,11 +1324,8 @@ format_integer (const directive &dir, tree arg, const vr_values *vr_values) const value_range *vr = CONST_CAST (class vr_values *, vr_values)->get_value_range (arg); - if (range_int_cst_p (vr)) + if (range_int_cst_p (vr, &argmin, &argmax)) { - argmin = vr->min (); - argmax = vr->max (); - /* Set KNOWNRANGE if the argument is in a known subrange of the directive's type and neither width nor precision is unknown. (KNOWNRANGE may be reset below). */ @@ -1342,11 +1337,7 @@ format_integer (const directive &dir, tree arg, const vr_values *vr_values) res.argmin = argmin; res.argmax = argmax; } - else if (vr->kind () == VR_ANTI_RANGE) - { - /* Handle anti-ranges if/when bug 71690 is resolved. */ - } - else if (vr->varying_p () || vr->undefined_p ()) + else if (vr->undefined_p ()) { /* The argument here may be the result of promoting the actual argument to int. Try to determine the type of the actual @@ -4089,11 +4080,12 @@ handle_printf_call (gimple_stmt_iterator *gsi, const vr_values *vr_values) of them at level 2. */ const value_range *vr = CONST_CAST (class vr_values *, vr_values)->get_value_range (size); + tree min, max; - if (range_int_cst_p (vr)) + if (range_int_cst_p (vr, &min, &max)) { - unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (vr->min ()); - unsigned HOST_WIDE_INT maxsize = TREE_INT_CST_LOW (vr->max ()); + unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (min); + unsigned HOST_WIDE_INT maxsize = TREE_INT_CST_LOW (max); dstsize = warn_level < 2 ? maxsize : minsize; if (minsize > target_int_max ()) @@ -4107,13 +4099,6 @@ handle_printf_call (gimple_stmt_iterator *gsi, const vr_values *vr_values) if (maxsize > target_int_max ()) posunder4k = false; } - else if (vr->varying_p ()) - { - /* POSIX requires snprintf to fail if DSTSIZE is greater - than INT_MAX. Since SIZE's range is unknown, avoid - folding. */ - posunder4k = false; - } /* The destination size is not constant. If the function is bounded (e.g., snprintf) a lower bound of zero doesn't diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 50cc442a61f..25a075d3dc5 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -228,17 +228,16 @@ compare_nonzero_chars (strinfo *si, unsigned HOST_WIDE_INT off, const value_range *vr = (CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars)); - - value_range_kind rng = vr->kind (); - if (rng != VR_RANGE || !range_int_cst_p (vr)) + tree min, max; + if (!range_int_cst_p (vr, &min, &max)) return -1; /* If the offset is less than the minimum length or if the bounds of the length range are equal return the result of the comparison same as in the constant case. Otherwise return a conservative result. */ - int cmpmin = compare_tree_int (vr->min (), off); - if (cmpmin > 0 || tree_int_cst_equal (vr->min (), vr->max ())) + int cmpmin = compare_tree_int (min, off); + if (cmpmin > 0 || tree_int_cst_equal (min, max)) return cmpmin; return -1; @@ -795,32 +794,19 @@ dump_strlen_info (FILE *fp, gimple *stmt, const vr_values *rvals) print_generic_expr (fp, si->nonzero_chars); if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range_kind rng = VR_UNDEFINED; - wide_int min, max; + value_range_base vr; if (rvals) { - const value_range *vr + const value_range *vr_p = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - rng = vr->kind (); - if (range_int_cst_p (vr)) - { - min = wi::to_wide (vr->min ()); - max = wi::to_wide (vr->max ()); - } - else - rng = VR_UNDEFINED; + if (vr_p) + vr = *vr_p; } else - rng = get_range_info (si->nonzero_chars, &min, &max); + get_range_info (si->nonzero_chars, vr); - if (rng == VR_RANGE || rng == VR_ANTI_RANGE) - { - fprintf (fp, " %s[%llu, %llu]", - rng == VR_RANGE ? "" : "~", - (long long) min.to_uhwi (), - (long long) max.to_uhwi ()); - } + vr.dump (fp); } fprintf (fp, " , refcount = %i", si->refcount); if (si->stmt) @@ -994,13 +980,7 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited, const value_range *vr = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - if (vr->kind () == VR_RANGE - && range_int_cst_p (vr)) - { - pdata->minlen = vr->min (); - pdata->maxlen = vr->max (); - } - else + if (!range_int_cst_p (vr, &pdata->minlen, &pdata->maxlen)) pdata->minlen = build_zero_cst (size_type_node); } else @@ -1034,13 +1014,8 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited, const value_range *vr = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - if (vr->kind () == VR_RANGE - && range_int_cst_p (vr)) - { - pdata->minlen = vr->min (); - pdata->maxlen = vr->max (); - pdata->maxbound = pdata->maxlen; - } + if (range_int_cst_p (vr, &pdata->minlen, &pdata->maxlen)) + pdata->maxbound = pdata->maxlen; else { pdata->minlen = build_zero_cst (size_type_node); @@ -4043,12 +4018,14 @@ count_nonzero_bytes (tree exp, unsigned HOST_WIDE_INT offset, const value_range *vr = CONST_CAST (class vr_values *, rvals) ->get_value_range (si->nonzero_chars); - if (vr->kind () != VR_RANGE - || !range_int_cst_p (vr)) + tree min, max; + if (range_int_cst_p (vr, &min, &max)) + { + minlen = tree_to_uhwi (min); + maxlen = tree_to_uhwi (max); + } + else return false; - - minlen = tree_to_uhwi (vr->min ()); - maxlen = tree_to_uhwi (vr->max ()); } else return false; diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index e1d5c7cb98c..b7d7e5e6646 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -922,21 +922,28 @@ vrp_operand_equal_p (const_tree val1, const_tree val2) return true; } -static bool -range_has_numeric_bounds_p (const value_range_base *vr) -{ - return (vr->min () - && TREE_CODE (vr->min ()) == INTEGER_CST - && TREE_CODE (vr->max ()) == INTEGER_CST); -} +/* Return true if range is an integer constant, though not necessarily + a singleton. This can be true for a VR_RANGE, VR_ANTI_RANGE, or + VR_VARYING, as all of them can contain an integer constant range. -/* Return true if max and min of VR are INTEGER_CST. It's not necessary - a singleton. */ + If true, and MIN/MAX are non-zero, set them to the lower and upper + bounds of the range respectively. */ bool -range_int_cst_p (const value_range_base *vr) +range_int_cst_p (const value_range_base *vr, tree *min, tree *max) { - return (vr->kind () == VR_RANGE && range_has_numeric_bounds_p (vr)); + if (vr->min () + && TREE_CODE (vr->min ()) == INTEGER_CST + && TREE_CODE (vr->max ()) == INTEGER_CST) + { + tree type = vr->type (); + if (min) + *min = wide_int_to_tree (type, vr->lower_bound ()); + if (max) + *max = wide_int_to_tree (type, vr->upper_bound ()); + return true; + } + return false; } /* Return the single symbol (an SSA_NAME) contained in T if any, or NULL_TREE @@ -1511,12 +1518,12 @@ extract_range_from_pointer_plus_expr (value_range_base *vr, doesn't either. As the second operand is sizetype (unsigned), consider all ranges where the MSB could be set as possible subtractions where the result might be NULL. */ - if ((!range_includes_zero_p (vr0) - || !range_includes_zero_p (vr1)) + tree vr1min, vr1max; + if ((!range_includes_zero_p (vr0) || !range_includes_zero_p (vr1)) && !TYPE_OVERFLOW_WRAPS (expr_type) && (flag_delete_null_pointer_checks - || (range_int_cst_p (vr1) - && !tree_int_cst_sign_bit (vr1->max ())))) + || (range_int_cst_p (vr1, &vr1min, &vr1max) + && !tree_int_cst_sign_bit (vr1max)))) vr->set_nonzero (expr_type); else if (vr0->zero_p () && vr1->zero_p ()) vr->set_zero (expr_type); @@ -6054,7 +6061,7 @@ value_range_base::normalize_addresses () const if (undefined_p ()) return *this; - if (!POINTER_TYPE_P (type ()) || range_has_numeric_bounds_p (this)) + if (!POINTER_TYPE_P (type ()) || range_int_cst_p (this)) return *this; if (!range_includes_zero_p (this)) diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h index 0bf33caba85..b0d5ae3e877 100644 --- a/gcc/tree-vrp.h +++ b/gcc/tree-vrp.h @@ -279,7 +279,8 @@ extern void register_edge_assert_for (tree, edge, enum tree_code, extern bool stmt_interesting_for_vrp (gimple *); extern bool infer_value_range (gimple *, tree, tree_code *, tree *); -extern bool range_int_cst_p (const value_range_base *); +extern bool range_int_cst_p (const value_range_base *, + tree * = NULL, tree * = NULL); extern int compare_values (tree, tree); extern int compare_values_warnv (tree, tree, bool *); diff --git a/gcc/vr-values.c b/gcc/vr-values.c index d1713bf4e0e..ceda5cbdc9f 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -1022,16 +1022,15 @@ vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type, else vr1.set_varying (TREE_TYPE (op1)); - tree vr0min = vr0.min (), vr0max = vr0.max (); - tree vr1min = vr1.min (), vr1max = vr1.max (); - if (!range_int_cst_p (&vr0) + tree vr0min, vr0max, vr1min, vr1max; + if (!range_int_cst_p (&vr0, &vr0min, &vr0max) || TREE_OVERFLOW (vr0min) || TREE_OVERFLOW (vr0max)) { vr0min = vrp_val_min (TREE_TYPE (op0)); vr0max = vrp_val_max (TREE_TYPE (op0)); } - if (!range_int_cst_p (&vr1) + if (!range_int_cst_p (&vr1, &vr1min, &vr1max) || TREE_OVERFLOW (vr1min) || TREE_OVERFLOW (vr1max)) { @@ -3138,19 +3137,14 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, else { vr = get_value_range (op0); - if (range_int_cst_p (vr)) - { - op0min = vr->min (); - op0max = vr->max (); - } + range_int_cst_p (vr, &op0min, &op0max); } if (rhs_code == TRUNC_MOD_EXPR && TREE_CODE (op1) == SSA_NAME) { const value_range *vr1 = get_value_range (op1); - if (range_int_cst_p (vr1)) - op1min = vr1->min (); + range_int_cst_p (vr1, &op1min); } if (rhs_code == TRUNC_MOD_EXPR && TREE_CODE (op1min) == INTEGER_CST @@ -3352,11 +3346,11 @@ vr_set_zero_nonzero_bits (const tree expr_type, wide_int *may_be_nonzero, wide_int *must_be_nonzero) { - if (range_int_cst_p (vr)) + tree min, max; + if (range_int_cst_p (vr, &min, &max)) { wi_set_zero_nonzero_bits (expr_type, - wi::to_wide (vr->min ()), - wi::to_wide (vr->max ()), + wi::to_wide (min), wi::to_wide (max), *may_be_nonzero, *must_be_nonzero); return true; } @@ -3525,8 +3519,7 @@ range_fits_type_p (const value_range *vr, /* We can only handle integral and pointer types. */ src_type = vr->type (); - if (!INTEGRAL_TYPE_P (src_type) - && !POINTER_TYPE_P (src_type)) + if (!value_range_base::supports_type_p (src_type)) return false; /* An extension is fine unless VR is SIGNED and dest_sgn is UNSIGNED, @@ -3539,7 +3532,8 @@ range_fits_type_p (const value_range *vr, return true; /* Now we can only handle ranges with constant bounds. */ - if (!range_int_cst_p (vr)) + tree min, max; + if (!range_int_cst_p (vr, &min, &max)) return false; /* For sign changes, the MSB of the wide_int has to be clear. @@ -3547,17 +3541,17 @@ range_fits_type_p (const value_range *vr, a signed wide_int, while a negative value cannot be represented by an unsigned wide_int. */ if (src_sgn != dest_sgn - && (wi::lts_p (wi::to_wide (vr->min ()), 0) - || wi::lts_p (wi::to_wide (vr->max ()), 0))) + && (wi::lts_p (wi::to_wide (min), 0) + || wi::lts_p (wi::to_wide (max), 0))) return false; /* Then we can perform the conversion on both ends and compare the result for equality. */ - tem = wi::ext (wi::to_widest (vr->min ()), dest_precision, dest_sgn); - if (tem != wi::to_widest (vr->min ())) + tem = wi::ext (wi::to_widest (min), dest_precision, dest_sgn); + if (tem != wi::to_widest (min)) return false; - tem = wi::ext (wi::to_widest (vr->max ()), dest_precision, dest_sgn); - if (tem != wi::to_widest (vr->max ())) + tem = wi::ext (wi::to_widest (max), dest_precision, dest_sgn); + if (tem != wi::to_widest (max)) return false; return true;