From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 52927385840E for ; Mon, 1 May 2023 06:29:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 52927385840E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1682922554; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0H6SCOJQoq9WEFNEvEcngTo8sq6Nona8ZMFW7lNcVsw=; b=HvEDFI/umEwwTTB/dK3OR7O/HLMBLltF0lG/4oVdInb56ACO7rXr6Q6mpKsor795z2/u8e 9gcPBxQpUTedJzND8bq+qdAczjWjfW70C8fdeYf6G3k7+EbQMsrlOQy8dLswKWQHzmbPp5 qXdQH83mFab68EGJPoFAZV7jbrCDrEs= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-669-On2tOtITOPWXSto69kKuCg-1; Mon, 01 May 2023 02:29:13 -0400 X-MC-Unique: On2tOtITOPWXSto69kKuCg-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6E4CA2A59543 for ; Mon, 1 May 2023 06:29:13 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.192.81]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 05DBB483EC4; Mon, 1 May 2023 06:29:12 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.17.1/8.17.1) with ESMTPS id 3416TBNG564853 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 1 May 2023 08:29:11 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 3416TBkZ564852; Mon, 1 May 2023 08:29:11 +0200 From: Aldy Hernandez To: GCC patches Cc: Andrew MacLeod , Aldy Hernandez Subject: [COMMITTED] Various cleanups in vr-values.cc towards ranger API. Date: Mon, 1 May 2023 08:28:58 +0200 Message-Id: <20230501062906.564803-4-aldyh@redhat.com> In-Reply-To: <20230501062906.564803-1-aldyh@redhat.com> References: <20230501062906.564803-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: gcc/ChangeLog: * vr-values.cc (check_for_binary_op_overflow): Tidy up by using ranger API. (compare_ranges): Delete. (compare_range_with_value): Delete. (bounds_of_var_in_loop): Tidy up by using ranger API. (simplify_using_ranges::fold_cond_with_ops): Cleanup and rename from vrp_evaluate_conditional_warnv_with_ops_using_ranges. (simplify_using_ranges::legacy_fold_cond_overflow): Remove strict_overflow_p and only_ranges. (simplify_using_ranges::legacy_fold_cond): Adjust call to legacy_fold_cond_overflow. (simplify_using_ranges::simplify_abs_using_ranges): Adjust for rename. (range_fits_type_p): Rename value_range to irange. * vr-values.h (range_fits_type_p): Adjust prototype. --- gcc/vr-values.cc | 531 ++++++++--------------------------------------- gcc/vr-values.h | 8 +- 2 files changed, 87 insertions(+), 452 deletions(-) diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 2ee234c4d88..7f623102ac6 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -104,43 +104,34 @@ check_for_binary_op_overflow (range_query *query, tree op0, tree op1, bool *ovf, gimple *s = NULL) { value_range vr0, vr1; - if (TREE_CODE (op0) == SSA_NAME) - { - if (!query->range_of_expr (vr0, op0, s)) - vr0.set_varying (TREE_TYPE (op0)); - } - else if (TREE_CODE (op0) == INTEGER_CST) - vr0.set (op0, op0); - else + if (!query->range_of_expr (vr0, op0, s)) vr0.set_varying (TREE_TYPE (op0)); - - if (TREE_CODE (op1) == SSA_NAME) - { - if (!query->range_of_expr (vr1, op1, s)) - vr1.set_varying (TREE_TYPE (op1)); - } - else if (TREE_CODE (op1) == INTEGER_CST) - vr1.set (op1, op1); - else + if (!query->range_of_expr (vr1, op1, s)) vr1.set_varying (TREE_TYPE (op1)); tree vr0min, vr0max, vr1min, vr1max; - value_range_kind kind0 = get_legacy_range (vr0, vr0min, vr0max); - value_range_kind kind1 = get_legacy_range (vr1, vr1min, vr1max); - if (kind0 != VR_RANGE - || TREE_OVERFLOW (vr0min) - || TREE_OVERFLOW (vr0max)) + if (vr0.undefined_p () || vr0.varying_p ()) { vr0min = vrp_val_min (TREE_TYPE (op0)); vr0max = vrp_val_max (TREE_TYPE (op0)); } - if (kind1 != VR_RANGE - || TREE_OVERFLOW (vr1min) - || TREE_OVERFLOW (vr1max)) + else + { + tree type = vr0.type (); + vr0min = wide_int_to_tree (type, vr0.lower_bound ()); + vr0max = wide_int_to_tree (type, vr0.upper_bound ()); + } + if (vr1.undefined_p () || vr1.varying_p ()) { vr1min = vrp_val_min (TREE_TYPE (op1)); vr1max = vrp_val_max (TREE_TYPE (op1)); } + else + { + tree type = vr1.type (); + vr1min = wide_int_to_tree (type, vr1.lower_bound ()); + vr1max = wide_int_to_tree (type, vr1.upper_bound ()); + } *ovf = arith_overflowed_p (subcode, type, vr0min, subcode == MINUS_EXPR ? vr1max : vr1min); if (arith_overflowed_p (subcode, type, vr0max, @@ -208,269 +199,6 @@ check_for_binary_op_overflow (range_query *query, return true; } -/* Given two numeric value ranges VR0, VR1 and a comparison code COMP: - - - Return BOOLEAN_TRUE_NODE if VR0 COMP VR1 always returns true for - all the values in the ranges. - - - Return BOOLEAN_FALSE_NODE if the comparison always returns false. - - - Return NULL_TREE if it is not always possible to determine the - value of the comparison. - - Also set *STRICT_OVERFLOW_P to indicate whether comparision evaluation - assumed signed overflow is undefined. */ - - -static tree -compare_ranges (enum tree_code comp, const value_range *vr0, - const value_range *vr1, bool *strict_overflow_p) -{ - /* VARYING or UNDEFINED ranges cannot be compared. */ - if (vr0->varying_p () - || vr0->undefined_p () - || vr1->varying_p () - || vr1->undefined_p ()) - return NULL_TREE; - - /* Anti-ranges need to be handled separately. */ - tree vr0min, vr0max, vr1min, vr1max; - value_range_kind kind0 = get_legacy_range (*vr0, vr0min, vr0max); - value_range_kind kind1 = get_legacy_range (*vr1, vr1min, vr1max); - if (kind0 == VR_ANTI_RANGE || kind1 == VR_ANTI_RANGE) - { - /* If both are anti-ranges, then we cannot compute any - comparison. */ - if (kind0 == VR_ANTI_RANGE && kind1 == VR_ANTI_RANGE) - return NULL_TREE; - - /* These comparisons are never statically computable. */ - if (comp == GT_EXPR - || comp == GE_EXPR - || comp == LT_EXPR - || comp == LE_EXPR) - return NULL_TREE; - - /* Equality can be computed only between a range and an - anti-range. ~[VAL1, VAL2] == [VAL1, VAL2] is always false. */ - if (kind0 == VR_RANGE) - { - /* To simplify processing, make VR0 the anti-range. */ - kind0 = kind1; - vr0min = vr1min; - vr0max = vr1max; - kind1 = get_legacy_range (*vr0, vr1min, vr1max); - } - - gcc_assert (comp == NE_EXPR || comp == EQ_EXPR); - - if (compare_values_warnv (vr0min, vr1min, strict_overflow_p) == 0 - && compare_values_warnv (vr0max, vr1max, strict_overflow_p) == 0) - return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node; - - return NULL_TREE; - } - - /* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the - operands around and change the comparison code. */ - if (comp == GT_EXPR || comp == GE_EXPR) - { - comp = (comp == GT_EXPR) ? LT_EXPR : LE_EXPR; - kind0 = kind1; - vr0min = vr1min; - vr0max = vr1max; - kind1 = get_legacy_range (*vr0, vr1min, vr1max); - } - - if (comp == EQ_EXPR) - { - /* Equality may only be computed if both ranges represent - exactly one value. */ - if (compare_values_warnv (vr0min, vr0max, strict_overflow_p) == 0 - && compare_values_warnv (vr1min, vr1max, strict_overflow_p) == 0) - { - int cmp_min = compare_values_warnv (vr0min, vr1min, - strict_overflow_p); - int cmp_max = compare_values_warnv (vr0max, vr1max, - strict_overflow_p); - if (cmp_min == 0 && cmp_max == 0) - return boolean_true_node; - else if (cmp_min != -2 && cmp_max != -2) - return boolean_false_node; - } - /* If [V0_MIN, V1_MAX] < [V1_MIN, V1_MAX] then V0 != V1. */ - else if (compare_values_warnv (vr0min, vr1max, - strict_overflow_p) == 1 - || compare_values_warnv (vr1min, vr0max, - strict_overflow_p) == 1) - return boolean_false_node; - - return NULL_TREE; - } - else if (comp == NE_EXPR) - { - int cmp1, cmp2; - - /* If VR0 is completely to the left or completely to the right - of VR1, they are always different. Notice that we need to - make sure that both comparisons yield similar results to - avoid comparing values that cannot be compared at - compile-time. */ - cmp1 = compare_values_warnv (vr0max, vr1min, strict_overflow_p); - cmp2 = compare_values_warnv (vr0min, vr1max, strict_overflow_p); - if ((cmp1 == -1 && cmp2 == -1) || (cmp1 == 1 && cmp2 == 1)) - return boolean_true_node; - - /* If VR0 and VR1 represent a single value and are identical, - return false. */ - else if (compare_values_warnv (vr0min, vr0max, - strict_overflow_p) == 0 - && compare_values_warnv (vr1min, vr1max, - strict_overflow_p) == 0 - && compare_values_warnv (vr0min, vr1min, - strict_overflow_p) == 0 - && compare_values_warnv (vr0max, vr1max, - strict_overflow_p) == 0) - return boolean_false_node; - - /* Otherwise, they may or may not be different. */ - else - return NULL_TREE; - } - else if (comp == LT_EXPR || comp == LE_EXPR) - { - int tst; - - /* If VR0 is to the left of VR1, return true. */ - tst = compare_values_warnv (vr0max, vr1min, strict_overflow_p); - if ((comp == LT_EXPR && tst == -1) - || (comp == LE_EXPR && (tst == -1 || tst == 0))) - return boolean_true_node; - - /* If VR0 is to the right of VR1, return false. */ - tst = compare_values_warnv (vr0min, vr1max, strict_overflow_p); - if ((comp == LT_EXPR && (tst == 0 || tst == 1)) - || (comp == LE_EXPR && tst == 1)) - return boolean_false_node; - - /* Otherwise, we don't know. */ - return NULL_TREE; - } - - gcc_unreachable (); -} - -/* Given a value range VR, a value VAL and a comparison code COMP, return - BOOLEAN_TRUE_NODE if VR COMP VAL always returns true for all the - values in VR. Return BOOLEAN_FALSE_NODE if the comparison - always returns false. Return NULL_TREE if it is not always - possible to determine the value of the comparison. Also set - *STRICT_OVERFLOW_P to indicate whether comparision evaluation - assumed signed overflow is undefined. */ - -static tree -compare_range_with_value (enum tree_code comp, const value_range *vr, - tree val, bool *strict_overflow_p) -{ - if (vr->varying_p () || vr->undefined_p ()) - return NULL_TREE; - - /* Anti-ranges need to be handled separately. */ - tree min, max; - if (get_legacy_range (*vr, min, max) == VR_ANTI_RANGE) - { - /* For anti-ranges, the only predicates that we can compute at - compile time are equality and inequality. */ - if (comp == GT_EXPR - || comp == GE_EXPR - || comp == LT_EXPR - || comp == LE_EXPR) - return NULL_TREE; - - /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2. */ - bool contains_p = TREE_CODE (val) != INTEGER_CST || vr->contains_p (val); - if (!contains_p) - return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node; - - return NULL_TREE; - } - - if (comp == EQ_EXPR) - { - /* EQ_EXPR may only be computed if VR represents exactly - one value. */ - if (compare_values_warnv (min, max, strict_overflow_p) == 0) - { - int cmp = compare_values_warnv (min, val, strict_overflow_p); - if (cmp == 0) - return boolean_true_node; - else if (cmp == -1 || cmp == 1 || cmp == 2) - return boolean_false_node; - } - else if (compare_values_warnv (val, min, strict_overflow_p) == -1 - || compare_values_warnv (max, val, strict_overflow_p) == -1) - return boolean_false_node; - - return NULL_TREE; - } - else if (comp == NE_EXPR) - { - /* If VAL is not inside VR, then they are always different. */ - if (compare_values_warnv (max, val, strict_overflow_p) == -1 - || compare_values_warnv (min, val, strict_overflow_p) == 1) - return boolean_true_node; - - /* If VR represents exactly one value equal to VAL, then return - false. */ - if (compare_values_warnv (min, max, strict_overflow_p) == 0 - && compare_values_warnv (min, val, strict_overflow_p) == 0) - return boolean_false_node; - - /* Otherwise, they may or may not be different. */ - return NULL_TREE; - } - else if (comp == LT_EXPR || comp == LE_EXPR) - { - int tst; - - /* If VR is to the left of VAL, return true. */ - tst = compare_values_warnv (max, val, strict_overflow_p); - if ((comp == LT_EXPR && tst == -1) - || (comp == LE_EXPR && (tst == -1 || tst == 0))) - return boolean_true_node; - - /* If VR is to the right of VAL, return false. */ - tst = compare_values_warnv (min, val, strict_overflow_p); - if ((comp == LT_EXPR && (tst == 0 || tst == 1)) - || (comp == LE_EXPR && tst == 1)) - return boolean_false_node; - - /* Otherwise, we don't know. */ - return NULL_TREE; - } - else if (comp == GT_EXPR || comp == GE_EXPR) - { - int tst; - - /* If VR is to the right of VAL, return true. */ - tst = compare_values_warnv (min, val, strict_overflow_p); - if ((comp == GT_EXPR && tst == 1) - || (comp == GE_EXPR && (tst == 0 || tst == 1))) - return boolean_true_node; - - /* If VR is to the left of VAL, return false. */ - tst = compare_values_warnv (max, val, strict_overflow_p); - if ((comp == GT_EXPR && (tst == -1 || tst == 0)) - || (comp == GE_EXPR && tst == -1)) - return boolean_false_node; - - /* Otherwise, we don't know. */ - return NULL_TREE; - } - - gcc_unreachable (); -} - static inline void fix_overflow (tree *min, tree *max) { @@ -557,12 +285,12 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, /* Try to use estimated number of iterations for the loop to constrain the final value in the evolution. */ - tree rmin, rmax; if (TREE_CODE (step) == INTEGER_CST && is_gimple_val (init) && (TREE_CODE (init) != SSA_NAME || (query->range_of_expr (r, init, stmt) - && get_legacy_range (r, rmin, rmax) == VR_RANGE))) + && !r.varying_p () + && !r.undefined_p ()))) { widest_int nit; @@ -586,35 +314,29 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, || wi::gts_p (wtmp, 0) == wi::gts_p (wi::to_wide (step), 0))) { value_range maxvr, vr0, vr1; - if (TREE_CODE (init) == SSA_NAME) - query->range_of_expr (vr0, init, stmt); - else if (is_gimple_min_invariant (init)) - vr0.set (init, init); - else + if (!query->range_of_expr (vr0, init, stmt)) vr0.set_varying (TREE_TYPE (init)); - tree tem = wide_int_to_tree (TREE_TYPE (init), wtmp); - vr1.set (tem, tem); + vr1.set (TREE_TYPE (init), wtmp, wtmp); range_op_handler handler (PLUS_EXPR, TREE_TYPE (init)); if (!handler.fold_range (maxvr, TREE_TYPE (init), vr0, vr1)) maxvr.set_varying (TREE_TYPE (init)); - tree maxvr_min, maxvr_max; - value_range_kind maxvr_kind - = get_legacy_range (maxvr, maxvr_min, maxvr_max); /* Likewise if the addition did. */ - if (maxvr_kind == VR_RANGE) + if (!maxvr.varying_p () && !maxvr.undefined_p ()) { int_range<2> initvr; - if (TREE_CODE (init) == SSA_NAME) - query->range_of_expr (initvr, init, stmt); - else if (is_gimple_min_invariant (init)) - initvr.set (init, init); - else + if (!query->range_of_expr (initvr, init, stmt) + || initvr.undefined_p ()) return false; tree initvr_min, initvr_max; + tree maxvr_type = maxvr.type (); + tree maxvr_min = wide_int_to_tree (maxvr_type, + maxvr.lower_bound ()); + tree maxvr_max = wide_int_to_tree (maxvr_type, + maxvr.upper_bound ()); get_legacy_range (initvr, initvr_min, initvr_max); /* Check if init + nit * step overflows. Though we checked @@ -649,40 +371,33 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, optimizers. */ tree -simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges - (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p, - gimple *s) +simplify_using_ranges::fold_cond_with_ops (enum tree_code code, + tree op0, tree op1, gimple *s) { - bool ssa0 = TREE_CODE (op0) == SSA_NAME; - bool ssa1 = TREE_CODE (op1) == SSA_NAME; - value_range vr0, vr1; - if (ssa0 && !query->range_of_expr (vr0, op0, s)) - vr0.set_varying (TREE_TYPE (op0)); - if (ssa1 && !query->range_of_expr (vr1, op1, s)) - vr1.set_varying (TREE_TYPE (op1)); + int_range_max r0, r1; + if (!query->range_of_expr (r0, op0, s) + || !query->range_of_expr (r1, op1, s)) + return NULL_TREE; - tree res = NULL_TREE; - if (ssa0 && ssa1) - res = compare_ranges (code, &vr0, &vr1, strict_overflow_p); - if (!res && ssa0) - res = compare_range_with_value (code, &vr0, op1, strict_overflow_p); - if (!res && ssa1) - res = (compare_range_with_value - (swap_tree_comparison (code), &vr1, op0, strict_overflow_p)); - return res; + tree type = TREE_TYPE (op0); + int_range<1> res; + range_op_handler handler (code, type); + if (handler && handler.fold_range (res, type, r0, r1)) + { + if (res == range_true (type)) + return boolean_true_node; + if (res == range_false (type)) + return boolean_false_node; + } + return NULL; } /* Helper function for legacy_fold_cond. */ tree -simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt, - bool *strict_overflow_p, - bool *only_ranges) +simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt) { tree ret; - if (only_ranges) - *only_ranges = true; - tree_code code = gimple_cond_code (stmt); tree op0 = gimple_cond_lhs (stmt); tree op1 = gimple_cond_rhs (stmt); @@ -760,11 +475,8 @@ simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt, } } - if ((ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges - (code, op0, op1, strict_overflow_p, stmt))) + if ((ret = fold_cond_with_ops (code, op0, op1, stmt))) return ret; - if (only_ranges) - *only_ranges = false; return NULL_TREE; } @@ -801,8 +513,7 @@ simplify_using_ranges::legacy_fold_cond (gcond *stmt, edge *taken_edge_p) fprintf (dump_file, "\n"); } - bool sop; - val = legacy_fold_cond_overflow (stmt, &sop, NULL); + val = legacy_fold_cond_overflow (stmt); if (val) *taken_edge_p = find_taken_edge (gimple_bb (stmt), val); @@ -1054,25 +765,8 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges val = integer_one_node; else { - bool sop = false; - - val = compare_range_with_value (GE_EXPR, &vr, integer_zero_node, &sop); - - if (val - && sop - && integer_onep (val) - && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC)) - { - location_t location; - - if (!gimple_has_location (stmt)) - location = input_location; - else - location = gimple_location (stmt); - warning_at (location, OPT_Wstrict_overflow, - "assuming signed overflow does not occur when " - "simplifying % or %<%%%> to %<>>%> or %<&%>"); - } + tree zero = build_zero_cst (TREE_TYPE (op0)); + val = fold_cond_with_ops (GE_EXPR, op0, zero, stmt); } if (val && integer_onep (val)) @@ -1115,33 +809,14 @@ simplify_using_ranges::simplify_min_or_max_using_ranges { tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); - bool sop = false; tree val; - val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges - (LE_EXPR, op0, op1, &sop, stmt)); + val = fold_cond_with_ops (LE_EXPR, op0, op1, stmt); if (!val) - { - sop = false; - val = (vrp_evaluate_conditional_warnv_with_ops_using_ranges - (LT_EXPR, op0, op1, &sop, stmt)); - } + val = fold_cond_with_ops (LT_EXPR, op0, op1, stmt); if (val) { - if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC)) - { - location_t location; - - if (!gimple_has_location (stmt)) - location = input_location; - else - location = gimple_location (stmt); - warning_at (location, OPT_Wstrict_overflow, - "assuming signed overflow does not occur when " - "simplifying % to % or %"); - } - /* VAL == TRUE -> OP0 < or <= op1 VAL == FALSE -> OP0 > or >= op1. */ tree res = ((gimple_assign_rhs_code (stmt) == MAX_EXPR) @@ -1162,52 +837,26 @@ simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) { tree op = gimple_assign_rhs1 (stmt); - value_range vr; + tree zero = build_zero_cst (TREE_TYPE (op)); + tree val = fold_cond_with_ops (LE_EXPR, op, zero, stmt); - if (!query->range_of_expr (vr, op, stmt)) - vr.set_undefined (); - - if (!vr.undefined_p () && !vr.varying_p ()) + if (!val) { - tree val = NULL; - bool sop = false; - - val = compare_range_with_value (LE_EXPR, &vr, integer_zero_node, &sop); - if (!val) - { - /* The range is neither <= 0 nor > 0. Now see if it is - either < 0 or >= 0. */ - sop = false; - val = compare_range_with_value (LT_EXPR, &vr, integer_zero_node, - &sop); - } - - if (val) - { - if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC)) - { - location_t location; - - if (!gimple_has_location (stmt)) - location = input_location; - else - location = gimple_location (stmt); - warning_at (location, OPT_Wstrict_overflow, - "assuming signed overflow does not occur when " - "simplifying % to % or %<-X%>"); - } - - gimple_assign_set_rhs1 (stmt, op); - if (integer_zerop (val)) - gimple_assign_set_rhs_code (stmt, SSA_NAME); - else - gimple_assign_set_rhs_code (stmt, NEGATE_EXPR); - update_stmt (stmt); - fold_stmt (gsi, follow_single_use_edges); - return true; - } + /* The range is neither <= 0 nor > 0. Now see if it is + either < 0 or >= 0. */ + val = fold_cond_with_ops (LT_EXPR, op, zero, stmt); + } + if (val) + { + gimple_assign_set_rhs1 (stmt, op); + if (integer_zerop (val)) + gimple_assign_set_rhs_code (stmt, SSA_NAME); + else + gimple_assign_set_rhs_code (stmt, NEGATE_EXPR); + update_stmt (stmt); + fold_stmt (gsi, follow_single_use_edges); + return true; } - return false; } @@ -1252,24 +901,11 @@ simplify_using_ranges::simplify_bit_ops_using_ranges wide_int must_be_nonzero0, must_be_nonzero1; wide_int mask; - if (TREE_CODE (op0) == SSA_NAME) - { - if (!query->range_of_expr (vr0, op0, stmt)) - vr0.set_varying (TREE_TYPE (op0)); - } - else if (is_gimple_min_invariant (op0)) - vr0.set (op0, op0); - else + if (!query->range_of_expr (vr0, op0, stmt) + || vr0.undefined_p ()) return false; - - if (TREE_CODE (op1) == SSA_NAME) - { - if (!query->range_of_expr (vr1, op1, stmt)) - vr1.set_varying (TREE_TYPE (op1)); - } - else if (is_gimple_min_invariant (op1)) - vr1.set (op1, op1); - else + if (!query->range_of_expr (vr1, op1, stmt) + || vr1.undefined_p ()) return false; if (!vr_set_zero_nonzero_bits (TREE_TYPE (op0), &vr0, &may_be_nonzero0, @@ -1393,7 +1029,7 @@ test_for_singularity (enum tree_code cond_code, tree op0, by PRECISION and UNSIGNED_P. */ bool -range_fits_type_p (const value_range *vr, +range_fits_type_p (const irange *vr, unsigned dest_precision, signop dest_sgn) { tree src_type; @@ -1417,27 +1053,28 @@ range_fits_type_p (const value_range *vr, return true; /* Now we can only handle ranges with constant bounds. */ - tree vrmin, vrmax; - value_range_kind kind = get_legacy_range (*vr, vrmin, vrmax); - if (kind != VR_RANGE) + if (vr->undefined_p () || vr->varying_p ()) return false; + wide_int vrmin = vr->lower_bound (); + wide_int vrmax = vr->upper_bound (); + /* For sign changes, the MSB of the wide_int has to be clear. An unsigned value with its MSB set cannot be represented by 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 (vrmin), 0) - || wi::lts_p (wi::to_wide (vrmax), 0))) + && (wi::lts_p (vrmin, 0) || wi::lts_p (vrmax, 0))) return false; /* Then we can perform the conversion on both ends and compare the result for equality. */ - tem = wi::ext (wi::to_widest (vrmin), dest_precision, dest_sgn); - if (tem != wi::to_widest (vrmin)) + signop sign = TYPE_SIGN (vr->type ()); + tem = wi::ext (widest_int::from (vrmin, sign), dest_precision, dest_sgn); + if (tem != widest_int::from (vrmin, sign)) return false; - tem = wi::ext (wi::to_widest (vrmax), dest_precision, dest_sgn); - if (tem != wi::to_widest (vrmax)) + tem = wi::ext (widest_int::from (vrmax, sign), dest_precision, dest_sgn); + if (tem != widest_int::from (vrmax, sign)) return false; return true; diff --git a/gcc/vr-values.h b/gcc/vr-values.h index ff814155881..dc0c22df4d8 100644 --- a/gcc/vr-values.h +++ b/gcc/vr-values.h @@ -36,7 +36,8 @@ public: bool fold_cond (gcond *); private: void legacy_fold_cond (gcond *, edge *); - tree legacy_fold_cond_overflow (gimple *stmt, bool *, bool *); + tree legacy_fold_cond_overflow (gimple *stmt); + tree fold_cond_with_ops (tree_code, tree, tree, gimple *s); bool simplify_casted_cond (gcond *); bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *); bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *); @@ -51,9 +52,6 @@ private: bool two_valued_val_range_p (tree, tree *, tree *, gimple *); bool op_with_boolean_value_range_p (tree, gimple *); - tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code, - tree, tree, - bool *, gimple *s); void set_and_propagate_unexecutable (edge e); void cleanup_edges_and_switches (void); @@ -74,7 +72,7 @@ private: vec m_flag_set_edges; // List of edges with flag to be cleared. }; -extern bool range_fits_type_p (const value_range *vr, +extern bool range_fits_type_p (const irange *vr, unsigned dest_precision, signop dest_sgn); extern bool bounds_of_var_in_loop (tree *min, tree *max, range_query *, class loop *loop, gimple *stmt, tree var); -- 2.40.0