From patchwork Mon May 1 06:29:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 1775423 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=RcLGSzAD; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Q8tgq4mzsz1ydX for ; Mon, 1 May 2023 16:33:11 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A47E83887F4A for ; Mon, 1 May 2023 06:33:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A47E83887F4A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1682922789; bh=xAlZrGvMGTP8JiF5aMfHPr4SWZwy4oIX2JidQg73FO8=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=RcLGSzADFA5il6ppXyxz5yUmoHj2FKrbpbP1fxpwkqyiAe+ug1Cfq1h2rCPrehZ8R D1WQ2m7Z48T7o5w7vFE+Lk0Cfm3BM/MdPmOqi38CuZtu3x3tompeXizu8GDEMelwL3 Y6QrvZBE6zA5XcE8r6PmAnD1Hn+kVWqzaWpMb3Ww= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org 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 4D63C3858417 for ; Mon, 1 May 2023 06:29:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4D63C3858417 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-167-gkSCBtrVNQ-mYGOdI4TCkw-1; Mon, 01 May 2023 02:29:14 -0400 X-MC-Unique: gkSCBtrVNQ-mYGOdI4TCkw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 19F41101A550 for ; Mon, 1 May 2023 06:29:14 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.192.81]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6159C2166B26; Mon, 1 May 2023 06:29:13 +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 3416TCXO564865 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 1 May 2023 08:29:12 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 3416TC1H564864; Mon, 1 May 2023 08:29:12 +0200 To: GCC patches Cc: Andrew MacLeod , Aldy Hernandez Subject: [COMMITTED] Conversion to irange wide_int API. Date: Mon, 1 May 2023 08:29:01 +0200 Message-Id: <20230501062906.564803-7-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.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.9 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, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP, T_FILL_THIS_FORM_SHORT, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Aldy Hernandez via Gcc-patches From: Aldy Hernandez Reply-To: Aldy Hernandez Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" This converts the irange API to use wide_ints exclusively, along with its users. This patch will slow down VRP, as there will be more useless wide_int to tree conversions. However, this slowdown is only temporary, as a follow-up patch will convert the internal representation of iranges to wide_ints for a net overall gain in performance. gcc/ChangeLog: * fold-const.cc (expr_not_equal_to): Convert to irange wide_int API. * gimple-fold.cc (size_must_be_zero_p): Same. * gimple-loop-versioning.cc (loop_versioning::prune_loop_conditions): Same. * gimple-range-edge.cc (gcond_edge_range): Same. (gimple_outgoing_range::calc_switch_ranges): Same. * gimple-range-fold.cc (adjust_imagpart_expr): Same. (adjust_realpart_expr): Same. (fold_using_range::range_of_address): Same. (fold_using_range::relation_fold_and_or): Same. * gimple-range-gori.cc (gori_compute::gori_compute): Same. (range_is_either_true_or_false): Same. * gimple-range-op.cc (cfn_toupper_tolower::get_letter_range): Same. (cfn_clz::fold_range): Same. (cfn_ctz::fold_range): Same. * gimple-range-tests.cc (class test_expr_eval): Same. * gimple-ssa-warn-alloca.cc (alloca_call_type): Same. * ipa-cp.cc (ipa_value_range_from_jfunc): Same. (propagate_vr_across_jump_function): Same. (decide_whether_version_node): Same. * ipa-fnsummary.cc (evaluate_conditions_for_known_args): Same. * ipa-prop.cc (ipa_get_value_range): Same. * range-op.cc (get_shift_range): Same. (value_range_from_overflowed_bounds): Same. (value_range_with_overflow): Same. (create_possibly_reversed_range): Same. (equal_op1_op2_relation): Same. (not_equal_op1_op2_relation): Same. (lt_op1_op2_relation): Same. (le_op1_op2_relation): Same. (gt_op1_op2_relation): Same. (ge_op1_op2_relation): Same. (operator_mult::op1_range): Same. (operator_exact_divide::op1_range): Same. (operator_lshift::op1_range): Same. (operator_rshift::op1_range): Same. (operator_cast::op1_range): Same. (operator_logical_and::fold_range): Same. (set_nonzero_range_from_mask): Same. (operator_bitwise_or::op1_range): Same. (operator_bitwise_xor::op1_range): Same. (operator_addr_expr::fold_range): Same. (pointer_plus_operator::wi_fold): Same. (pointer_or_operator::op1_range): Same. (INT): Same. (UINT): Same. (INT16): Same. (UINT16): Same. (SCHAR): Same. (UCHAR): Same. (range_op_cast_tests): Same. (range_op_lshift_tests): Same. (range_op_rshift_tests): Same. (range_op_bitwise_and_tests): Same. (range_relational_tests): Same. * range.cc (range_zero): Same. (range_nonzero): Same. * range.h (range_true): Same. (range_false): Same. (range_true_and_false): Same. * tree-data-ref.cc (split_constant_offset_1): Same. * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same. * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same. (find_unswitching_predicates_for_bb): Same. * tree-ssa-phiopt.cc (value_replacement): Same. * tree-ssa-threadbackward.cc (back_threader::find_taken_edge_cond): Same. * tree-ssanames.cc (ssa_name_has_boolean_range): Same. * tree-vrp.cc (find_case_label_range): Same. * value-query.cc (range_query::get_tree_range): Same. * value-range.cc (irange::set_nonnegative): Same. (frange::contains_p): Same. (frange::singleton_p): Same. (frange::internal_singleton_p): Same. (irange::irange_set): Same. (irange::irange_set_1bit_anti_range): Same. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::operator==): Same. (irange::singleton_p): Same. (irange::contains_p): Same. (irange::set_range_from_nonzero_bits): Same. (DEFINE_INT_RANGE_INSTANCE): Same. (INT): Same. (UINT): Same. (SCHAR): Same. (UINT128): Same. (UCHAR): Same. (range): New. (tree_range): New. (range_int): New. (range_uint): New. (range_uint128): New. (range_uchar): New. (range_char): New. (build_range3): Convert to irange wide_int API. (range_tests_irange3): Same. (range_tests_int_range_max): Same. (range_tests_strict_enum): Same. (range_tests_misc): Same. (range_tests_nonzero_bits): Same. (range_tests_nan): Same. (range_tests_signed_zeros): Same. * value-range.h (Value_Range::Value_Range): Same. (irange::set): Same. (irange::nonzero_p): Same. (irange::contains_p): Same. (range_includes_zero_p): Same. (irange::set_nonzero): Same. (irange::set_zero): Same. (contains_zero_p): Same. (frange::contains_p): Same. * vr-values.cc (simplify_using_ranges::op_with_boolean_value_range_p): Same. (bounds_of_var_in_loop): Same. (simplify_using_ranges::legacy_fold_cond_overflow): Same. --- gcc/fold-const.cc | 3 +- gcc/gimple-fold.cc | 4 +- gcc/gimple-loop-versioning.cc | 2 +- gcc/gimple-range-edge.cc | 17 +- gcc/gimple-range-fold.cc | 14 +- gcc/gimple-range-gori.cc | 7 +- gcc/gimple-range-op.cc | 42 +-- gcc/gimple-range-tests.cc | 9 +- gcc/gimple-ssa-warn-alloca.cc | 5 +- gcc/ipa-cp.cc | 10 +- gcc/ipa-prop.cc | 3 +- gcc/ipa-prop.h | 5 +- gcc/range-op.cc | 263 +++++++++--------- gcc/range.cc | 7 +- gcc/range.h | 14 +- gcc/tree-data-ref.cc | 7 +- gcc/tree-ssa-loop-ch.cc | 8 +- gcc/tree-ssa-loop-unswitch.cc | 17 +- gcc/tree-ssa-phiopt.cc | 3 +- gcc/tree-ssa-threadbackward.cc | 4 +- gcc/tree-ssanames.cc | 5 +- gcc/tree-vrp.cc | 8 +- gcc/value-query.cc | 17 +- gcc/value-range.cc | 472 ++++++++++++++++++++------------- gcc/value-range.h | 75 ++++-- gcc/vr-values.cc | 27 +- 26 files changed, 608 insertions(+), 440 deletions(-) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 7d2352dbcdd..db54bfc5662 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -10882,8 +10882,7 @@ expr_not_equal_to (tree t, const wide_int &w) else get_global_range_query ()->range_of_expr (vr, t); - if (!vr.undefined_p () - && !vr.contains_p (wide_int_to_tree (TREE_TYPE (t), w))) + if (!vr.undefined_p () && !vr.contains_p (w)) return true; /* If T has some known zero bits and W has any of those bits set, then T is known not to be equal to W. */ diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 1d0e4c32c40..581575b65ec 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -873,8 +873,8 @@ size_must_be_zero_p (tree size) /* Compute the value of SSIZE_MAX, the largest positive value that can be stored in ssize_t, the signed counterpart of size_t. */ wide_int ssize_max = wi::lshift (wi::one (prec), prec - 1) - 1; - value_range valid_range (build_int_cst (type, 0), - wide_int_to_tree (type, ssize_max)); + wide_int zero = wi::zero (TYPE_PRECISION (type)); + value_range valid_range (type, zero, ssize_max); value_range vr; if (cfun) get_range_query (cfun)->range_of_expr (vr, size); diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc index 640bb28016f..7b55129baa7 100644 --- a/gcc/gimple-loop-versioning.cc +++ b/gcc/gimple-loop-versioning.cc @@ -1476,7 +1476,7 @@ loop_versioning::prune_loop_conditions (class loop *loop) gimple *stmt = first_stmt (loop->header); if (get_range_query (cfun)->range_of_expr (r, name, stmt) - && !r.contains_p (build_one_cst (TREE_TYPE (name)))) + && !r.contains_p (wi::one (TYPE_PRECISION (TREE_TYPE (name))))) { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, find_loop_location (loop), diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 22fb709c9b1..5fc7e791c1b 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -59,9 +59,9 @@ gcond_edge_range (irange &r, edge e) { gcc_checking_assert (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)); if (e->flags & EDGE_TRUE_VALUE) - r = int_range<2> (boolean_true_node, boolean_true_node); + r = range_true (); else - r = int_range<2> (boolean_false_node, boolean_false_node); + r = range_false (); } @@ -136,19 +136,22 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw) if (e == default_edge) continue; - tree low = CASE_LOW (gimple_switch_label (sw, x)); - tree high = CASE_HIGH (gimple_switch_label (sw, x)); - if (!high) + wide_int low = wi::to_wide (CASE_LOW (gimple_switch_label (sw, x))); + wide_int high; + tree tree_high = CASE_HIGH (gimple_switch_label (sw, x)); + if (tree_high) + high = wi::to_wide (tree_high); + else high = low; // Remove the case range from the default case. - int_range_max def_range (low, high); + int_range_max def_range (type, low, high); range_cast (def_range, type); def_range.invert (); default_range.intersect (def_range); // Create/union this case with anything on else on the edge. - int_range_max case_range (low, high); + int_range_max case_range (type, low, high); range_cast (case_range, type); vrange_storage *&slot = m_edge_table->get_or_insert (e, &existed); if (existed) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 180f349eda9..62875a35038 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -404,7 +404,8 @@ adjust_imagpart_expr (vrange &res, const gimple *stmt) tree cst = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (cst) == COMPLEX_CST) { - int_range<2> imag (TREE_IMAGPART (cst), TREE_IMAGPART (cst)); + wide_int w = wi::to_wide (TREE_IMAGPART (cst)); + int_range<1> imag (TREE_TYPE (TREE_IMAGPART (cst)), w, w); res.intersect (imag); } } @@ -430,8 +431,8 @@ adjust_realpart_expr (vrange &res, const gimple *stmt) tree cst = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (cst) == COMPLEX_CST) { - tree imag = TREE_REALPART (cst); - int_range<2> tmp (imag, imag); + wide_int imag = wi::to_wide (TREE_REALPART (cst)); + int_range<2> tmp (TREE_TYPE (TREE_REALPART (cst)), imag, imag); res.intersect (tmp); } } @@ -689,7 +690,8 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src) { /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't allow going from non-NULL pointer to NULL. */ - if (r.undefined_p () || !r.contains_p (build_zero_cst (r.type ()))) + if (r.undefined_p () + || !r.contains_p (wi::zero (TYPE_PRECISION (TREE_TYPE (expr))))) { /* We could here instead adjust r by off >> LOG2_BITS_PER_UNIT using POINTER_PLUS_EXPR if off_cst and just fall back to @@ -1069,7 +1071,7 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, else if (ssa1_dep1 != ssa2_dep2 || ssa1_dep2 != ssa2_dep1) return; - int_range<2> bool_one (boolean_true_node, boolean_true_node); + int_range<2> bool_one = range_true (); relation_kind relation1 = handler1.op1_op2_relation (bool_one); relation_kind relation2 = handler2.op1_op2_relation (bool_one); @@ -1081,7 +1083,7 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, // x && y is false if the relation intersection of the true cases is NULL. if (is_and && relation_intersect (relation1, relation2) == VREL_UNDEFINED) - lhs_range = int_range<2> (boolean_false_node, boolean_false_node); + lhs_range = range_false (boolean_type_node); // x || y is true if the union of the true cases is NO-RELATION.. // ie, one or the other being true covers the full range of possibilities. else if (!is_and && relation_union (relation1, relation2) == VREL_VARYING) diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 9d0cc97bf8c..a1c8d51e484 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -562,8 +562,8 @@ gori_compute::gori_compute (int not_executable_flag) { m_not_executable_flag = not_executable_flag; // Create a boolean_type true and false range. - m_bool_zero = int_range<2> (boolean_false_node, boolean_false_node); - m_bool_one = int_range<2> (boolean_true_node, boolean_true_node); + m_bool_zero = range_false (); + m_bool_one = range_true (); if (dump_file && (param_ranger_debug & RANGER_DEBUG_GORI)) tracer.enable_trace (); } @@ -731,7 +731,8 @@ range_is_either_true_or_false (const irange &r) // so true can be ~[0, 0] (i.e. [1,MAX]). tree type = r.type (); gcc_checking_assert (range_compatible_p (type, boolean_type_node)); - return (r.singleton_p () || !r.contains_p (build_zero_cst (type))); + return (r.singleton_p () + || !r.contains_p (wi::zero (TYPE_PRECISION (type)))); } // Evaluate a binary logical expression by combining the true and diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 6fa26f5d3a2..29c7c776a2c 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -276,7 +276,8 @@ public: { if (lh.singleton_p ()) { - r.set (build_one_cst (type), build_one_cst (type)); + wide_int one = wi::one (TYPE_PRECISION (type)); + r.set (type, one, one); return true; } if (cfun->after_inlining) @@ -298,7 +299,8 @@ public: { if (lh.singleton_p ()) { - r.set (build_one_cst (type), build_one_cst (type)); + wide_int one = wi::one (TYPE_PRECISION (type)); + r.set (type, one, one); return true; } if (cfun->after_inlining) @@ -359,7 +361,7 @@ public: r.update_nan (false); return true; } - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ())))) { r.set (type, frange_val_min (type), dconstm0); r.update_nan (true); @@ -589,8 +591,12 @@ cfn_toupper_tolower::get_letter_range (tree type, irange &lowers, if ((z - a == 25) && (Z - A == 25)) { - lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z)); - uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z)); + lowers = int_range<2> (type, + wi::shwi (a, TYPE_PRECISION (type)), + wi::shwi (z, TYPE_PRECISION (type))); + uppers = int_range<2> (type, + wi::shwi (A, TYPE_PRECISION (type)), + wi::shwi (Z, TYPE_PRECISION (type))); return true; } // Unknown character set. @@ -648,7 +654,7 @@ public: range_cast (tmp, unsigned_type_for (tmp.type ())); wide_int max = tmp.upper_bound (); maxi = wi::floor_log2 (max) + 1; - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + r.set (type, wi::shwi (mini, prec), wi::shwi (maxi, prec)); return true; } } op_cfn_ffs; @@ -753,7 +759,9 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh, if (mini == -2) return false; - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + r.set (type, + wi::shwi (mini, TYPE_PRECISION (type)), + wi::shwi (maxi, TYPE_PRECISION (type))); return true; } @@ -823,7 +831,9 @@ cfn_ctz::fold_range (irange &r, tree type, const irange &lh, if (mini == -2) return false; - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + r.set (type, + wi::shwi (mini, TYPE_PRECISION (type)), + wi::shwi (maxi, TYPE_PRECISION (type))); return true; } @@ -839,7 +849,9 @@ public: if (lh.undefined_p ()) return false; int prec = TYPE_PRECISION (lh.type ()); - r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1)); + r.set (type, + wi::zero (TYPE_PRECISION (type)), + wi::shwi (prec - 1, TYPE_PRECISION (type))); return true; } } op_cfn_clrsb; @@ -891,14 +903,12 @@ public: tree max = vrp_val_max (ptrdiff_type_node); wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); - tree range_min = build_zero_cst (type); // To account for the terminating NULL, the maximum length // is one less than the maximum array size, which in turn // is one less than PTRDIFF_MAX (or SIZE_MAX where it's // smaller than the former type). // FIXME: Use max_object_size() - 1 here. - tree range_max = wide_int_to_tree (type, wmax - 2); - r.set (range_min, range_max); + r.set (type, wi::zero (TYPE_PRECISION (type)), wmax - 2); return true; } } op_cfn_strlen; @@ -922,9 +932,11 @@ public: // If it's dynamic, the backend might know a hardware limitation. size = targetm.goacc.dim_limit (axis); - r.set (build_int_cst (type, m_is_pos ? 0 : 1), + r.set (type, + wi::shwi (m_is_pos ? 0 : 1, TYPE_PRECISION (type)), size - ? build_int_cst (type, size - m_is_pos) : vrp_val_max (type)); + ? wi::shwi (size - m_is_pos, TYPE_PRECISION (type)) + : wi::to_wide (vrp_val_max (type))); return true; } private: @@ -940,7 +952,7 @@ public: virtual bool fold_range (irange &r, tree type, const irange &, const irange &, relation_trio) const { - r.set (build_zero_cst (type), build_one_cst (type)); + r = range_true_and_false (type); return true; } } op_cfn_parity; diff --git a/gcc/gimple-range-tests.cc b/gcc/gimple-range-tests.cc index 7e4d234ddda..c325a7bcebd 100644 --- a/gcc/gimple-range-tests.cc +++ b/gcc/gimple-range-tests.cc @@ -35,7 +35,9 @@ public: // [5,10] + [15,20] => [20, 30] tree expr = fold_build2 (PLUS_EXPR, type, op0, op1); - int_range<2> expect (build_int_cst (type, 20), build_int_cst (type, 30)); + int_range<1> expect (type, + wi::shwi (20, TYPE_PRECISION (type)), + wi::shwi (30, TYPE_PRECISION (type))); int_range_max r; ASSERT_TRUE (range_of_expr (r, expr)); @@ -45,14 +47,15 @@ public: virtual bool range_of_expr (vrange &v, tree expr, gimple * = NULL) override { irange &r = as_a (v); + unsigned prec = TYPE_PRECISION (type); if (expr == op0) { - r.set (build_int_cst (type, 5), build_int_cst (type, 10)); + r.set (type, wi::shwi (5, prec), wi::shwi (10, prec)); return true; } if (expr == op1) { - r.set (build_int_cst (type, 15), build_int_cst (type, 20)); + r.set (type, wi::shwi (15, prec), wi::shwi (20, prec)); return true; } return gimple_ranger::range_of_expr (r, expr); diff --git a/gcc/gimple-ssa-warn-alloca.cc b/gcc/gimple-ssa-warn-alloca.cc index 4374f572cd9..c129aca16e2 100644 --- a/gcc/gimple-ssa-warn-alloca.cc +++ b/gcc/gimple-ssa-warn-alloca.cc @@ -222,8 +222,9 @@ alloca_call_type (gimple *stmt, bool is_vla) && !r.varying_p ()) { // The invalid bits are anything outside of [0, MAX_SIZE]. - int_range<2> invalid_range (build_int_cst (size_type_node, 0), - build_int_cst (size_type_node, max_size), + int_range<1> invalid_range (size_type_node, + wi::shwi (0, TYPE_PRECISION (size_type_node)), + wi::shwi (max_size, TYPE_PRECISION (size_type_node)), VR_ANTI_RANGE); r.intersect (invalid_range); diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index a5b45a8e6b9..1f5e0e13872 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -1943,8 +1943,9 @@ ipa_value_range_from_jfunc (ipa_node_params *info, cgraph_edge *cs, if (!(*sum->m_vr)[idx].known) return vr; tree vr_type = ipa_get_type (info, idx); - value_range srcvr (wide_int_to_tree (vr_type, (*sum->m_vr)[idx].min), - wide_int_to_tree (vr_type, (*sum->m_vr)[idx].max), + value_range srcvr (vr_type, + (*sum->m_vr)[idx].min, + (*sum->m_vr)[idx].max, (*sum->m_vr)[idx].type); enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); @@ -2799,7 +2800,8 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, if (TREE_OVERFLOW_P (val)) val = drop_tree_overflow (val); - value_range tmpvr (val, val); + value_range tmpvr (TREE_TYPE (val), + wi::to_wide (val), wi::to_wide (val)); return dest_lat->meet_with (&tmpvr); } } @@ -6204,7 +6206,7 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, necessary. */ static inline bool -ipa_range_contains_p (const irange &r, tree val) +ipa_range_contains_p (const vrange &r, tree val) { if (r.undefined_p ()) return false; diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index c6d4585aed1..0f3cb3dd9f9 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -2220,7 +2220,8 @@ ipa_get_value_range (value_range *tmp) static value_range * ipa_get_value_range (enum value_range_kind kind, tree min, tree max) { - value_range tmp (min, max, kind); + value_range tmp (TREE_TYPE (min), + wi::to_wide (min), wi::to_wide (max), kind); return ipa_get_value_range (&tmp); } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 93785a6a8e6..d4936d4eaff 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -1208,7 +1208,10 @@ inline void ipa_range_set_and_normalize (irange &r, tree val) { if (TREE_CODE (val) == INTEGER_CST) - r.set (val, val); + { + wide_int w = wi::to_wide (val); + r.set (TREE_TYPE (val), w, w); + } else if (TREE_CODE (val) == ADDR_EXPR) r.set_nonzero (TREE_TYPE (val)); else diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 215a1613b38..224a561c170 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -119,8 +119,9 @@ get_shift_range (irange &r, tree type, const irange &op) return false; // Build valid range and intersect it with the shift range. - r = value_range (build_int_cst_type (op.type (), 0), - build_int_cst_type (op.type (), TYPE_PRECISION (type) - 1)); + r = value_range (op.type (), + wi::shwi (0, TYPE_PRECISION (op.type ())), + wi::shwi (TYPE_PRECISION (type) - 1, TYPE_PRECISION (op.type ()))); r.intersect (op); // If there are no valid ranges in the shift range, returned false. @@ -414,11 +415,7 @@ value_range_from_overflowed_bounds (irange &r, tree type, if (covers || wi::cmp (tmin, tmax, sgn) > 0) r.set_varying (type); else - { - tree tree_min = wide_int_to_tree (type, tmin); - tree tree_max = wide_int_to_tree (type, tmax); - r.set (tree_min, tree_max, VR_ANTI_RANGE); - } + r.set (type, tmin, tmax, VR_ANTI_RANGE); } // Create and return a range from a pair of wide-ints. MIN_OVF and @@ -458,8 +455,7 @@ value_range_with_overflow (irange &r, tree type, else // No overflow or both overflow or underflow. The range // kind stays normal. - r.set (wide_int_to_tree (type, tmin), - wide_int_to_tree (type, tmax)); + r.set (type, tmin, tmax); return; } @@ -497,8 +493,7 @@ value_range_with_overflow (irange &r, tree type, else new_ub = wmax; - r.set (wide_int_to_tree (type, new_lb), - wide_int_to_tree (type, new_ub)); + r.set (type, new_lb, new_ub); } } @@ -516,7 +511,7 @@ create_possibly_reversed_range (irange &r, tree type, value_range_from_overflowed_bounds (r, type, new_lb, new_ub); else // Otherwise it's just a normal range. - r.set (wide_int_to_tree (type, new_lb), wide_int_to_tree (type, new_ub)); + r.set (type, new_lb, new_ub); } // Return the summary information about boolean range LHS. If EMPTY/FULL, @@ -581,7 +576,7 @@ equal_op1_op2_relation (const irange &lhs) return VREL_NE; // TRUE = op1 == op2 indicates EQ_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (lhs.undefined_p () || !contains_zero_p (lhs)) return VREL_EQ; return VREL_VARYING; } @@ -701,7 +696,7 @@ not_equal_op1_op2_relation (const irange &lhs) return VREL_EQ; // TRUE = op1 != op2 indicates NE_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (lhs.undefined_p () || !contains_zero_p (lhs)) return VREL_NE; return VREL_VARYING; } @@ -881,7 +876,7 @@ lt_op1_op2_relation (const irange &lhs) return VREL_GE; // TRUE = op1 < op2 indicates LT_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (lhs.undefined_p () || !contains_zero_p (lhs)) return VREL_LT; return VREL_VARYING; } @@ -1001,7 +996,7 @@ le_op1_op2_relation (const irange &lhs) return VREL_GT; // TRUE = op1 <= op2 indicates LE_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (lhs.undefined_p () || !contains_zero_p (lhs)) return VREL_LE; return VREL_VARYING; } @@ -1118,7 +1113,7 @@ gt_op1_op2_relation (const irange &lhs) return VREL_LE; // TRUE = op1 > op2 indicates GT_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (!contains_zero_p (lhs)) return VREL_GT; return VREL_VARYING; } @@ -1234,7 +1229,7 @@ ge_op1_op2_relation (const irange &lhs) return VREL_LT; // TRUE = op1 >= op2 indicates GE_EXPR. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (!contains_zero_p (lhs)) return VREL_GE; return VREL_VARYING; } @@ -1963,7 +1958,6 @@ operator_mult::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, relation_trio) const { - tree offset; if (lhs.undefined_p ()) return false; @@ -1973,7 +1967,8 @@ operator_mult::op1_range (irange &r, tree type, if (TYPE_OVERFLOW_WRAPS (type)) return false; - if (op2.singleton_p (&offset) && !integer_zerop (offset)) + wide_int offset; + if (op2.singleton_p (offset) && offset != 0) return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type, lhs, op2); return false; @@ -2284,15 +2279,14 @@ operator_exact_divide::op1_range (irange &r, tree type, { if (lhs.undefined_p ()) return false; - tree offset; + wide_int offset; // [2, 4] = op1 / [3,3] since its exact divide, no need to worry about // remainders in the endpoints, so op1 = [2,4] * [3,3] = [6,12]. // We wont bother trying to enumerate all the in between stuff :-P // TRUE accuracy is [6,6][9,9][12,12]. This is unlikely to matter most of // the time however. // If op2 is a multiple of 2, we would be able to set some non-zero bits. - if (op2.singleton_p (&offset) - && !integer_zerop (offset)) + if (op2.singleton_p (offset) && offset != 0) return range_op_handler (MULT_EXPR, type).fold_range (r, type, lhs, op2); return false; } @@ -2495,16 +2489,15 @@ operator_lshift::op1_range (irange &r, { if (lhs.undefined_p ()) return false; - tree shift_amount; - if (!lhs.contains_p (build_zero_cst (type))) + if (!contains_zero_p (lhs)) r.set_nonzero (type); else r.set_varying (type); - if (op2.singleton_p (&shift_amount)) + wide_int shift; + if (op2.singleton_p (shift)) { - wide_int shift = wi::to_wide (shift_amount); if (wi::lt_p (shift, 0, SIGNED)) return false; if (wi::ge_p (shift, wi::uhwi (TYPE_PRECISION (type), @@ -2541,8 +2534,7 @@ operator_lshift::op1_range (irange &r, // This would be [0x42, 0xFC] aka [01000010, 11111100]. // Ideally we do this for each subrange, but just lump them all for now. - unsigned low_bits = TYPE_PRECISION (utype) - - TREE_INT_CST_LOW (shift_amount); + unsigned low_bits = TYPE_PRECISION (utype) - shift.to_uhwi (); wide_int up_mask = wi::mask (low_bits, true, TYPE_PRECISION (utype)); wide_int new_ub = wi::bit_or (up_mask, tmp_range.upper_bound ()); wide_int new_lb = wi::set_bit (tmp_range.lower_bound (), low_bits); @@ -2566,18 +2558,18 @@ operator_rshift::op1_range (irange &r, const irange &op2, relation_trio) const { - tree shift; if (lhs.undefined_p ()) return false; - if (op2.singleton_p (&shift)) + wide_int shift; + if (op2.singleton_p (shift)) { // Ignore nonsensical shifts. unsigned prec = TYPE_PRECISION (type); - if (wi::ge_p (wi::to_wide (shift), - wi::uhwi (prec, TYPE_PRECISION (TREE_TYPE (shift))), + if (wi::ge_p (shift, + wi::uhwi (prec, TYPE_PRECISION (op2.type ())), UNSIGNED)) return false; - if (wi::to_wide (shift) == 0) + if (shift == 0) { r = lhs; return true; @@ -2593,7 +2585,7 @@ operator_rshift::op1_range (irange &r, r.set_undefined (); return true; } - int_range_max shift_range (shift, shift); + int_range_max shift_range (op2.type (), shift, shift); int_range_max lb, ub; op_lshift.fold_range (lb, type, lhs_refined, shift_range); // LHS @@ -2605,12 +2597,14 @@ operator_rshift::op1_range (irange &r, tree mask = fold_build1 (BIT_NOT_EXPR, type, fold_build2 (LSHIFT_EXPR, type, build_minus_one_cst (type), - shift)); - int_range_max mask_range (build_zero_cst (type), mask); + wide_int_to_tree (op2.type (), shift))); + int_range_max mask_range (type, + wi::zero (TYPE_PRECISION (type)), + wi::to_wide (mask)); op_plus.fold_range (ub, type, lb, mask_range); r = lb; r.union_ (ub); - if (!lhs_refined.contains_p (build_zero_cst (type))) + if (!contains_zero_p (lhs_refined)) { mask_range.invert (); r.intersect (mask_range); @@ -2853,7 +2847,7 @@ operator_cast::op1_range (irange &r, tree type, { // If the LHS is not a pointer nor a singleton, then it is // either VARYING or non-zero. - if (!lhs.contains_p (build_zero_cst (lhs.type ()))) + if (!contains_zero_p (lhs)) r.set_nonzero (type); else r.set_varying (type); @@ -2971,8 +2965,7 @@ operator_logical_and::fold_range (irange &r, tree type, if ((wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (lh.upper_bound (), 0)) || (wi::eq_p (lh.lower_bound (), 0) && wi::eq_p (rh.upper_bound (), 0))) r = range_false (type); - else if (lh.contains_p (build_zero_cst (lh.type ())) - || rh.contains_p (build_zero_cst (rh.type ()))) + else if (contains_zero_p (lh) || contains_zero_p (rh)) // To reach this point, there must be a logical 1 on each side, and // the only remaining question is whether there is a zero or not. r = range_true_and_false (type); @@ -3288,7 +3281,7 @@ operator_bitwise_and::wi_fold (irange &r, tree type, static void set_nonzero_range_from_mask (irange &r, tree type, const irange &lhs) { - if (!lhs.contains_p (build_zero_cst (type))) + if (!contains_zero_p (lhs)) r = range_nonzero (type); else r.set_varying (type); @@ -3605,8 +3598,7 @@ operator_bitwise_or::op1_range (irange &r, tree type, if (lhs.zero_p ()) { - tree zero = build_zero_cst (type); - r = int_range<1> (zero, zero); + r.set_zero (type); return true; } r.set_varying (type); @@ -3743,7 +3735,7 @@ operator_bitwise_xor::op1_range (irange &r, tree type, else if (op2.zero_p ()) r = range_true (type); // See get_bool_state for the rationale - else if (op2.contains_p (build_zero_cst (op2.type ()))) + else if (contains_zero_p (op2)) r = range_true_and_false (type); else r = range_false (type); @@ -4346,7 +4338,7 @@ operator_addr_expr::fold_range (irange &r, tree type, // Return a non-null pointer of the LHS type (passed in op2). if (lh.zero_p ()) r = range_zero (type); - else if (!lh.contains_p (build_zero_cst (lh.type ()))) + else if (!contains_zero_p (lh)) r = range_nonzero (type); else r.set_varying (type); @@ -4387,8 +4379,7 @@ pointer_plus_operator::wi_fold (irange &r, tree type, // Check for [0,0] + const, and simply return the const. if (lh_lb == 0 && lh_ub == 0 && rh_lb == rh_ub) { - tree val = wide_int_to_tree (type, rh_lb); - r.set (val, val); + r.set (type, rh_lb, rh_lb); return; } @@ -4522,8 +4513,7 @@ pointer_or_operator::op1_range (irange &r, tree type, return false; if (lhs.zero_p ()) { - tree zero = build_zero_cst (type); - r = int_range<1> (zero, zero); + r.set_zero (type); return true; } r.set_varying (type); @@ -4880,112 +4870,120 @@ range_cast (vrange &r, tree type) namespace selftest { -#define INT(N) build_int_cst (integer_type_node, (N)) -#define UINT(N) build_int_cstu (unsigned_type_node, (N)) -#define INT16(N) build_int_cst (short_integer_type_node, (N)) -#define UINT16(N) build_int_cstu (short_unsigned_type_node, (N)) -#define SCHAR(N) build_int_cst (signed_char_type_node, (N)) -#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N)) +#define INT(x) wi::shwi ((x), TYPE_PRECISION (integer_type_node)) +#define UINT(x) wi::uhwi ((x), TYPE_PRECISION (unsigned_type_node)) +#define INT16(x) wi::shwi ((x), TYPE_PRECISION (short_integer_type_node)) +#define UINT16(x) wi::uhwi ((x), TYPE_PRECISION (short_unsigned_type_node)) +#define SCHAR(x) wi::shwi ((x), TYPE_PRECISION (signed_char_type_node)) +#define UCHAR(x) wi::uhwi ((x), TYPE_PRECISION (unsigned_char_type_node)) static void range_op_cast_tests () { int_range<2> r0, r1, r2, rold; r0.set_varying (integer_type_node); - tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ()); + wide_int maxint = r0.upper_bound (); // If a range is in any way outside of the range for the converted // to range, default to the range for the new type. r0.set_varying (short_integer_type_node); - tree minshort = wide_int_to_tree (short_integer_type_node, r0.lower_bound ()); - tree maxshort = wide_int_to_tree (short_integer_type_node, r0.upper_bound ()); - if (TYPE_PRECISION (TREE_TYPE (maxint)) + wide_int minshort = r0.lower_bound (); + wide_int maxshort = r0.upper_bound (); + if (TYPE_PRECISION (integer_type_node) > TYPE_PRECISION (short_integer_type_node)) { - r1 = int_range<1> (integer_zero_node, maxint); + r1 = int_range<1> (integer_type_node, + wi::zero (TYPE_PRECISION (integer_type_node)), + maxint); range_cast (r1, short_integer_type_node); - ASSERT_TRUE (r1.lower_bound () == wi::to_wide (minshort) - && r1.upper_bound() == wi::to_wide (maxshort)); + ASSERT_TRUE (r1.lower_bound () == minshort + && r1.upper_bound() == maxshort); } // (unsigned char)[-5,-1] => [251,255]. - r0 = rold = int_range<1> (SCHAR (-5), SCHAR (-1)); + r0 = rold = int_range<1> (signed_char_type_node, SCHAR (-5), SCHAR (-1)); range_cast (r0, unsigned_char_type_node); - ASSERT_TRUE (r0 == int_range<1> (UCHAR (251), UCHAR (255))); + ASSERT_TRUE (r0 == int_range<1> (unsigned_char_type_node, + UCHAR (251), UCHAR (255))); range_cast (r0, signed_char_type_node); ASSERT_TRUE (r0 == rold); // (signed char)[15, 150] => [-128,-106][15,127]. - r0 = rold = int_range<1> (UCHAR (15), UCHAR (150)); + r0 = rold = int_range<1> (unsigned_char_type_node, UCHAR (15), UCHAR (150)); range_cast (r0, signed_char_type_node); - r1 = int_range<1> (SCHAR (15), SCHAR (127)); - r2 = int_range<1> (SCHAR (-128), SCHAR (-106)); + r1 = int_range<1> (signed_char_type_node, SCHAR (15), SCHAR (127)); + r2 = int_range<1> (signed_char_type_node, SCHAR (-128), SCHAR (-106)); r1.union_ (r2); ASSERT_TRUE (r1 == r0); range_cast (r0, unsigned_char_type_node); ASSERT_TRUE (r0 == rold); // (unsigned char)[-5, 5] => [0,5][251,255]. - r0 = rold = int_range<1> (SCHAR (-5), SCHAR (5)); + r0 = rold = int_range<1> (signed_char_type_node, SCHAR (-5), SCHAR (5)); range_cast (r0, unsigned_char_type_node); - r1 = int_range<1> (UCHAR (251), UCHAR (255)); - r2 = int_range<1> (UCHAR (0), UCHAR (5)); + r1 = int_range<1> (unsigned_char_type_node, UCHAR (251), UCHAR (255)); + r2 = int_range<1> (unsigned_char_type_node, UCHAR (0), UCHAR (5)); r1.union_ (r2); ASSERT_TRUE (r0 == r1); range_cast (r0, signed_char_type_node); ASSERT_TRUE (r0 == rold); // (unsigned char)[-5,5] => [0,5][251,255]. - r0 = int_range<1> (INT (-5), INT (5)); + r0 = int_range<1> (integer_type_node, INT (-5), INT (5)); range_cast (r0, unsigned_char_type_node); - r1 = int_range<1> (UCHAR (0), UCHAR (5)); - r1.union_ (int_range<1> (UCHAR (251), UCHAR (255))); + r1 = int_range<1> (unsigned_char_type_node, UCHAR (0), UCHAR (5)); + r1.union_ (int_range<1> (unsigned_char_type_node, UCHAR (251), UCHAR (255))); ASSERT_TRUE (r0 == r1); // (unsigned char)[5U,1974U] => [0,255]. - r0 = int_range<1> (UINT (5), UINT (1974)); + r0 = int_range<1> (unsigned_type_node, UINT (5), UINT (1974)); range_cast (r0, unsigned_char_type_node); - ASSERT_TRUE (r0 == int_range<1> (UCHAR (0), UCHAR (255))); + ASSERT_TRUE (r0 == int_range<1> (unsigned_char_type_node, UCHAR (0), UCHAR (255))); range_cast (r0, integer_type_node); // Going to a wider range should not sign extend. - ASSERT_TRUE (r0 == int_range<1> (INT (0), INT (255))); + ASSERT_TRUE (r0 == int_range<1> (integer_type_node, INT (0), INT (255))); // (unsigned char)[-350,15] => [0,255]. - r0 = int_range<1> (INT (-350), INT (15)); + r0 = int_range<1> (integer_type_node, INT (-350), INT (15)); range_cast (r0, unsigned_char_type_node); ASSERT_TRUE (r0 == (int_range<1> - (TYPE_MIN_VALUE (unsigned_char_type_node), - TYPE_MAX_VALUE (unsigned_char_type_node)))); + (unsigned_char_type_node, + min_limit (unsigned_char_type_node), + max_limit (unsigned_char_type_node)))); // Casting [-120,20] from signed char to unsigned short. // => [0, 20][0xff88, 0xffff]. - r0 = int_range<1> (SCHAR (-120), SCHAR (20)); + r0 = int_range<1> (signed_char_type_node, SCHAR (-120), SCHAR (20)); range_cast (r0, short_unsigned_type_node); - r1 = int_range<1> (UINT16 (0), UINT16 (20)); - r2 = int_range<1> (UINT16 (0xff88), UINT16 (0xffff)); + r1 = int_range<1> (short_unsigned_type_node, UINT16 (0), UINT16 (20)); + r2 = int_range<1> (short_unsigned_type_node, + UINT16 (0xff88), UINT16 (0xffff)); r1.union_ (r2); ASSERT_TRUE (r0 == r1); // A truncating cast back to signed char will work because [-120, 20] // is representable in signed char. range_cast (r0, signed_char_type_node); - ASSERT_TRUE (r0 == int_range<1> (SCHAR (-120), SCHAR (20))); + ASSERT_TRUE (r0 == int_range<1> (signed_char_type_node, + SCHAR (-120), SCHAR (20))); // unsigned char -> signed short // (signed short)[(unsigned char)25, (unsigned char)250] // => [(signed short)25, (signed short)250] - r0 = rold = int_range<1> (UCHAR (25), UCHAR (250)); + r0 = rold = int_range<1> (unsigned_char_type_node, UCHAR (25), UCHAR (250)); range_cast (r0, short_integer_type_node); - r1 = int_range<1> (INT16 (25), INT16 (250)); + r1 = int_range<1> (short_integer_type_node, INT16 (25), INT16 (250)); ASSERT_TRUE (r0 == r1); range_cast (r0, unsigned_char_type_node); ASSERT_TRUE (r0 == rold); // Test casting a wider signed [-MIN,MAX] to a narrower unsigned. - r0 = int_range<1> (TYPE_MIN_VALUE (long_long_integer_type_node), - TYPE_MAX_VALUE (long_long_integer_type_node)); + r0 = int_range<1> (long_long_integer_type_node, + min_limit (long_long_integer_type_node), + max_limit (long_long_integer_type_node)); range_cast (r0, short_unsigned_type_node); - r1 = int_range<1> (TYPE_MIN_VALUE (short_unsigned_type_node), - TYPE_MAX_VALUE (short_unsigned_type_node)); + r1 = int_range<1> (short_unsigned_type_node, + min_limit (short_unsigned_type_node), + max_limit (short_unsigned_type_node)); ASSERT_TRUE (r0 == r1); // Casting NONZERO to a narrower type will wrap/overflow so @@ -4999,8 +4997,9 @@ range_op_cast_tests () { r0 = range_nonzero (integer_type_node); range_cast (r0, short_integer_type_node); - r1 = int_range<1> (TYPE_MIN_VALUE (short_integer_type_node), - TYPE_MAX_VALUE (short_integer_type_node)); + r1 = int_range<1> (short_integer_type_node, + min_limit (short_integer_type_node), + max_limit (short_integer_type_node)); ASSERT_TRUE (r0 == r1); } @@ -5010,8 +5009,8 @@ range_op_cast_tests () // Converting this to 32-bits signed is [-MIN_16,-1][1, +MAX_16]. r0 = range_nonzero (short_integer_type_node); range_cast (r0, integer_type_node); - r1 = int_range<1> (INT (-32768), INT (-1)); - r2 = int_range<1> (INT (1), INT (32767)); + r1 = int_range<1> (integer_type_node, INT (-32768), INT (-1)); + r2 = int_range<1> (integer_type_node, INT (1), INT (32767)); r1.union_ (r2); ASSERT_TRUE (r0 == r1); } @@ -5024,17 +5023,16 @@ range_op_lshift_tests () { int_range_max res; tree big_type = long_long_unsigned_type_node; + unsigned big_prec = TYPE_PRECISION (big_type); // big_num = 0x808,0000,0000,0000 - tree big_num = fold_build2 (LSHIFT_EXPR, big_type, - build_int_cst (big_type, 0x808), - build_int_cst (big_type, 48)); + wide_int big_num = wi::lshift (wi::uhwi (0x808, big_prec), + wi::uhwi (48, big_prec)); op_bitwise_and.fold_range (res, big_type, int_range <1> (big_type), - int_range <1> (big_num, big_num)); + int_range <1> (big_type, big_num, big_num)); // val = 0x8,0000,0000,0000 - tree val = fold_build2 (LSHIFT_EXPR, big_type, - build_int_cst (big_type, 0x8), - build_int_cst (big_type, 48)); + wide_int val = wi::lshift (wi::uhwi (8, big_prec), + wi::uhwi (48, big_prec)); ASSERT_TRUE (res.contains_p (val)); } @@ -5042,13 +5040,13 @@ range_op_lshift_tests () { // unsigned VARYING = op1 << 1 should be VARYING. int_range<2> lhs (unsigned_type_node); - int_range<2> shift (INT (1), INT (1)); + int_range<2> shift (unsigned_type_node, INT (1), INT (1)); int_range_max op1; op_lshift.op1_range (op1, unsigned_type_node, lhs, shift); ASSERT_TRUE (op1.varying_p ()); // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000]. - int_range<2> zero (UINT (0), UINT (0)); + int_range<2> zero (unsigned_type_node, UINT (0), UINT (0)); op_lshift.op1_range (op1, unsigned_type_node, zero, shift); ASSERT_TRUE (op1.num_pairs () == 2); // Remove the [0,0] range. @@ -5065,13 +5063,13 @@ range_op_lshift_tests () { // unsigned VARYING = op1 << 1 should be VARYING. int_range<2> lhs (integer_type_node); - int_range<2> shift (INT (1), INT (1)); + int_range<2> shift (integer_type_node, INT (1), INT (1)); int_range_max op1; op_lshift.op1_range (op1, integer_type_node, lhs, shift); ASSERT_TRUE (op1.varying_p ()); // 0 = op1 << 1 should be [0,0], [0x8000000, 0x8000000]. - int_range<2> zero (INT (0), INT (0)); + int_range<2> zero (integer_type_node, INT (0), INT (0)); op_lshift.op1_range (op1, integer_type_node, zero, shift); ASSERT_TRUE (op1.num_pairs () == 2); // Remove the [0,0] range. @@ -5090,10 +5088,11 @@ range_op_rshift_tests () { // unsigned: [3, MAX] = OP1 >> 1 { - int_range_max lhs (build_int_cst (unsigned_type_node, 3), - TYPE_MAX_VALUE (unsigned_type_node)); - int_range_max one (build_one_cst (unsigned_type_node), - build_one_cst (unsigned_type_node)); + int_range_max lhs (unsigned_type_node, + UINT (3), max_limit (unsigned_type_node)); + int_range_max one (unsigned_type_node, + wi::one (TYPE_PRECISION (unsigned_type_node)), + wi::one (TYPE_PRECISION (unsigned_type_node))); int_range_max op1; op_rshift.op1_range (op1, unsigned_type_node, lhs, one); ASSERT_FALSE (op1.contains_p (UINT (3))); @@ -5101,8 +5100,9 @@ range_op_rshift_tests () // signed: [3, MAX] = OP1 >> 1 { - int_range_max lhs (INT (3), TYPE_MAX_VALUE (integer_type_node)); - int_range_max one (INT (1), INT (1)); + int_range_max lhs (integer_type_node, + INT (3), max_limit (integer_type_node)); + int_range_max one (integer_type_node, INT (1), INT (1)); int_range_max op1; op_rshift.op1_range (op1, integer_type_node, lhs, one); ASSERT_FALSE (op1.contains_p (INT (-2))); @@ -5111,9 +5111,10 @@ range_op_rshift_tests () // This is impossible, so OP1 should be []. // signed: [MIN, MIN] = OP1 >> 1 { - int_range_max lhs (TYPE_MIN_VALUE (integer_type_node), - TYPE_MIN_VALUE (integer_type_node)); - int_range_max one (INT (1), INT (1)); + int_range_max lhs (integer_type_node, + min_limit (integer_type_node), + min_limit (integer_type_node)); + int_range_max one (integer_type_node, INT (1), INT (1)); int_range_max op1; op_rshift.op1_range (op1, integer_type_node, lhs, one); ASSERT_TRUE (op1.undefined_p ()); @@ -5122,8 +5123,8 @@ range_op_rshift_tests () // signed: ~[-1] = OP1 >> 31 if (TYPE_PRECISION (integer_type_node) > 31) { - int_range_max lhs (INT (-1), INT (-1), VR_ANTI_RANGE); - int_range_max shift (INT (31), INT (31)); + int_range_max lhs (integer_type_node, INT (-1), INT (-1), VR_ANTI_RANGE); + int_range_max shift (integer_type_node, INT (31), INT (31)); int_range_max op1; op_rshift.op1_range (op1, integer_type_node, lhs, shift); int_range_max negatives = range_negatives (integer_type_node); @@ -5136,13 +5137,11 @@ static void range_op_bitwise_and_tests () { int_range_max res; - tree min = vrp_val_min (integer_type_node); - tree max = vrp_val_max (integer_type_node); - tree tiny = fold_build2 (PLUS_EXPR, integer_type_node, min, - build_one_cst (integer_type_node)); - int_range_max i1 (tiny, max); - int_range_max i2 (build_int_cst (integer_type_node, 255), - build_int_cst (integer_type_node, 255)); + wide_int min = min_limit (integer_type_node); + wide_int max = max_limit (integer_type_node); + wide_int tiny = wi::add (min, wi::one (TYPE_PRECISION (integer_type_node))); + int_range_max i1 (integer_type_node, tiny, max); + int_range_max i2 (integer_type_node, INT (255), INT (255)); // [MIN+1, MAX] = OP1 & 255: OP1 is VARYING op_bitwise_and.op1_range (res, integer_type_node, i1, i2); @@ -5155,8 +5154,8 @@ range_op_bitwise_and_tests () // For 0 = x & MASK, x is ~MASK. { - int_range<2> zero (integer_zero_node, integer_zero_node); - int_range<2> mask = int_range<2> (INT (7), INT (7)); + int_range<2> zero (integer_type_node, INT (0), INT (0)); + int_range<2> mask = int_range<2> (integer_type_node, INT (7), INT (7)); op_bitwise_and.op1_range (res, integer_type_node, zero, mask); wide_int inv = wi::shwi (~7U, TYPE_PRECISION (integer_type_node)); ASSERT_TRUE (res.get_nonzero_bits () == inv); @@ -5169,7 +5168,7 @@ range_op_bitwise_and_tests () ASSERT_TRUE (res.nonzero_p ()); // (NEGATIVE | X) is nonzero. - i1 = int_range<1> (INT (-5), INT (-3)); + i1 = int_range<1> (integer_type_node, INT (-5), INT (-3)); i2.set_varying (integer_type_node); op_bitwise_or.fold_range (res, integer_type_node, i1, i2); ASSERT_FALSE (res.contains_p (INT (0))); @@ -5179,22 +5178,22 @@ static void range_relational_tests () { int_range<2> lhs (unsigned_char_type_node); - int_range<2> op1 (UCHAR (8), UCHAR (10)); - int_range<2> op2 (UCHAR (20), UCHAR (20)); + int_range<2> op1 (unsigned_char_type_node, UCHAR (8), UCHAR (10)); + int_range<2> op2 (unsigned_char_type_node, UCHAR (20), UCHAR (20)); // Never wrapping additions mean LHS > OP1. relation_kind code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING); ASSERT_TRUE (code == VREL_GT); // Most wrapping additions mean nothing... - op1 = int_range<2> (UCHAR (8), UCHAR (10)); - op2 = int_range<2> (UCHAR (0), UCHAR (255)); + op1 = int_range<2> (unsigned_char_type_node, UCHAR (8), UCHAR (10)); + op2 = int_range<2> (unsigned_char_type_node, UCHAR (0), UCHAR (255)); code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING); ASSERT_TRUE (code == VREL_VARYING); // However, always wrapping additions mean LHS < OP1. - op1 = int_range<2> (UCHAR (1), UCHAR (255)); - op2 = int_range<2> (UCHAR (255), UCHAR (255)); + op1 = int_range<2> (unsigned_char_type_node, UCHAR (1), UCHAR (255)); + op2 = int_range<2> (unsigned_char_type_node, UCHAR (255), UCHAR (255)); code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_VARYING); ASSERT_TRUE (code == VREL_LT); } diff --git a/gcc/range.cc b/gcc/range.cc index d9e9e0c788c..7c4a83032d7 100644 --- a/gcc/range.cc +++ b/gcc/range.cc @@ -32,14 +32,15 @@ along with GCC; see the file COPYING3. If not see value_range range_zero (tree type) { - return value_range (build_zero_cst (type), build_zero_cst (type)); + wide_int zero = wi::zero (TYPE_PRECISION (type)); + return value_range (type, zero, zero); } value_range range_nonzero (tree type) { - return value_range (build_zero_cst (type), build_zero_cst (type), - VR_ANTI_RANGE); + wide_int zero = wi::zero (TYPE_PRECISION (type)); + return value_range (type, zero, zero, VR_ANTI_RANGE); } value_range diff --git a/gcc/range.h b/gcc/range.h index 3b0e9efffbf..f6a55baf80e 100644 --- a/gcc/range.h +++ b/gcc/range.h @@ -29,30 +29,30 @@ value_range range_negatives (tree type); // Return an irange instance that is a boolean TRUE. inline int_range<1> -range_true (tree type) +range_true (tree type = boolean_type_node) { unsigned prec = TYPE_PRECISION (type); - return int_range<2> (type, wi::one (prec), wi::one (prec)); + return int_range<1> (type, wi::one (prec), wi::one (prec)); } // Return an irange instance that is a boolean FALSE. inline int_range<1> -range_false (tree type) +range_false (tree type = boolean_type_node) { unsigned prec = TYPE_PRECISION (type); - return int_range<2> (type, wi::zero (prec), wi::zero (prec)); + return int_range<1> (type, wi::zero (prec), wi::zero (prec)); } // Return an irange that covers both true and false. inline int_range<1> -range_true_and_false (tree type) +range_true_and_false (tree type = boolean_type_node) { unsigned prec = TYPE_PRECISION (type); if (prec == 1) - return int_range<2> (type); - return int_range<2> (type, wi::zero (prec), wi::one (prec)); + return int_range<1> (type); + return int_range<1> (type, wi::zero (prec), wi::one (prec)); } #endif // GCC_RANGE_H diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index b3a1d410cbd..b576cce6db6 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -769,7 +769,10 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, *var = size_int (0); *off = fold_convert (ssizetype, op0); if (result_range) - result_range->set (op0, op0); + { + wide_int w = wi::to_wide (op0); + result_range->set (TREE_TYPE (op0), w, w); + } return true; case POINTER_PLUS_EXPR: @@ -795,7 +798,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, return false; split_constant_offset (op0, &var0, &off0, &op0_range, cache, limit); - op1_range.set (op1, op1); + op1_range.set (TREE_TYPE (op1), wi::to_wide (op1), wi::to_wide (op1)); *off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, op1)); if (!compute_distributive_range (type, op0_range, code, op1_range, off, result_range)) diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc index 83c2c1c6792..692e8ce7c38 100644 --- a/gcc/tree-ssa-loop-ch.cc +++ b/gcc/tree-ssa-loop-ch.cc @@ -79,15 +79,15 @@ entry_loop_condition_is_static (class loop *l, gimple_ranger *ranger) if (!loop_exit_edge_p (l, true_e) && !loop_exit_edge_p (l, false_e)) return false; - tree desired_static_value; + int_range<1> desired_static_range; if (loop_exit_edge_p (l, true_e)) - desired_static_value = boolean_false_node; + desired_static_range = range_false (); else - desired_static_value = boolean_true_node; + desired_static_range = range_true (); int_range<2> r; edge_range_query (r, e, last, *ranger); - return r == int_range<2> (desired_static_value, desired_static_value); + return r == desired_static_range; } /* Check whether we should duplicate HEADER of LOOP. At most *LIMIT diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc index 588610eaa47..081fb42ba54 100644 --- a/gcc/tree-ssa-loop-unswitch.cc +++ b/gcc/tree-ssa-loop-unswitch.cc @@ -142,14 +142,14 @@ struct unswitch_predicate auto range_op = range_op_handler (code, TREE_TYPE (lhs)); int_range<2> rhs_range (TREE_TYPE (rhs)); if (CONSTANT_CLASS_P (rhs)) - rhs_range.set (rhs, rhs); + { + wide_int w = wi::to_wide (rhs); + rhs_range.set (TREE_TYPE (rhs), w, w); + } if (!range_op.op1_range (true_range, TREE_TYPE (lhs), - int_range<2> (boolean_true_node, - boolean_true_node), rhs_range) + range_true (), rhs_range) || !range_op.op1_range (false_range, TREE_TYPE (lhs), - int_range<2> (boolean_false_node, - boolean_false_node), - rhs_range)) + range_false (), rhs_range)) { true_range.set_varying (TREE_TYPE (lhs)); false_range.set_varying (TREE_TYPE (lhs)); @@ -605,12 +605,13 @@ find_unswitching_predicates_for_bb (basic_block bb, class loop *loop, tree cmp1 = fold_build2 (GE_EXPR, boolean_type_node, idx, low); tree cmp2 = fold_build2 (LE_EXPR, boolean_type_node, idx, high); cmp = fold_build2 (BIT_AND_EXPR, boolean_type_node, cmp1, cmp2); - lab_range.set (low, high); + lab_range.set (idx_type, wi::to_wide (low), wi::to_wide (high)); } else { cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx, low); - lab_range.set (low, low); + wide_int w = wi::to_wide (low); + lab_range.set (idx_type, w, w); } /* Combine the expression with the existing one. */ diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 4b43f1abdbc..874526f0baa 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -1138,7 +1138,8 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, if (get_global_range_query ()->range_of_expr (r, phires, phi)) { - int_range<2> tmp (carg, carg); + wide_int warg = wi::to_wide (carg); + int_range<2> tmp (TREE_TYPE (carg), warg, warg); r.union_ (tmp); reset_flow_sensitive_info (phires); set_range_info (phires, r); diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index 962b33d88da..d5da4b0c1b1 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -327,8 +327,8 @@ back_threader::find_taken_edge_cond (const vec &path, if (solver.unreachable_path_p ()) return UNREACHABLE_EDGE; - int_range<2> true_range (boolean_true_node, boolean_true_node); - int_range<2> false_range (boolean_false_node, boolean_false_node); + int_range<2> true_range = range_true (); + int_range<2> false_range = range_false (); if (r == true_range || r == false_range) { diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc index b6cbf97b878..a510dfa031a 100644 --- a/gcc/tree-ssanames.cc +++ b/gcc/tree-ssanames.cc @@ -522,10 +522,9 @@ ssa_name_has_boolean_range (tree op) if (INTEGRAL_TYPE_P (TREE_TYPE (op)) && (TYPE_PRECISION (TREE_TYPE (op)) > 1)) { - int_range<2> onezero (build_zero_cst (TREE_TYPE (op)), - build_one_cst (TREE_TYPE (op))); int_range<2> r; - if (get_range_query (cfun)->range_of_expr (r, op) && r == onezero) + if (get_range_query (cfun)->range_of_expr (r, op) + && r == range_true_and_false (TREE_TYPE (op))) return true; if (wi::eq_p (get_nonzero_bits (op), 1)) diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index c0dcd50ee01..d28637b1918 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -837,7 +837,9 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op) tree label = gimple_switch_label (switch_stmt, i); tree case_high = CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label); - int_range_max label_range (CASE_LOW (label), case_high); + int_range_max label_range (type, + wi::to_wide (CASE_LOW (label)), + wi::to_wide (case_high)); if (!types_compatible_p (label_range.type (), range_of_op->type ())) range_cast (label_range, range_of_op->type ()); label_range.intersect (*range_of_op); @@ -861,7 +863,9 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op) tree case_high = CASE_HIGH (max_label); if (!case_high) case_high = CASE_LOW (max_label); - int_range_max label_range (CASE_LOW (min_label), case_high); + int_range_max label_range (TREE_TYPE (CASE_LOW (min_label)), + wi::to_wide (CASE_LOW (min_label)), + wi::to_wide (case_high)); if (!types_compatible_p (label_range.type (), range_of_op->type ())) range_cast (label_range, range_of_op->type ()); label_range.intersect (*range_of_op); diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 8ccdc9f8852..43297f17c39 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -176,16 +176,21 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) switch (TREE_CODE (expr)) { case INTEGER_CST: - if (TREE_OVERFLOW_P (expr)) - expr = drop_tree_overflow (expr); - r.set (expr, expr); - return true; + { + irange &i = as_a (r); + if (TREE_OVERFLOW_P (expr)) + expr = drop_tree_overflow (expr); + wide_int w = wi::to_wide (expr); + i.set (TREE_TYPE (expr), w, w); + return true; + } case REAL_CST: { frange &f = as_a (r); - f.set (expr, expr); - if (!real_isnan (TREE_REAL_CST_PTR (expr))) + REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (expr); + f.set (TREE_TYPE (expr), *rv, *rv); + if (!real_isnan (rv)) f.clear_nan (); return true; } diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 69b214ecc06..f2148722a3a 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -301,7 +301,9 @@ irange::fits_p (const vrange &r) const void irange::set_nonnegative (tree type) { - set (build_int_cst (type, 0), TYPE_MAX_VALUE (type)); + set (type, + wi::zero (TYPE_PRECISION (type)), + wi::to_wide (TYPE_MAX_VALUE (type))); } void @@ -700,13 +702,12 @@ frange::operator== (const frange &src) const return false; } -// Return TRUE if range contains the TREE_REAL_CST_PTR in CST. +// Return TRUE if range contains R. bool -frange::contains_p (tree cst) const +frange::contains_p (const REAL_VALUE_TYPE &r) const { gcc_checking_assert (m_kind != VR_ANTI_RANGE); - const REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (cst); if (undefined_p ()) return false; @@ -714,7 +715,7 @@ frange::contains_p (tree cst) const if (varying_p ()) return true; - if (real_isnan (rv)) + if (real_isnan (&r)) { // No NAN in range. if (!m_pos_nan && !m_neg_nan) @@ -722,16 +723,16 @@ frange::contains_p (tree cst) const // Both +NAN and -NAN are present. if (m_pos_nan && m_neg_nan) return true; - return m_neg_nan == rv->sign; + return m_neg_nan == r.sign; } if (known_isnan ()) return false; - if (real_compare (GE_EXPR, rv, &m_min) && real_compare (LE_EXPR, rv, &m_max)) + if (real_compare (GE_EXPR, &r, &m_min) && real_compare (LE_EXPR, &r, &m_max)) { // Make sure the signs are equal for signed zeros. - if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (rv)) - return rv->sign == m_min.sign || rv->sign == m_max.sign; + if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (&r)) + return r.sign == m_min.sign || r.sign == m_max.sign; return true; } return false; @@ -743,7 +744,7 @@ frange::contains_p (tree cst) const // A NAN can never be a singleton. bool -frange::singleton_p (tree *result) const +frange::internal_singleton_p (REAL_VALUE_TYPE *result) const { if (m_kind == VR_RANGE && real_identical (&m_min, &m_max)) { @@ -766,6 +767,18 @@ frange::singleton_p (tree *result) const return false; } + if (result) + *result = m_min; + return true; + } + return false; +} + +bool +frange::singleton_p (tree *result) const +{ + if (internal_singleton_p ()) + { if (result) *result = build_real (m_type, m_min); return true; @@ -773,6 +786,12 @@ frange::singleton_p (tree *result) const return false; } +bool +frange::singleton_p (REAL_VALUE_TYPE &r) const +{ + return internal_singleton_p (&r); +} + bool frange::supports_type_p (const_tree type) const { @@ -942,13 +961,10 @@ get_legacy_range (const irange &r, tree &min, tree &max) } void -irange::irange_set (tree min, tree max) +irange::irange_set (tree type, const wide_int &min, const wide_int &max) { - gcc_checking_assert (!POLY_INT_CST_P (min)); - gcc_checking_assert (!POLY_INT_CST_P (max)); - - m_base[0] = min; - m_base[1] = max; + m_base[0] = wide_int_to_tree (type, min); + m_base[1] = wide_int_to_tree (type, max); m_num_ranges = 1; m_kind = VR_RANGE; m_nonzero_mask = NULL; @@ -959,26 +975,31 @@ irange::irange_set (tree min, tree max) } void -irange::irange_set_1bit_anti_range (tree min, tree max) +irange::irange_set_1bit_anti_range (tree type, + const wide_int &min, const wide_int &max) { - tree type = TREE_TYPE (min); gcc_checking_assert (TYPE_PRECISION (type) == 1); - if (operand_equal_p (min, max)) + if (min == max) { // Since these are 1-bit quantities, they can only be [MIN,MIN] // or [MAX,MAX]. - if (vrp_val_is_min (min)) - min = max = vrp_val_max (type); + if (min == wi::to_wide (TYPE_MIN_VALUE (type))) + { + wide_int tmp = wi::to_wide (TYPE_MAX_VALUE (type)); + set (type, tmp, tmp); + } else - min = max = vrp_val_min (type); - set (min, max); + { + wide_int tmp = wi::to_wide (TYPE_MIN_VALUE (type)); + set (type, tmp, tmp); + } } else { // The only alternative is [MIN,MAX], which is the empty range. - gcc_checking_assert (vrp_val_is_min (min)); - gcc_checking_assert (vrp_val_is_max (max)); + gcc_checking_assert (min == wi::to_wide (TYPE_MIN_VALUE (type))); + gcc_checking_assert (max == wi::to_wide (TYPE_MAX_VALUE (type))); set_undefined (); } if (flag_checking) @@ -986,43 +1007,38 @@ irange::irange_set_1bit_anti_range (tree min, tree max) } void -irange::irange_set_anti_range (tree min, tree max) +irange::irange_set_anti_range (tree type, + const wide_int &min, const wide_int &max) { - gcc_checking_assert (!POLY_INT_CST_P (min)); - gcc_checking_assert (!POLY_INT_CST_P (max)); - - if (TYPE_PRECISION (TREE_TYPE (min)) == 1) + if (TYPE_PRECISION (type) == 1) { - irange_set_1bit_anti_range (min, max); + irange_set_1bit_anti_range (type, min, max); return; } // set an anti-range - tree type = TREE_TYPE (min); signop sign = TYPE_SIGN (type); int_range<2> type_range (type); // Calculate INVERSE([I,J]) as [-MIN, I-1][J+1, +MAX]. m_num_ranges = 0; wi::overflow_type ovf; - wide_int w_min = wi::to_wide (min); - if (wi::ne_p (w_min, type_range.lower_bound ())) + if (wi::ne_p (min, type_range.lower_bound ())) { - wide_int lim1 = wi::sub (w_min, 1, sign, &ovf); + wide_int lim1 = wi::sub (min, 1, sign, &ovf); gcc_checking_assert (ovf != wi::OVF_OVERFLOW); m_base[0] = wide_int_to_tree (type, type_range.lower_bound (0)); m_base[1] = wide_int_to_tree (type, lim1); m_num_ranges = 1; } - wide_int w_max = wi::to_wide (max); - if (wi::ne_p (w_max, type_range.upper_bound ())) + if (wi::ne_p (max, type_range.upper_bound ())) { if (m_max_ranges == 1 && m_num_ranges) { set_varying (type); return; } - wide_int lim2 = wi::add (w_max, 1, sign, &ovf); + wide_int lim2 = wi::add (max, 1, sign, &ovf); gcc_checking_assert (ovf != wi::OVF_OVERFLOW); m_base[m_num_ranges * 2] = wide_int_to_tree (type, lim2); m_base[m_num_ranges * 2 + 1] @@ -1047,6 +1063,36 @@ irange::irange_set_anti_range (tree min, tree max) This routine exists to ease canonicalization in the case where we extract ranges from var + CST op limit. */ +void +irange::set (tree type, const wide_int &rmin, const wide_int &rmax, + value_range_kind kind) +{ + if (kind == VR_UNDEFINED) + { + irange::set_undefined (); + return; + } + + if (kind == VR_VARYING) + { + set_varying (type); + return; + } + + signop sign = TYPE_SIGN (type); + unsigned prec = TYPE_PRECISION (type); + wide_int min = wide_int::from (rmin, prec, sign); + wide_int max = wide_int::from (rmax, prec, sign); + + if (kind == VR_RANGE) + irange_set (type, min, max); + else + { + gcc_checking_assert (kind == VR_ANTI_RANGE); + irange_set_anti_range (type, min, max); + } +} + void irange::set (tree min, tree max, value_range_kind kind) { @@ -1072,13 +1118,8 @@ irange::set (tree min, tree max, value_range_kind kind) if (TREE_OVERFLOW_P (max)) max = drop_tree_overflow (max); - if (kind == VR_RANGE) - irange_set (min, max); - else - { - gcc_checking_assert (kind == VR_ANTI_RANGE); - irange_set_anti_range (min, max); - } + return set (TREE_TYPE (min), + wi::to_wide (min), wi::to_wide (max), kind); } // Check the validity of the range. @@ -1138,9 +1179,7 @@ irange::operator== (const irange &other) const return nz1 == nz2; } -/* If range is a singleton, place it in RESULT and return TRUE. - Note: A singleton can be any gimple invariant, not just constants. - So, [&x, &x] counts as a singleton. */ +/* If range is a singleton, place it in RESULT and return TRUE. */ bool irange::singleton_p (tree *result) const @@ -1154,37 +1193,41 @@ irange::singleton_p (tree *result) const return false; } -/* Return TRUE if range contains INTEGER_CST. */ -/* Return 1 if VAL is inside value range. - 0 if VAL is not inside value range. +bool +irange::singleton_p (wide_int &w) const +{ + if (num_pairs () == 1 && lower_bound () == upper_bound ()) + { + w = lower_bound (); + return true; + } + return false; +} + +/* Return 1 if CST is inside value range. + 0 if CST is not inside value range. Benchmark compile/20001226-1.c compilation time after changing this function. */ - bool -irange::contains_p (tree cst) const +irange::contains_p (const wide_int &cst) const { if (undefined_p ()) return false; - gcc_checking_assert (TREE_CODE (cst) == INTEGER_CST); - // See if we can exclude CST based on the nonzero bits. - if (m_nonzero_mask) - { - wide_int cstw = wi::to_wide (cst); - if (cstw != 0 && wi::bit_and (wi::to_wide (m_nonzero_mask), cstw) == 0) - return false; - } + if (m_nonzero_mask + && cst != 0 + && wi::bit_and (wi::to_wide (m_nonzero_mask), cst) == 0) + return false; - signop sign = TYPE_SIGN (TREE_TYPE (cst)); - wide_int v = wi::to_wide (cst); + signop sign = TYPE_SIGN (type ()); for (unsigned r = 0; r < m_num_ranges; ++r) { - if (wi::lt_p (v, lower_bound (r), sign)) + if (wi::lt_p (cst, lower_bound (r), sign)) return false; - if (wi::le_p (v, upper_bound (r), sign)) + if (wi::le_p (cst, upper_bound (r), sign)) return true; } @@ -1760,10 +1803,10 @@ irange::set_range_from_nonzero_bits () if (popcount == 1) { // Make sure we don't pessimize the range. - if (!contains_p (m_nonzero_mask)) + if (!contains_p (wi::to_wide (m_nonzero_mask))) return false; - bool has_zero = contains_p (build_zero_cst (type ())); + bool has_zero = contains_zero_p (*this); tree nz = m_nonzero_mask; set (nz, nz); m_nonzero_mask = nz; @@ -2085,7 +2128,6 @@ gt_ggc_mx (int_range<2> *&x) } #define DEFINE_INT_RANGE_INSTANCE(N) \ - template int_range::int_range(tree, tree, value_range_kind); \ template int_range::int_range(tree_node *, \ const wide_int &, \ const wide_int &, \ @@ -2103,20 +2145,73 @@ DEFINE_INT_RANGE_INSTANCE(255) #if CHECKING_P #include "selftest.h" +#define INT(x) wi::shwi ((x), TYPE_PRECISION (integer_type_node)) +#define UINT(x) wi::uhwi ((x), TYPE_PRECISION (unsigned_type_node)) +#define SCHAR(x) wi::shwi ((x), TYPE_PRECISION (signed_char_type_node)) + namespace selftest { -#define INT(N) build_int_cst (integer_type_node, (N)) -#define UINT(N) build_int_cstu (unsigned_type_node, (N)) -#define UINT128(N) build_int_cstu (u128_type, (N)) -#define UCHAR(N) build_int_cstu (unsigned_char_type_node, (N)) -#define SCHAR(N) build_int_cst (signed_char_type_node, (N)) + +static int_range<2> +range (tree type, int a, int b, value_range_kind kind = VR_RANGE) +{ + wide_int w1, w2; + if (TYPE_UNSIGNED (type)) + { + w1 = wi::uhwi (a, TYPE_PRECISION (type)); + w2 = wi::uhwi (b, TYPE_PRECISION (type)); + } + else + { + w1 = wi::shwi (a, TYPE_PRECISION (type)); + w2 = wi::shwi (b, TYPE_PRECISION (type)); + } + return int_range<2> (type, w1, w2, kind); +} + +static int_range<2> +tree_range (tree a, tree b, value_range_kind kind = VR_RANGE) +{ + return int_range<2> (TREE_TYPE (a), wi::to_wide (a), wi::to_wide (b), kind); +} + +static int_range<2> +range_int (int a, int b, value_range_kind kind = VR_RANGE) +{ + return range (integer_type_node, a, b, kind); +} + +static int_range<2> +range_uint (int a, int b, value_range_kind kind = VR_RANGE) +{ + return range (unsigned_type_node, a, b, kind); +} + +static int_range<2> +range_uint128 (int a, int b, value_range_kind kind = VR_RANGE) +{ + tree u128_type_node = build_nonstandard_integer_type (128, 1); + return range (u128_type_node, a, b, kind); +} + +static int_range<2> +range_uchar (int a, int b, value_range_kind kind = VR_RANGE) +{ + return range (unsigned_char_type_node, a, b, kind); +} + +static int_range<2> +range_char (int a, int b, value_range_kind kind = VR_RANGE) +{ + return range (signed_char_type_node, a, b, kind); +} static int_range<3> build_range3 (int a, int b, int c, int d, int e, int f) { - int_range<3> i1 (INT (a), INT (b)); - int_range<3> i2 (INT (c), INT (d)); - int_range<3> i3 (INT (e), INT (f)); + int_range<3> i1 = range_int (a, b); + int_range<3> i2 = range_int (c, d); + int_range<3> i3 = range_int (e, f); i1.union_ (i2); i1.union_ (i3); return i1; @@ -2125,76 +2220,75 @@ build_range3 (int a, int b, int c, int d, int e, int f) static void range_tests_irange3 () { - typedef int_range<3> int_range3; - int_range3 r0, r1, r2; - int_range3 i1, i2, i3; + int_range<3> r0, r1, r2; + int_range<3> i1, i2, i3; // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20]. - r0 = int_range3 (INT (10), INT (20)); - r1 = int_range3 (INT (5), INT (8)); + r0 = range_int (10, 20); + r1 = range_int (5, 8); r0.union_ (r1); - r1 = int_range3 (INT (1), INT (3)); + r1 = range_int (1, 3); r0.union_ (r1); ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20)); // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20]. - r1 = int_range3 (INT (-5), INT (0)); + r1 = range_int (-5, 0); r0.union_ (r1); ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20)); // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60]. - r1 = int_range3 (INT (50), INT (60)); - r0 = int_range3 (INT (10), INT (20)); - r0.union_ (int_range3 (INT (30), INT (40))); + r1 = range_int (50, 60); + r0 = range_int (10, 20); + r0.union_ (range_int (30, 40)); r0.union_ (r1); ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60)); // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80]. - r1 = int_range3 (INT (70), INT (80)); + r1 = range_int (70, 80); r0.union_ (r1); r2 = build_range3 (10, 20, 30, 40, 50, 60); - r2.union_ (int_range3 (INT (70), INT (80))); + r2.union_ (range_int (70, 80)); ASSERT_TRUE (r0 == r2); // [10,20][30,40][50,60] U [6,35] => [6,40][50,60]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (6), INT (35)); + r1 = range_int (6, 35); r0.union_ (r1); - r1 = int_range3 (INT (6), INT (40)); - r1.union_ (int_range3 (INT (50), INT (60))); + r1 = range_int (6, 40); + r1.union_ (range_int (50, 60)); ASSERT_TRUE (r0 == r1); // [10,20][30,40][50,60] U [6,60] => [6,60]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (6), INT (60)); + r1 = range_int (6, 60); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range3 (INT (6), INT (60))); + ASSERT_TRUE (r0 == range_int (6, 60)); // [10,20][30,40][50,60] U [6,70] => [6,70]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (6), INT (70)); + r1 = range_int (6, 70); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range3 (INT (6), INT (70))); + ASSERT_TRUE (r0 == range_int (6, 70)); // [10,20][30,40][50,60] U [35,70] => [10,20][30,70]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (35), INT (70)); + r1 = range_int (35, 70); r0.union_ (r1); - r1 = int_range3 (INT (10), INT (20)); - r1.union_ (int_range3 (INT (30), INT (70))); + r1 = range_int (10, 20); + r1.union_ (range_int (30, 70)); ASSERT_TRUE (r0 == r1); // [10,20][30,40][50,60] U [15,35] => [10,40][50,60]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (15), INT (35)); + r1 = range_int (15, 35); r0.union_ (r1); - r1 = int_range3 (INT (10), INT (40)); - r1.union_ (int_range3 (INT (50), INT (60))); + r1 = range_int (10, 40); + r1.union_ (range_int (50, 60)); ASSERT_TRUE (r0 == r1); // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60]. r0 = build_range3 (10, 20, 30, 40, 50, 60); - r1 = int_range3 (INT (35), INT (35)); + r1 = range_int (35, 35); r0.union_ (r1); ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60)); } @@ -2208,7 +2302,7 @@ range_tests_int_range_max () // Build a huge multi-range range. for (nrange = 0; nrange < 50; ++nrange) { - int_range<1> tmp (INT (nrange*10), INT (nrange*10 + 5)); + int_range<1> tmp = range_int (nrange*10, nrange *10 + 5); big.union_ (tmp); } ASSERT_TRUE (big.num_pairs () == nrange); @@ -2221,18 +2315,16 @@ range_tests_int_range_max () big.invert (); ASSERT_TRUE (big.num_pairs () == nrange + 1); - int_range<1> tmp (INT (5), INT (37)); + int_range<1> tmp = range_int (5, 37); big.intersect (tmp); ASSERT_TRUE (big.num_pairs () == 4); // Test that [10,10][20,20] does NOT contain 15. { - int_range_max i1 (build_int_cst (integer_type_node, 10), - build_int_cst (integer_type_node, 10)); - int_range_max i2 (build_int_cst (integer_type_node, 20), - build_int_cst (integer_type_node, 20)); + int_range_max i1 = range_int (10, 10); + int_range_max i2 = range_int (20, 20); i1.union_ (i2); - ASSERT_FALSE (i1.contains_p (build_int_cst (integer_type_node, 15))); + ASSERT_FALSE (i1.contains_p (INT (15))); } } @@ -2249,11 +2341,10 @@ range_tests_strict_enum () // Test that even though vr1 covers the strict enum domain ([0, 3]), // it does not cover the domain of the underlying type. - int_range<1> vr1 (build_int_cstu (rtype, 0), build_int_cstu (rtype, 1)); - int_range<1> vr2 (build_int_cstu (rtype, 2), build_int_cstu (rtype, 3)); + int_range<1> vr1 = range (rtype, 0, 1); + int_range<1> vr2 = range (rtype, 2, 3); vr1.union_ (vr2); - ASSERT_TRUE (vr1 == int_range<1> (build_int_cstu (rtype, 0), - build_int_cstu (rtype, 3))); + ASSERT_TRUE (vr1 == range (rtype, 0, 3)); ASSERT_FALSE (vr1.varying_p ()); // Test that copying to a multi-range does not change things. @@ -2262,7 +2353,7 @@ range_tests_strict_enum () ASSERT_FALSE (ir1.varying_p ()); // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3]. - vr1 = int_range<1> (TYPE_MIN_VALUE (rtype), TYPE_MAX_VALUE (rtype)); + vr1 = tree_range (TYPE_MIN_VALUE (rtype), TYPE_MAX_VALUE (rtype)); ir1 = vr1; ASSERT_TRUE (ir1 == vr1); ASSERT_FALSE (ir1.varying_p ()); @@ -2281,8 +2372,8 @@ range_tests_misc () tree one_bit_min = vrp_val_min (one_bit_type); tree one_bit_max = vrp_val_max (one_bit_type); { - int_range<2> min (one_bit_min, one_bit_min); - int_range<2> max (one_bit_max, one_bit_max); + int_range<2> min = tree_range (one_bit_min, one_bit_min); + int_range<2> max = tree_range (one_bit_max, one_bit_max); max.union_ (min); ASSERT_TRUE (max.varying_p ()); } @@ -2291,8 +2382,8 @@ range_tests_misc () // Test inversion of 1-bit signed integers. { - int_range<2> min (one_bit_min, one_bit_min); - int_range<2> max (one_bit_max, one_bit_max); + int_range<2> min = tree_range (one_bit_min, one_bit_min); + int_range<2> max = tree_range (one_bit_max, one_bit_max); int_range<2> t; t = min; t.invert (); @@ -2303,79 +2394,81 @@ range_tests_misc () } // Test that NOT(255) is [0..254] in 8-bit land. - int_range<1> not_255 (UCHAR (255), UCHAR (255), VR_ANTI_RANGE); - ASSERT_TRUE (not_255 == int_range<1> (UCHAR (0), UCHAR (254))); + int_range<1> not_255 = range_uchar (255, 255, VR_ANTI_RANGE); + ASSERT_TRUE (not_255 == range_uchar (0, 254)); // Test that NOT(0) is [1..255] in 8-bit land. int_range<2> not_zero = range_nonzero (unsigned_char_type_node); - ASSERT_TRUE (not_zero == int_range<1> (UCHAR (1), UCHAR (255))); + ASSERT_TRUE (not_zero == range_uchar (1, 255)); // Check that [0,127][0x..ffffff80,0x..ffffff] // => ~[128, 0x..ffffff7f]. - r0 = int_range<1> (UINT128 (0), UINT128 (127)); - tree high = build_minus_one_cst (u128_type); + r0 = range_uint128 (0, 127); + wide_int high = wi::minus_one (128); // low = -1 - 127 => 0x..ffffff80. - tree low = fold_build2 (MINUS_EXPR, u128_type, high, UINT128(127)); - r1 = int_range<1> (low, high); // [0x..ffffff80, 0x..ffffffff] + wide_int low = wi::sub (high, wi::uhwi (127, 128)); + r1 = int_range<1> (u128_type, low, high); // [0x..ffffff80, 0x..ffffffff] // r0 = [0,127][0x..ffffff80,0x..fffffff]. r0.union_ (r1); // r1 = [128, 0x..ffffff7f]. - r1 = int_range<1> (UINT128(128), - fold_build2 (MINUS_EXPR, u128_type, - build_minus_one_cst (u128_type), - UINT128(128))); + r1 = int_range<1> (u128_type, + wi::uhwi (128, 128), + wi::sub (wi::minus_one (128), wi::uhwi (128, 128))); r0.invert (); ASSERT_TRUE (r0 == r1); r0.set_varying (integer_type_node); - tree minint = wide_int_to_tree (integer_type_node, r0.lower_bound ()); - tree maxint = wide_int_to_tree (integer_type_node, r0.upper_bound ()); + wide_int minint = r0.lower_bound (); + wide_int maxint = r0.upper_bound (); r0.set_varying (short_integer_type_node); r0.set_varying (unsigned_type_node); - tree maxuint = wide_int_to_tree (unsigned_type_node, r0.upper_bound ()); + wide_int maxuint = r0.upper_bound (); // Check that ~[0,5] => [6,MAX] for unsigned int. - r0 = int_range<1> (UINT (0), UINT (5)); + r0 = range_uint (0, 5); r0.invert (); - ASSERT_TRUE (r0 == int_range<1> (UINT(6), maxuint)); + ASSERT_TRUE (r0 == int_range<1> (unsigned_type_node, + wi::uhwi (6, TYPE_PRECISION (unsigned_type_node)), + maxuint)); // Check that ~[10,MAX] => [0,9] for unsigned int. - r0 = int_range<1> (UINT(10), maxuint); + r0 = int_range<1> (unsigned_type_node, + wi::uhwi (10, TYPE_PRECISION (unsigned_type_node)), + maxuint); r0.invert (); - ASSERT_TRUE (r0 == int_range<1> (UINT (0), UINT (9))); + ASSERT_TRUE (r0 == range_uint (0, 9)); // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers. - r0 = int_range<1> (UINT128 (0), UINT128 (5), VR_ANTI_RANGE); - r1 = int_range<1> (UINT128(6), build_minus_one_cst (u128_type)); + r0 = range_uint128 (0, 5, VR_ANTI_RANGE); + r1 = int_range<1> (u128_type, wi::uhwi (6, 128), wi::minus_one (128)); ASSERT_TRUE (r0 == r1); // Check that [~5] is really [-MIN,4][6,MAX]. - r0 = int_range<2> (INT (5), INT (5), VR_ANTI_RANGE); - r1 = int_range<1> (minint, INT (4)); - r1.union_ (int_range<1> (INT (6), maxint)); + r0 = range_int (5, 5, VR_ANTI_RANGE); + r1 = int_range<1> (integer_type_node, minint, INT (4)); + r1.union_ (int_range<1> (integer_type_node, INT (6), maxint)); ASSERT_FALSE (r1.undefined_p ()); ASSERT_TRUE (r0 == r1); - r1 = int_range<1> (INT (5), INT (5)); + r1 = range_int (5, 5); int_range<2> r2 (r1); ASSERT_TRUE (r1 == r2); - r1 = int_range<1> (INT (5), INT (10)); + r1 = range_int (5, 10); - r1 = int_range<1> (integer_type_node, - wi::to_wide (INT (5)), wi::to_wide (INT (10))); + r1 = range_int (5, 10); ASSERT_TRUE (r1.contains_p (INT (7))); - r1 = int_range<1> (SCHAR (0), SCHAR (20)); + r1 = range_char (0, 20); ASSERT_TRUE (r1.contains_p (SCHAR(15))); ASSERT_FALSE (r1.contains_p (SCHAR(300))); // NOT([10,20]) ==> [-MIN,9][21,MAX]. - r0 = r1 = int_range<1> (INT (10), INT (20)); - r2 = int_range<1> (minint, INT(9)); - r2.union_ (int_range<1> (INT(21), maxint)); + r0 = r1 = range_int (10, 20); + r2 = int_range<1> (integer_type_node, minint, INT(9)); + r2.union_ (int_range<1> (integer_type_node, INT(21), maxint)); ASSERT_FALSE (r2.undefined_p ()); r1.invert (); ASSERT_TRUE (r1 == r2); @@ -2385,11 +2478,9 @@ range_tests_misc () // Test that booleans and their inverse work as expected. r0 = range_zero (boolean_type_node); - ASSERT_TRUE (r0 == int_range<1> (build_zero_cst (boolean_type_node), - build_zero_cst (boolean_type_node))); + ASSERT_TRUE (r0 == range_false ()); r0.invert (); - ASSERT_TRUE (r0 == int_range<1> (build_one_cst (boolean_type_node), - build_one_cst (boolean_type_node))); + ASSERT_TRUE (r0 == range_true ()); // Make sure NULL and non-NULL of pointer types work, and that // inverses of them are consistent. @@ -2401,34 +2492,34 @@ range_tests_misc () ASSERT_TRUE (r0 == r1); // [10,20] U [15, 30] => [10, 30]. - r0 = int_range<1> (INT (10), INT (20)); - r1 = int_range<1> (INT (15), INT (30)); + r0 = range_int (10, 20); + r1 = range_int (15, 30); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (30))); + ASSERT_TRUE (r0 == range_int (10, 30)); // [15,40] U [] => [15,40]. - r0 = int_range<1> (INT (15), INT (40)); + r0 = range_int (15, 40); r1.set_undefined (); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (40))); + ASSERT_TRUE (r0 == range_int (15, 40)); // [10,20] U [10,10] => [10,20]. - r0 = int_range<1> (INT (10), INT (20)); - r1 = int_range<1> (INT (10), INT (10)); + r0 = range_int (10, 20); + r1 = range_int (10, 10); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range<1> (INT (10), INT (20))); + ASSERT_TRUE (r0 == range_int (10, 20)); // [10,20] U [9,9] => [9,20]. - r0 = int_range<1> (INT (10), INT (20)); - r1 = int_range<1> (INT (9), INT (9)); + r0 = range_int (10, 20); + r1 = range_int (9, 9); r0.union_ (r1); - ASSERT_TRUE (r0 == int_range<1> (INT (9), INT (20))); + ASSERT_TRUE (r0 == range_int (9, 20)); // [10,20] ^ [15,30] => [15,20]. - r0 = int_range<1> (INT (10), INT (20)); - r1 = int_range<1> (INT (15), INT (30)); + r0 = range_int (10, 20); + r1 = range_int (15, 30); r0.intersect (r1); - ASSERT_TRUE (r0 == int_range<1> (INT (15), INT (20))); + ASSERT_TRUE (r0 == range_int (15, 20)); // Test the internal sanity of wide_int's wrt HWIs. ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node), @@ -2436,18 +2527,18 @@ range_tests_misc () == wi::uhwi (1, TYPE_PRECISION (boolean_type_node))); // Test zero_p(). - r0 = int_range<1> (INT (0), INT (0)); + r0 = range_int (0, 0); ASSERT_TRUE (r0.zero_p ()); // Test nonzero_p(). - r0 = int_range<1> (INT (0), INT (0)); + r0 = range_int (0, 0); r0.invert (); ASSERT_TRUE (r0.nonzero_p ()); // r0 = ~[1,1] - r0 = int_range<2> (UINT (1), UINT (1), VR_ANTI_RANGE); + r0 = range_int (1, 1, VR_ANTI_RANGE); // r1 = ~[3,3] - r1 = int_range<2> (UINT (3), UINT (3), VR_ANTI_RANGE); + r1 = range_int (3, 3, VR_ANTI_RANGE); // vv = [0,0][2,2][4, MAX] int_range<3> vv = r0; @@ -2456,7 +2547,7 @@ range_tests_misc () ASSERT_TRUE (vv.contains_p (UINT (2))); ASSERT_TRUE (vv.num_pairs () == 3); - r0 = int_range<1> (UINT (1), UINT (1)); + r0 = range_uint (1, 1); // And union it with [0,0][2,2][4,MAX] multi range r0.union_ (vv); // The result should be [0,2][4,MAX], or ~[3,3] but it must contain 2 @@ -2493,7 +2584,7 @@ range_tests_nonzero_bits () ASSERT_TRUE (r0.get_nonzero_bits () == 0xff); // Intersect of nonzero bits. - r0.set (INT (0), INT (255)); + r0 = range_int (0, 255); r0.set_nonzero_bits (0xfe); r1.set_varying (integer_type_node); r1.set_nonzero_bits (0xf0); @@ -2502,7 +2593,7 @@ range_tests_nonzero_bits () // Intersect where the mask of nonzero bits is implicit from the range. r0.set_varying (integer_type_node); - r1.set (INT (0), INT (255)); + r1 = range_int (0, 255); r0.intersect (r1); ASSERT_TRUE (r0.get_nonzero_bits () == 0xff); @@ -2631,13 +2722,13 @@ range_tests_nan () // NAN is in a VARYING. r0.set_varying (float_type_node); real_nan (&r, "", 1, TYPE_MODE (float_type_node)); - tree nan = build_real (float_type_node, r); + REAL_VALUE_TYPE nan = r; ASSERT_TRUE (r0.contains_p (nan)); // -NAN is in a VARYING. r0.set_varying (float_type_node); q = real_value_negate (&r); - tree neg_nan = build_real (float_type_node, q); + REAL_VALUE_TYPE neg_nan = q; ASSERT_TRUE (r0.contains_p (neg_nan)); // Clearing the NAN on a [] NAN is the empty set. @@ -2669,28 +2760,29 @@ range_tests_nan () static void range_tests_signed_zeros () { - tree zero = build_zero_cst (float_type_node); - tree neg_zero = fold_build1 (NEGATE_EXPR, float_type_node, zero); + REAL_VALUE_TYPE zero = dconst0; + REAL_VALUE_TYPE neg_zero = zero; + neg_zero.sign = 1; frange r0, r1; bool signbit; // [0,0] contains [0,0] but not [-0,-0] and vice versa. - r0 = frange (zero, zero); - r1 = frange (neg_zero, neg_zero); + r0 = frange_float ("0.0", "0.0"); + r1 = frange_float ("-0.0", "-0.0"); ASSERT_TRUE (r0.contains_p (zero)); ASSERT_TRUE (!r0.contains_p (neg_zero)); ASSERT_TRUE (r1.contains_p (neg_zero)); ASSERT_TRUE (!r1.contains_p (zero)); // Test contains_p() when we know the sign of the zero. - r0 = frange (zero, zero); + r0 = frange_float ("0.0", "0.0"); ASSERT_TRUE (r0.contains_p (zero)); ASSERT_FALSE (r0.contains_p (neg_zero)); - r0 = frange (neg_zero, neg_zero); + r0 = frange_float ("-0.0", "-0.0"); ASSERT_TRUE (r0.contains_p (neg_zero)); ASSERT_FALSE (r0.contains_p (zero)); - r0 = frange (neg_zero, zero); + r0 = frange_float ("-0.0", "0.0"); ASSERT_TRUE (r0.contains_p (neg_zero)); ASSERT_TRUE (r0.contains_p (zero)); @@ -2700,8 +2792,8 @@ range_tests_signed_zeros () // The intersection of zeros that differ in sign is a NAN (or // undefined if not honoring NANs). - r0 = frange (neg_zero, neg_zero); - r1 = frange (zero, zero); + r0 = frange_float ("-0.0", "-0.0"); + r1 = frange_float ("0.0", "0.0"); r0.intersect (r1); if (HONOR_NANS (float_type_node)) ASSERT_TRUE (r0.known_isnan ()); @@ -2709,18 +2801,18 @@ range_tests_signed_zeros () ASSERT_TRUE (r0.undefined_p ()); // The union of zeros that differ in sign is a zero with unknown sign. - r0 = frange (zero, zero); - r1 = frange (neg_zero, neg_zero); + r0 = frange_float ("0.0", "0.0"); + r1 = frange_float ("-0.0", "-0.0"); r0.union_ (r1); ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit)); // [-0, +0] has an unknown sign. - r0 = frange (neg_zero, zero); + r0 = frange_float ("-0.0", "0.0"); ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit)); // [-0, +0] ^ [0, 0] is [0, 0] - r0 = frange (neg_zero, zero); - r1 = frange (zero, zero); + r0 = frange_float ("-0.0", "0.0"); + r1 = frange_float ("0.0", "0.0"); r0.intersect (r1); ASSERT_TRUE (r0.zero_p ()); diff --git a/gcc/value-range.h b/gcc/value-range.h index 6d108154dc1..633a234d41f 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -122,8 +122,7 @@ class GTY((user)) irange : public vrange friend class irange_storage; public: // In-place setters. - virtual void set (tree, tree, value_range_kind = VR_RANGE) override; - void set (tree type, const wide_int_ref &, const wide_int_ref &, + void set (tree type, const wide_int &, const wide_int &, value_range_kind = VR_RANGE); virtual void set_nonzero (tree type) override; virtual void set_zero (tree type) override; @@ -146,7 +145,8 @@ public: virtual bool zero_p () const override; virtual bool nonzero_p () const override; virtual bool singleton_p (tree *result = NULL) const override; - virtual bool contains_p (tree cst) const override; + bool singleton_p (wide_int &) const; + bool contains_p (const wide_int &) const; // In-place operators. virtual bool union_ (const vrange &) override; @@ -167,11 +167,13 @@ public: void set_nonzero_bits (const wide_int_ref &bits); protected: + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + virtual bool contains_p (tree cst) const override; irange (tree *, unsigned); // In-place operators. - void irange_set (tree, tree); - void irange_set_anti_range (tree, tree); + void irange_set (tree type, const wide_int &, const wide_int &); + void irange_set_anti_range (tree type, const wide_int &, const wide_int &); bool irange_contains_p (const irange &) const; bool irange_single_pair_union (const irange &r); @@ -184,7 +186,8 @@ private: friend void gt_pch_nx (irange *); friend void gt_pch_nx (irange *, gt_pointer_operator, void *); - void irange_set_1bit_anti_range (tree, tree); + void irange_set_1bit_anti_range (tree type, + const wide_int &, const wide_int &); bool varying_compatible_p () const; bool intersect_nonzero_bits (const irange &r); bool union_nonzero_bits (const irange &r); @@ -206,7 +209,6 @@ class GTY((user)) int_range : public irange { public: int_range (); - int_range (tree, tree, value_range_kind = VR_RANGE); int_range (tree type, const wide_int &, const wide_int &, value_range_kind = VR_RANGE); int_range (tree type); @@ -214,6 +216,8 @@ public: int_range (const irange &); virtual ~int_range () = default; int_range& operator= (const int_range &); +protected: + int_range (tree, tree, value_range_kind = VR_RANGE); private: template friend void gt_ggc_mx (int_range *); template friend void gt_pch_nx (int_range *); @@ -319,7 +323,6 @@ public: return SCALAR_FLOAT_TYPE_P (type) && !DECIMAL_FLOAT_TYPE_P (type); } virtual tree type () const override; - virtual void set (tree, tree, value_range_kind = VR_RANGE) override; void set (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &, value_range_kind = VR_RANGE); void set (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &, @@ -330,8 +333,9 @@ public: virtual void set_undefined () override; virtual bool union_ (const vrange &) override; virtual bool intersect (const vrange &) override; - virtual bool contains_p (tree) const override; + bool contains_p (const REAL_VALUE_TYPE &) const; virtual bool singleton_p (tree *result = NULL) const override; + bool singleton_p (REAL_VALUE_TYPE &r) const; virtual bool supports_type_p (const_tree type) const override; virtual void accept (const vrange_visitor &v) const override; virtual bool zero_p () const override; @@ -361,7 +365,13 @@ public: bool maybe_isinf () const; bool signbit_p (bool &signbit) const; bool nan_signbit_p (bool &signbit) const; + +protected: + virtual bool contains_p (tree cst) const override; + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + private: + bool internal_singleton_p (REAL_VALUE_TYPE * = NULL) const; void verify_range (); bool normalize_kind (); bool union_nans (const frange &); @@ -485,8 +495,6 @@ public: static bool supports_type_p (const_tree type); // Convenience methods for vrange compatibility. - void set (tree min, tree max, value_range_kind kind = VR_RANGE) - { return m_vrange->set (min, max, kind); } tree type () { return m_vrange->type (); } bool varying_p () const { return m_vrange->varying_p (); } bool undefined_p () const { return m_vrange->undefined_p (); } @@ -536,7 +544,7 @@ inline Value_Range::Value_Range (tree min, tree max, value_range_kind kind) { init (TREE_TYPE (min)); - set (min, max, kind); + m_vrange->set (min, max, kind); } inline @@ -674,13 +682,6 @@ irange::varying_compatible_p () const return true; } -inline void -irange::set (tree type, const wide_int_ref &min, const wide_int_ref &max, - value_range_kind kind) -{ - set (wide_int_to_tree (type, min), wide_int_to_tree (type, max), kind); -} - inline bool vrange::varying_p () const { @@ -707,8 +708,8 @@ irange::nonzero_p () const if (undefined_p ()) return false; - tree zero = build_zero_cst (type ()); - return *this == int_range<2> (zero, zero, VR_ANTI_RANGE); + wide_int zero = wi::zero (TYPE_PRECISION (type ())); + return *this == int_range<2> (type (), zero, zero, VR_ANTI_RANGE); } inline bool @@ -717,6 +718,12 @@ irange::supports_p (const_tree type) return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type); } +inline bool +irange::contains_p (tree cst) const +{ + return contains_p (wi::to_wide (cst)); +} + inline bool range_includes_zero_p (const irange *vr) { @@ -726,7 +733,7 @@ range_includes_zero_p (const irange *vr) if (vr->varying_p ()) return true; - tree zero = build_zero_cst (vr->type ()); + wide_int zero = wi::zero (TYPE_PRECISION (vr->type ())); return vr->contains_p (zero); } @@ -906,8 +913,8 @@ irange::upper_bound () const inline void irange::set_nonzero (tree type) { - tree zero = build_int_cst (type, 0); - irange_set_anti_range (zero, zero); + wide_int zero = wi::zero (TYPE_PRECISION (type)); + set (type, zero, zero, VR_ANTI_RANGE); } // Set value range VR to a ZERO range of type TYPE. @@ -915,8 +922,8 @@ irange::set_nonzero (tree type) inline void irange::set_zero (tree type) { - tree z = build_int_cst (type, 0); - irange_set (z, z); + wide_int zero = wi::zero (TYPE_PRECISION (type)); + set (type, zero, zero); } // Normalize a range to VARYING or UNDEFINED if possible. @@ -935,6 +942,16 @@ irange::normalize_kind () } } +inline bool +contains_zero_p (const irange &r) +{ + if (r.undefined_p ()) + return true; + + wide_int zero = wi::zero (TYPE_PRECISION (r.type ())); + return r.contains_p (zero); +} + // Return the maximum value for TYPE. inline tree @@ -1083,6 +1100,12 @@ frange::update_nan (bool sign) } } +inline bool +frange::contains_p (tree cst) const +{ + return contains_p (*TREE_REAL_CST_PTR (cst)); +} + // Clear the NAN bit and adjust the range. inline void diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 3d28198f9f5..49ae324419a 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -88,8 +88,7 @@ simplify_using_ranges::op_with_boolean_value_range_p (tree op, gimple *s) as [0,1]. */ value_range vr; return (query->range_of_expr (vr, op, s) - && vr == value_range (build_zero_cst (TREE_TYPE (op)), - build_one_cst (TREE_TYPE (op)))); + && vr == range_true_and_false (TREE_TYPE (op))); } /* Helper function for simplify_internal_call_using_ranges and @@ -316,7 +315,11 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, value_range maxvr, vr0, vr1; if (!query->range_of_expr (vr0, init, stmt)) vr0.set_varying (TREE_TYPE (init)); - vr1.set (TREE_TYPE (init), wtmp, wtmp); + tree tinit = TREE_TYPE (init); + wide_int winit = wide_int::from (wtmp, + TYPE_PRECISION (tinit), + TYPE_SIGN (tinit)); + vr1.set (TREE_TYPE (init), winit, winit); range_op_handler handler (PLUS_EXPR, TREE_TYPE (init)); if (!handler.fold_range (maxvr, TREE_TYPE (init), vr0, vr1)) @@ -444,15 +447,25 @@ simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt) else { value_range vro, vri; + tree type = TREE_TYPE (op0); if (code == GT_EXPR || code == GE_EXPR) { - vro.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x, VR_ANTI_RANGE); - vri.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x); + vro.set (type, + wi::to_wide (TYPE_MIN_VALUE (type)), + wi::to_wide (x), VR_ANTI_RANGE); + vri.set (type, + wi::to_wide (TYPE_MIN_VALUE (type)), + wi::to_wide (x)); } else if (code == LT_EXPR || code == LE_EXPR) { - vro.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x); - vri.set (TYPE_MIN_VALUE (TREE_TYPE (op0)), x, VR_ANTI_RANGE); + vro.set (type, + wi::to_wide (TYPE_MIN_VALUE (type)), + wi::to_wide (x)); + vri.set (type, + wi::to_wide (TYPE_MIN_VALUE (type)), + wi::to_wide (x), + VR_ANTI_RANGE); } else gcc_unreachable ();