From patchwork Mon May 30 13:27:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54527 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DEDF03857343 for ; Mon, 30 May 2022 13:28:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DEDF03857343 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917316; bh=/EeOqfZArpSfe53tJs+juGzKEGEyDgV+OC2VJy4qSCc=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=ZhBJ8tIYF5IkF0gZJdFrszo7cEhoOAU1ZSXJQ4Mu6p7snRP/OoAsmjQ6xopQwNiqH 10dxD5VyueYGcPgdf54tis3FUG8ndM8a+u3bLLVukLGoSbaBvRMXgz4Vj0rp3b9L0f wa/7rM6gYtC4lVn20LLwJXLAia5UPtBvOCD2OK9I= 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 A5810385800E for ; Mon, 30 May 2022 13:28:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A5810385800E 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-607-0vkv8KQZPROKt_PJ3cwFSQ-1; Mon, 30 May 2022 09:28:03 -0400 X-MC-Unique: 0vkv8KQZPROKt_PJ3cwFSQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A91D6185A79C for ; Mon, 30 May 2022 13:28:03 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 358BD2026D07; Mon, 30 May 2022 13:28:03 +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 24UDS0Nt1752170 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:00 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS01Y1752164; Mon, 30 May 2022 15:28:00 +0200 To: GCC patches Subject: [PATCH 1/5] Implement abstract vrange class. Date: Mon, 30 May 2022 15:27:47 +0200 Message-Id: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.5 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This is a series of patches making ranger type agnostic in preparation for contributing support for other types of ranges (pointers and floats initially). The first step in this process is to implement vrange, an abstract class that will be exclusively used by ranger, and from which all ranges will inherit. Vrange provides the minimum operations for ranger to work. The current virtual methods are what we've used to implement frange (floats) and prange (pointers), but we may restrict the virtual methods further as other ranges come about (i.e. set_nonnegative() has no meaning for a future string range). This patchset also provides a mechanism for declaring local type agnostic ranges that can transparently hold an irange, frange, prange's, etc, and a dispatch mechanism for range-ops to work with various range types. More details in the relevant patches. FUTURE PLAN =========== The plan after this is to contribute a bare bones implementation for floats (frange) that will provide relationals, followed by a separation of integers and pointers (irange and prange). Once this is in place, we can further enhance both floats and pointers. For example, pointer tracking, pointer plus optimizations, and keeping track of NaN's, etc. Once frange and prange come live, all ranger clients will immediately benefit from these enhancements. For instance, in our local branch, the threader is already float aware with regards to relationals. We expect to wait a few weeks before starting to contribute further enhancements to give the tree a time to stabilize, and Andrew time to rebase his upcoming patches :-P. NOTES ===== In discussions with Andrew, it has become clear that with vrange coming about, supports_type_p() is somewhat ambiguous. Prior to vrange it has been used to (a) determine if a type is supported by ranger, (b) as a short-cut for checking if a type is pointer or integer, as well as (c) to see if a given range can hold a type. These things have had the same meaning in irange, but are slightly different with vrange. I will address this in a follow-up patch. Speaking of supported types, we now provide an unsupported_range for passing around ranges for unsupported types. We've been silently doing this for a while, in both vr-values by creating VARYING for unsupported types with error_mark_node end points, and in ranger when we pass an unsupported range before we realize in range_of_expr that it's unsupported. This class just formalizes what we've already been doing in an irange, but making it explicit that you can't do anything with these ranges except pass them. Any other operation traps. There is no GTY support for vrange yet, as we don't store it long term. When we contribute support for global ranges (think SSA_NAME_RANGE_INFO but for generic ranges), we will include it. There was just no need to pollute this patchset with it. TESTING ======= The patchset has been tested on x86-64 Linux as well as ppc64 Linux. I have also verified that we fold the same number of conditionals in evrp as well as thread the same number of paths. There should be no user visible changes. We have also benchmarked the work, with the final numbers being an *improvement* of 1.92% for evrp, and 0.82% for VRP. Overall compilation has a miniscule improvement. This is despite the extra indirection level. The improvements are mostly because of small cleanups required for the generalization of ranges. As a sanity check, I stuck kcachegrind on a few sample .ii files to see where the time was being gained. Most of the gain came from gimple_range_global() being 19% faster. This function is called a lot, and it was constructing a legacy value_range, then returning it by value, which the caller then had to convert to an irange. This is in line with other pending work: anytime we get rid of legacy, we gain time. I will wait a few days before committing to welcome any comments. gcc/ChangeLog: * value-range-equiv.cc (value_range_equiv::set): New. * value-range-equiv.h (class value_range_equiv): Make set method virtual. Remove default bitmap argument from set method. * value-range.cc (vrange::contains_p): New. (vrange::singleton_p): New. (vrange::operator=): New. (vrange::operator==): New. (irange::fits_p): Move to .cc file. (irange::set_nonnegative): New. (unsupported_range::unsupported_range): New. (unsupported_range::set): New. (unsupported_range::type): New. (unsupported_range::set_undefined): New. (unsupported_range::set_varying): New. (unsupported_range::dump): New. (unsupported_range::union_): New. (unsupported_range::intersect): New. (unsupported_range::zero_p): New. (unsupported_range::nonzero_p): New. (unsupported_range::set_nonzero): New. (unsupported_range::set_zero): New. (unsupported_range::set_nonnegative): New. (unsupported_range::fits_p): New. (irange::set): Call irange::set_undefined. (irange::verify_range): Check discriminator field. (irange::dump): Dump [irange] marker. (irange::debug): Move to... (vrange::debug): ...here. (dump_value_range): Accept vrange. (debug): Same. * value-range.h (enum value_range_discriminator): New. (class vrange): New. (class unsupported_range): New. (struct vrange_traits): New. (is_a): New. (as_a): New. (class irange): Inherit from vrange. (dump_value_range): Adjust for vrange. (irange::kind): Rename to... (vrange::kind): ...this. (irange::varying_p): Rename to... (vrange::varying_p): ...this. (irange::undefined_p): Rename to... (vrange::undefined_p): ...this. (irange::irange): Set discriminator. (irange::union_): Convert to irange before passing to irange method. (irange::intersect): Same. (vrange::supports_type_p): New. * vr-values.cc (vr_values::extract_range_from_binary_expr): Pass NULL bitmap argument to value_range_equiv::set. (vr_values::extract_range_basic): Same. --- gcc/value-range-equiv.cc | 6 ++ gcc/value-range-equiv.h | 3 +- gcc/value-range.cc | 168 ++++++++++++++++++++++++++++++++- gcc/value-range.h | 195 ++++++++++++++++++++++++++++++++------- gcc/vr-values.cc | 6 +- 5 files changed, 338 insertions(+), 40 deletions(-) diff --git a/gcc/value-range-equiv.cc b/gcc/value-range-equiv.cc index 77c6f5ca99d..b0ae1288a09 100644 --- a/gcc/value-range-equiv.cc +++ b/gcc/value-range-equiv.cc @@ -50,6 +50,12 @@ value_range_equiv::set (tree min, tree max, bitmap equiv, check (); } +void +value_range_equiv::set (tree min, tree max, value_range_kind kind) +{ + set (min, max, m_equiv, kind); +} + void value_range_equiv::set (tree val) { diff --git a/gcc/value-range-equiv.h b/gcc/value-range-equiv.h index 0aa1069cb61..743ceb2b227 100644 --- a/gcc/value-range-equiv.h +++ b/gcc/value-range-equiv.h @@ -41,9 +41,10 @@ class GTY((user)) value_range_equiv : public value_range void move (value_range_equiv *); /* Leaves equiv bitmap alone. */ + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; void update (tree, tree, value_range_kind = VR_RANGE); /* Deep-copies equiv bitmap argument. */ - void set (tree, tree, bitmap = NULL, value_range_kind = VR_RANGE); + void set (tree, tree, bitmap, value_range_kind = VR_RANGE); void set (tree); bool operator== (const value_range_equiv &) const /* = delete */; diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 2e7385aecc2..97ff0614f48 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -30,6 +30,162 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "gimple-range.h" +// Default implementation when none has been defined. + +bool +vrange::contains_p (tree) const +{ + return false; +} + +// Default implementation when none has been defined. + +bool +vrange::singleton_p (tree *) const +{ + return false; +} + +// Assignment operator for generic ranges. Copying incompatible types +// is not allowed. + +vrange & +vrange::operator= (const vrange &src) +{ + if (is_a (src)) + { + as_a (*this) = as_a (src); + return *this; + } + else + gcc_unreachable (); +} + +// Equality operator for generic ranges. + +bool +vrange::operator== (const vrange &src) const +{ + if (is_a (src)) + return as_a (*this) == as_a (src); + gcc_unreachable (); +} + +// Return TRUE if R fits in THIS. + +bool +irange::fits_p (const vrange &r) const +{ + return m_max_ranges >= as_a (r).num_pairs (); +} + +void +irange::set_nonnegative (tree type) +{ + set (build_int_cst (type, 0), TYPE_MAX_VALUE (type)); +} + +unsupported_range::unsupported_range () +{ + m_discriminator = VR_UNKNOWN; + set_undefined (); +} + +void +unsupported_range::set (tree, tree, value_range_kind) +{ + gcc_unreachable (); +} + +tree +unsupported_range::type () const +{ + gcc_unreachable (); + return nullptr; +} + +void +unsupported_range::set_undefined () +{ + m_kind = VR_UNDEFINED; +} + +void +unsupported_range::set_varying (tree) +{ + gcc_unreachable (); +} + +void +unsupported_range::dump (FILE *file) const +{ + fprintf (file, "[unsupported_range] "); + if (undefined_p ()) + { + fprintf (file, "UNDEFINED"); + return; + } + if (varying_p ()) + { + fprintf (file, "VARYING"); + return; + } + gcc_unreachable (); +} + +bool +unsupported_range::union_ (const vrange &) +{ + gcc_unreachable (); + return false; +} + +bool +unsupported_range::intersect (const vrange &) +{ + gcc_unreachable (); + return false; +} + +bool +unsupported_range::zero_p () const +{ + gcc_unreachable (); + return false; +} + +bool +unsupported_range::nonzero_p () const +{ + gcc_unreachable (); + return false; +} + +void +unsupported_range::set_nonzero (tree) +{ + gcc_unreachable (); +} + +void +unsupported_range::set_zero (tree) +{ + gcc_unreachable (); +} + +void +unsupported_range::set_nonnegative (tree) +{ + gcc_unreachable (); +} + +bool +unsupported_range::fits_p (const vrange &) const +{ + gcc_unreachable (); + return false; +} + // Here we copy between any two irange's. The ranges can be legacy or // multi-ranges, and copying between any combination works correctly. @@ -291,7 +447,7 @@ irange::set (tree min, tree max, value_range_kind kind) } if (kind == VR_UNDEFINED) { - set_undefined (); + irange::set_undefined (); return; } @@ -370,6 +526,7 @@ irange::set (tree min, tree max, value_range_kind kind) void irange::verify_range () { + gcc_checking_assert (m_discriminator == VR_IRANGE); if (m_kind == VR_UNDEFINED) { gcc_checking_assert (m_num_ranges == 0); @@ -2087,6 +2244,7 @@ dump_bound_with_infinite_markers (FILE *file, tree bound) void irange::dump (FILE *file) const { + fprintf (file, "[irange] "); if (undefined_p ()) { fprintf (file, "UNDEFINED"); @@ -2121,27 +2279,27 @@ irange::dump (FILE *file) const } void -irange::debug () const +vrange::debug () const { dump (stderr); fprintf (stderr, "\n"); } void -dump_value_range (FILE *file, const irange *vr) +dump_value_range (FILE *file, const vrange *vr) { vr->dump (file); } DEBUG_FUNCTION void -debug (const irange *vr) +debug (const vrange *vr) { dump_value_range (stderr, vr); fprintf (stderr, "\n"); } DEBUG_FUNCTION void -debug (const irange &vr) +debug (const vrange &vr) { debug (&vr); } diff --git a/gcc/value-range.h b/gcc/value-range.h index ec59d2e4f23..0061f667092 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_VALUE_RANGE_H #define GCC_VALUE_RANGE_H +class irange; + // Types of value ranges. enum value_range_kind { @@ -37,24 +39,71 @@ enum value_range_kind VR_LAST }; -// Range of values that can be associated with an SSA_NAME. -// -// This is the base class without any storage. +// Discriminator between different vrange types. + +enum value_range_discriminator +{ + // Range holds an integer or pointer. + VR_IRANGE, + // Range holds an unsupported type. + VR_UNKNOWN +}; + +// Abstract class for ranges of any of the supported types. + +class vrange +{ + template friend bool is_a (vrange &); +public: + virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0; + virtual tree type () const = 0; + virtual void set_varying (tree type) = 0; + virtual void set_undefined () = 0; + virtual void dump (FILE * = stderr) const = 0; + virtual bool union_ (const vrange &) = 0; + virtual bool intersect (const vrange &) = 0; + virtual bool singleton_p (tree *result = NULL) const; + virtual bool contains_p (tree cst) const; + virtual bool zero_p () const = 0; + virtual bool nonzero_p () const = 0; + virtual void set_nonzero (tree type) = 0; + virtual void set_zero (tree type) = 0; + virtual void set_nonnegative (tree type) = 0; + virtual bool fits_p (const vrange &r) const = 0; + + static bool supports_type_p (tree); + + bool varying_p () const; + bool undefined_p () const; + vrange& operator= (const vrange &); + bool operator== (const vrange &) const; + bool operator!= (const vrange &r) const { return !(*this == r); } + + enum value_range_kind kind () const; // DEPRECATED + void debug () const; + +protected: + ENUM_BITFIELD(value_range_kind) m_kind : 8; + ENUM_BITFIELD(value_range_discriminator) m_discriminator : 4; +}; + +// An integer range without any storage. -class GTY((user)) irange +class GTY((user)) irange : public vrange { friend class irange_allocator; public: // In-place setters. - void set (tree, tree, value_range_kind = VR_RANGE); - void set_nonzero (tree); - void set_zero (tree); - void set_varying (tree type); - void set_undefined (); + virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + virtual void set_nonzero (tree type) override; + virtual void set_zero (tree type) override; + virtual void set_nonnegative (tree type) override; + virtual void set_varying (tree type) override; + virtual void set_undefined () override; // Range types. static bool supports_type_p (tree); - tree type () const; + virtual tree type () const override; // Iteration over sub-ranges. unsigned num_pairs () const; @@ -63,16 +112,14 @@ public: wide_int upper_bound () const; // Predicates. - bool zero_p () const; - bool nonzero_p () const; - bool undefined_p () const; - bool varying_p () const; - bool singleton_p (tree *result = NULL) const; - bool contains_p (tree) const; + 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; // In-place operators. - bool union_ (const irange &); - bool intersect (const irange &); + virtual bool union_ (const vrange &) override; + virtual bool intersect (const vrange &) override; void invert (); // Operator overloads. @@ -81,12 +128,10 @@ public: bool operator!= (const irange &r) const { return !(*this == r); } // Misc methods. - bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); } - void dump (FILE * = stderr) const; - void debug () const; + virtual bool fits_p (const vrange &r) const override; + virtual void dump (FILE * = stderr) const override; // Deprecated legacy public methods. - enum value_range_kind kind () const; // DEPRECATED tree min () const; // DEPRECATED tree max () const; // DEPRECATED bool symbolic_p () const; // DEPRECATED @@ -139,7 +184,6 @@ private: bool intersect (const wide_int& lb, const wide_int& ub); unsigned char m_num_ranges; unsigned char m_max_ranges; - ENUM_BITFIELD(value_range_kind) m_kind : 8; tree *m_base; }; @@ -173,6 +217,88 @@ private: tree m_ranges[N*2]; }; +// Unsupported temporaries may be created by ranger before it's known +// they're unsupported, or by vr_values::get_value_range. All +// operations except construction cause a trap. + +class unsupported_range : public vrange +{ +public: + unsupported_range (); + virtual void set (tree, tree, value_range_kind) override; + virtual tree type () const override; + virtual void set_varying (tree type) override; + virtual void set_undefined () override; + virtual void dump (FILE *) const override; + virtual bool union_ (const vrange &) override; + virtual bool intersect (const vrange &) override; + virtual bool zero_p () const override; + virtual bool nonzero_p () const override; + virtual void set_nonzero (tree) override; + virtual void set_zero (tree) override; + virtual void set_nonnegative (tree) override; + virtual bool fits_p (const vrange &) const override; +}; + +// Traits to implement vrange is_a<> and as_a<>. + +template +struct vrange_traits +{ + // Default to something unusable. + typedef void range_type; +}; + +template<> +struct vrange_traits +{ + typedef irange range_type; +}; + +template +inline bool +is_a (vrange &v) +{ + gcc_unreachable (); + return false; +} + +template +inline bool +is_a (const vrange &v) +{ + // Reuse is_a to implement the const version. + const T &derived = static_cast (v); + return is_a (const_cast (derived)); +} + +template +inline T & +as_a (vrange &v) +{ + typedef typename vrange_traits::range_type range_type; + gcc_checking_assert (is_a (v)); + return static_cast (v); +} + +template +inline const T & +as_a (const vrange &v) +{ + typedef typename vrange_traits::range_type range_type; + gcc_checking_assert (is_a (v)); + return static_cast (v); +} + +// Specializations for the different range types. + +template <> +inline bool +is_a (vrange &v) +{ + return v.m_discriminator == VR_IRANGE; +} + // This is a special int_range<1> with only one pair, plus // VR_ANTI_RANGE magic to describe slightly more than can be described // in one pair. It is described in the code as a "legacy range" (as @@ -197,13 +323,13 @@ irange::legacy_mode_p () const extern bool range_has_numeric_bounds_p (const irange *); extern bool ranges_from_anti_range (const value_range *, value_range *, value_range *); -extern void dump_value_range (FILE *, const irange *); +extern void dump_value_range (FILE *, const vrange *); extern bool vrp_val_is_min (const_tree); extern bool vrp_val_is_max (const_tree); extern bool vrp_operand_equal_p (const_tree, const_tree); inline value_range_kind -irange::kind () const +vrange::kind () const { return m_kind; } @@ -293,13 +419,13 @@ irange::varying_compatible_p () const } inline bool -irange::varying_p () const +vrange::varying_p () const { return m_kind == VR_VARYING; } inline bool -irange::undefined_p () const +vrange::undefined_p () const { return m_kind == VR_UNDEFINED; } @@ -398,6 +524,7 @@ gt_pch_nx (int_range *x, gt_pointer_operator op, void *cookie) inline irange::irange (tree *base, unsigned nranges) { + m_discriminator = VR_IRANGE; m_base = base; m_max_ranges = nranges; set_undefined (); @@ -547,21 +674,21 @@ irange::upper_bound () const } inline bool -irange::union_ (const irange &r) +irange::union_ (const vrange &r) { dump_flags_t m_flags = dump_flags; dump_flags &= ~TDF_DETAILS; - bool ret = irange::legacy_verbose_union_ (&r); + bool ret = irange::legacy_verbose_union_ (&as_a (r)); dump_flags = m_flags; return ret; } inline bool -irange::intersect (const irange &r) +irange::intersect (const vrange &r) { dump_flags_t m_flags = dump_flags; dump_flags &= ~TDF_DETAILS; - bool ret = irange::legacy_verbose_intersect (&r); + bool ret = irange::legacy_verbose_intersect (&as_a (r)); dump_flags = m_flags; return ret; } @@ -608,6 +735,12 @@ irange::normalize_kind () } } +inline bool +vrange::supports_type_p (tree type) +{ + return irange::supports_type_p (type); +} + // Return the maximum value for TYPE. inline tree diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 47faa4ff938..6f8583c8d01 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -883,7 +883,7 @@ vr_values::extract_range_from_binary_expr (value_range_equiv *vr, wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); tree range_min = build_zero_cst (expr_type); tree range_max = wide_int_to_tree (expr_type, wmax - 1); - vr->set (range_min, range_max); + vr->set (range_min, range_max, NULL); return; } } @@ -1275,7 +1275,7 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt) /* This is the boolean return value whether compare and exchange changed anything or not. */ vr->set (build_int_cst (type, 0), - build_int_cst (type, 1)); + build_int_cst (type, 1), NULL); return; } break; @@ -1297,7 +1297,7 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt) vr->set_varying (type); else vr->set (build_int_cst (type, 0), - build_int_cst (type, 1)); + build_int_cst (type, 1), NULL); } else if (types_compatible_p (type, TREE_TYPE (op0)) && types_compatible_p (type, TREE_TYPE (op1))) From patchwork Mon May 30 13:27:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54528 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E57BF3838006 for ; Mon, 30 May 2022 13:29:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E57BF3838006 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917374; bh=C0D5TERBfk+Viwm6mnCka4iOxmw787SS+PbKwL+JU3U=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=wYU+I32jnGm8cXRVPAm/2Bd4PzPu/hv/xLBB+UvXUHUlCrFWKiK8j3ahtEccyHeUK ZufnJk+kVonwZWjDKSQEXWOj+mGY5fVxXN5bdo2+jk2DCboCMV5Q/F5QZEhiVy6lpk f4YdCq182ERLROkn8omBo8hS2vuGtGGG3EzV5ZKI= 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.133.124]) by sourceware.org (Postfix) with ESMTPS id E65A33857343 for ; Mon, 30 May 2022 13:28:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E65A33857343 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-612-bqt3mv57O1qooQtHYq9yCQ-1; Mon, 30 May 2022 09:28:05 -0400 X-MC-Unique: bqt3mv57O1qooQtHYq9yCQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3A0683C0E766 for ; Mon, 30 May 2022 13:28:05 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E138740CFD0A; Mon, 30 May 2022 13:28:04 +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 24UDS2Xn1752178 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:02 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS2jW1752177; Mon, 30 May 2022 15:28:02 +0200 To: GCC patches Subject: [PATCH 2/5] Implement generic range temporaries. Date: Mon, 30 May 2022 15:27:48 +0200 Message-Id: <20220530132751.1752112-2-aldyh@redhat.com> In-Reply-To: <20220530132751.1752112-1-aldyh@redhat.com> References: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Now that we have generic ranges, we need a way to define generic local temporaries on the stack for intermediate calculations in the ranger and elsewhere. We need temporaries analogous to int_range_max, but for any of the supported types (currently just integers, but soon integers, pointers, and floats). The tmp_range object is such a temporary. It is designed to be transparently used as a vrange. It shares vrange's abstract API, and implicitly casts itself to a vrange when passed around. The ultimate name will be value_range, but we need to remove legacy first for that to happen. Until then, tmp_range will do. Sample usage is as follows. Instead of: extern void foo (vrange &); int_range_max t; t.set_nonzero (type); foo (t); one does: tmp_range t (type); t.set_nonzero (type); foo (t); You can also delay initialization, for use in loops for example: tmp_range t; ... t.init (type); t.set_varying (type); Creating an supported range type, will result in an unsupported_range object being created, which will trap if anything but set_undefined() and undefined_p() are called on it. There's no size penalty for the unsupported_range, since its immutable and can be shared across instances. Since supports_type_p() is called at construction time for each temporary, I've removed the non-zero check from this function, which was mostly unneeded. I fixed the handful of callers that were passing null types, and in the process sped things up a bit. As more range types come about, the tmp_range class will be augmented to support them by adding the relevant bits in the initialization code. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-fold.h (gimple_range_type): Check type before calling supports_type_p. * gimple-range-path.cc (path_range_query::range_of_stmt): Same. * value-query.cc (range_query::get_tree_range): Same. * value-range.cc (tmp_range::lower_bound): New. (tmp_range::upper_bound): New. (tmp_range::dump): New. * value-range.h (class tmp_range): New. (irange::supports_type_p): Do not check if type is non-zero. --- gcc/gimple-range-fold.h | 2 +- gcc/gimple-range-path.cc | 2 +- gcc/value-query.cc | 3 +- gcc/value-range.cc | 38 ++++++++++++ gcc/value-range.h | 130 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 169 insertions(+), 6 deletions(-) diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 53a5bf85dd4..20cb73dabb9 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -81,7 +81,7 @@ gimple_range_type (const gimple *s) type = TREE_TYPE (type); } } - if (irange::supports_type_p (type)) + if (type && irange::supports_type_p (type)) return type; return NULL_TREE; } diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index 459d3797da7..66f433dd1d5 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -755,7 +755,7 @@ path_range_query::range_of_stmt (irange &r, gimple *stmt, tree) { tree type = gimple_range_type (stmt); - if (!irange::supports_type_p (type)) + if (!type || !irange::supports_type_p (type)) return false; // If resolving unknowns, fold the statement making use of any diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 9ccd802457b..26e3858103b 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -249,7 +249,8 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) if (UNARY_CLASS_P (expr)) { range_operator *op = range_op_handler (TREE_CODE (expr), type); - if (op) + tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0)); + if (op && irange::supports_type_p (op0_type)) { int_range_max r0; range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 97ff0614f48..c5f326ab479 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -30,6 +30,42 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "gimple-range.h" +// Convenience function only available for integers and pointers. + +wide_int +tmp_range::lower_bound () const +{ + if (is_a (*m_vrange)) + return as_a (*m_vrange).lower_bound (); + gcc_unreachable (); +} + +// Convenience function only available for integers and pointers. + +wide_int +tmp_range::upper_bound () const +{ + if (is_a (*m_vrange)) + return as_a (*m_vrange).upper_bound (); + gcc_unreachable (); +} + +void +tmp_range::dump (FILE *out) const +{ + if (m_vrange) + m_vrange->dump (out); + else + fprintf (out, "NULL"); +} + +DEBUG_FUNCTION void +debug (const tmp_range &r) +{ + r.dump (stderr); + fprintf (stderr, "\n"); +} + // Default implementation when none has been defined. bool @@ -186,6 +222,8 @@ unsupported_range::fits_p (const vrange &) const return false; } +unsupported_range tmp_range::m_unsupported; + // Here we copy between any two irange's. The ranges can be legacy or // multi-ranges, and copying between any combination works correctly. diff --git a/gcc/value-range.h b/gcc/value-range.h index 0061f667092..d51998145da 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -54,6 +54,7 @@ enum value_range_discriminator class vrange { template friend bool is_a (vrange &); + friend class tmp_range; public: virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0; virtual tree type () const = 0; @@ -313,6 +314,131 @@ typedef int_range<1> value_range; // calculations. typedef int_range<255> int_range_max; +// This is an "infinite" precision range object for use in temporary +// calculations for any of the handled types. The object can be +// transparently used as a vrange. + +class tmp_range +{ +public: + tmp_range (); + tmp_range (const vrange &r); + tmp_range (tree type); + bool init (tree type); + vrange& operator= (const vrange &); + bool operator== (const tmp_range &r) const; + bool operator!= (const tmp_range &r) const; + operator vrange &(); + operator const vrange &() const; + void dump (FILE *out = stderr) const; + + // Convenience methods for vrange compatability. + 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 (); } + enum value_range_kind kind () { return m_vrange->kind (); } + bool varying_p () const { return m_vrange->varying_p (); } + bool undefined_p () const { return m_vrange->undefined_p (); } + void set_varying (tree type) { m_vrange->set_varying (type); } + void set_undefined () { m_vrange->set_undefined (); } + bool union_ (const vrange &r) { return m_vrange->union_ (r); } + bool intersect (const vrange &r) { return m_vrange->intersect (r); } + bool singleton_p (tree *result = NULL) const + { return m_vrange->singleton_p (result); } + bool zero_p () const { return m_vrange->zero_p (); } + wide_int lower_bound () const; // For irange/prange compatability. + wide_int upper_bound () const; // For irange/prange compatability. +private: + static unsupported_range m_unsupported; + vrange *m_vrange; + int_range_max m_irange; + DISABLE_COPY_AND_ASSIGN (tmp_range); +}; + +// This default constructor leaves the temporary uninitialized. Use +// init() to initialize. + +inline +tmp_range::tmp_range () +{ + m_vrange = nullptr; +} + +// Copy constructor from a vrange. + +inline +tmp_range::tmp_range (const vrange &r) +{ + *this = r; +} + +// Copy constructor from a tree TYPE. +// +// Note that unlike the similarly named int_range<> constructor which +// defaults to VARYING, this constructor defaults to UNDEFINED. +// Defaulting to VARYING had an unfortunate performance penalty. We +// could remove the int_range<> (type) constructor if this is +// confusing. + +inline +tmp_range::tmp_range (tree type) +{ + init (type); +} + +// Initialize object so it is possible to store temporaries of TYPE +// into it. The range of the temporary is undefined after this call, +// and must be explicitly set (set_varying, set_undefined, etc). + +inline bool +tmp_range::init (tree type) +{ + gcc_checking_assert (TYPE_P (type)); + + if (irange::supports_type_p (type)) + m_vrange = &m_irange; + else + m_vrange = &m_unsupported; + return true; +} + +inline vrange & +tmp_range::operator= (const vrange &r) +{ + if (is_a (r)) + { + m_irange = as_a (r); + m_vrange = &m_irange; + return *m_vrange; + } + else + gcc_unreachable (); +} + +inline bool +tmp_range::operator== (const tmp_range &r) const +{ + return *m_vrange == *r.m_vrange; +} + +inline bool +tmp_range::operator!= (const tmp_range &r) const +{ + return *m_vrange != *r.m_vrange; +} + +inline +tmp_range::operator vrange &() +{ + return *m_vrange; +} + +inline +tmp_range::operator const vrange &() const +{ + return *m_vrange; +} + // Returns true for an old-school value_range as described above. inline bool irange::legacy_mode_p () const @@ -451,9 +577,7 @@ irange::nonzero_p () const inline bool irange::supports_type_p (tree type) { - if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) - return type; - return false; + return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type); } inline bool From patchwork Mon May 30 13:27:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54530 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A101A38485B5 for ; Mon, 30 May 2022 13:31:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A101A38485B5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917502; bh=t5HH/ucHhGRLOUecMqVWMLNZWyWwEQX5wRtYR9VnJSo=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=RocufAUz6PkbQ+ESCj/7Kt1y/aePOGhOJ8QZJ9P5AxJQennW8I/oxQ/FwQ5cpw59x R/pMU++bvkS2Zslw3AWSh2TTlHdJ5heHS5qAO+OXE8CCsVKQEPgF+LXFDjTSfMu0Wn Ygqit0ifN/kWNLSbG+Hnla38xuELx1NwKmSvbdEI= 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 1E5EF385E03D for ; Mon, 30 May 2022 13:28:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1E5EF385E03D Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-385-ZG0jmDUAP320dfw9fsxIUg-1; Mon, 30 May 2022 09:28:05 -0400 X-MC-Unique: ZG0jmDUAP320dfw9fsxIUg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 30CF82919EC5 for ; Mon, 30 May 2022 13:28:05 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 84B4240EC002; Mon, 30 May 2022 13:28:04 +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 24UDS2T01752182 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:03 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS22a1752181; Mon, 30 May 2022 15:28:02 +0200 To: GCC patches Subject: [PATCH 3/5] Convert range-op.* to vrange. Date: Mon, 30 May 2022 15:27:49 +0200 Message-Id: <20220530132751.1752112-3-aldyh@redhat.com> In-Reply-To: <20220530132751.1752112-1-aldyh@redhat.com> References: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch provides the infrastructure to make range-ops type agnostic. First, the range_op_handler function has been replaced with an object of the same name. It's coded in such a way to minimize changes to the code base, and to encapsulate the dispatch code. Instead of: range_operator *op = range_op_handler (code, type); if (op) op->fold_range (...); We now do: range_op_handler op (code, type); if (op) op->fold_range (...); I've folded gimple_range_handler into the range_op_handler class, since it's also a query into the range operators. Instead of: range_operator *handler = gimple_range_handler (stmt); We now do: range_op_handler handler (stmt); This all has the added benefit of moving all the dispatch code into an independent class and avoid polluting range_operator (which we'll further split later when frange and prange come live). There's this annoying "using" keyword that's been added to each operator due to hiding rules in C++. The issue is that we will have different virtual versions of fold_range() for each combination of operands. For example: // Traditional binary op on irange's. fold_range (irange &lhs, const irange &op1, const irange &op2); // For POINTER_DIFF_EXPR: fold_range (irange &lhs, const prange &op1, const prange &op2); // Cast from irange to prange. fold_range (prange &lhs, const irange &op1, const irange &op2); Overloading virtuals when there are multiple same named methods causes hidden virtuals warnings from -Woverloaded-virtual, thus the using keyword. An alternative would be to have different names: fold_range_III, fold_range_IPP, fold_range_PII, but that's uglier still. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for vrange and convert range_op_handler function calls to use the identically named object. * gimple-range-fold.cc (gimple_range_operand1): Same. (gimple_range_operand2): Same. (fold_using_range::fold_stmt): Same. (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_builtin_ubsan_call): Same. (fold_using_range::relation_fold_and_or): Same. (fur_source::register_outgoing_edges): Same. * gimple-range-fold.h (gimple_range_handler): Remove. * gimple-range-gori.cc (gimple_range_calc_op1): Adjust for vrange. (gimple_range_calc_op2): Same. (range_def_chain::get_def_chain): Same. (gori_compute::compute_operand_range): Same. (gori_compute::condexpr_adjust): Same. * gimple-range.cc (gimple_ranger::prefill_name): Same. (gimple_ranger::prefill_stmt_dependencies): Same. * range-op.cc (get_bool_state): Same. (class operator_equal): Add using clause. (class operator_not_equal): Same. (class operator_lt): Same. (class operator_le): Same. (class operator_gt): Same. (class operator_ge): Same. (class operator_plus): Same. (class operator_minus): Same. (class operator_mult): Same. (class operator_exact_divide): Same. (class operator_lshift): Same. (class operator_rshift): Same. (class operator_cast): Same. (class operator_logical_and): Same. (class operator_bitwise_and): Same. (class operator_logical_or): Same. (class operator_bitwise_or): Same. (class operator_bitwise_xor): Same. (class operator_trunc_mod): Same. (class operator_logical_not): Same. (class operator_bitwise_not): Same. (class operator_cst): Same. (class operator_identity): Same. (class operator_unknown): Same. (class operator_abs): Same. (class operator_negate): Same. (class operator_addr_expr): Same. (class pointer_or_operator): Same. (operator_plus::op1_range): Adjust for vrange. (operator_minus::op1_range): Same. (operator_mult::op1_range): Same. (operator_cast::op1_range): Same. (operator_bitwise_not::fold_range): Same. (operator_negate::fold_range): Same. (range_op_handler): Rename to... (get_handler): ...this. (range_op_handler::range_op_handler): New. (range_op_handler::fold_range): New. (range_op_handler::op1_range): New. (range_op_handler::op2_range): New. (range_op_handler::lhs_op1_relation): New. (range_op_handler::lhs_op2_relation): New. (range_op_handler::op1_op2_relation): New. (range_cast): Adjust for vrange. * range-op.h (range_op_handler): Remove function. (range_cast): Adjust for vrange. (class range_op_handler): New. (get_bool_state): Adjust for vrange. (empty_range_varying): Same. (relop_early_resolve): Same. * tree-data-ref.cc (compute_distributive_range): Same. * tree-vrp.cc (get_range_op_handler): Remove. (range_fold_binary_symbolics_p): Use range_op_handler class instead of get_range_op_handler. (range_fold_unary_symbolics_p): Same. (range_fold_binary_expr): Same. (range_fold_unary_expr): Same. * value-query.cc (range_query::get_tree_range): Adjust for vrange. --- gcc/gimple-range-edge.cc | 2 +- gcc/gimple-range-fold.cc | 43 ++++---- gcc/gimple-range-fold.h | 15 --- gcc/gimple-range-gori.cc | 41 ++++---- gcc/gimple-range.cc | 6 +- gcc/range-op.cc | 215 ++++++++++++++++++++++++++++++++++----- gcc/range-op.h | 45 ++++++-- gcc/tree-data-ref.cc | 8 +- gcc/tree-vrp.cc | 44 ++++---- gcc/value-query.cc | 8 +- 10 files changed, 303 insertions(+), 124 deletions(-) diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 0bee38ba770..5bbe23ae03d 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -42,7 +42,7 @@ gimple_outgoing_range_stmt_p (basic_block bb) if (!gsi_end_p (gsi)) { gimple *s = gsi_stmt (gsi); - if (is_a (s) && gimple_range_handler (s)) + if (is_a (s) && range_op_handler (s)) return gsi_stmt (gsi); gswitch *sw = dyn_cast (s); if (sw && irange::supports_type_p (TREE_TYPE (gimple_switch_index (sw)))) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 0a947c16c58..c53d2863d5e 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -482,7 +482,7 @@ gimple_range_base_of_assignment (const gimple *stmt) tree gimple_range_operand1 (const gimple *stmt) { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); switch (gimple_code (stmt)) { @@ -515,7 +515,7 @@ gimple_range_operand1 (const gimple *stmt) tree gimple_range_operand2 (const gimple *stmt) { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); switch (gimple_code (stmt)) { @@ -551,7 +551,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) && gimple_assign_rhs_code (s) == ADDR_EXPR) return range_of_address (r, s, src); - if (gimple_range_handler (s)) + if (range_op_handler (s)) res = range_of_range_op (r, s, src); else if (is_a(s)) res = range_of_phi (r, as_a (s), src); @@ -593,7 +593,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) tree type = gimple_range_type (s); if (!type) return false; - range_operator *handler = gimple_range_handler (s); + range_op_handler handler (s); gcc_checking_assert (handler); tree lhs = gimple_get_lhs (s); @@ -606,13 +606,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) { // Fold range, and register any dependency if available. int_range<2> r2 (type); - handler->fold_range (r, type, range1, r2); + handler.fold_range (r, type, range1, r2); if (lhs && gimple_range_ssa_p (op1)) { if (src.gori ()) src.gori ()->register_dependency (lhs, op1); relation_kind rel; - rel = handler->lhs_op1_relation (r, range1, range1); + rel = handler.lhs_op1_relation (r, range1, range1); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op1); } @@ -629,7 +629,7 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) fputc ('\n', dump_file); } // Fold range, and register any dependency if available. - handler->fold_range (r, type, range1, range2, rel); + handler.fold_range (r, type, range1, range2, rel); relation_fold_and_or (r, s, src); if (lhs) { @@ -640,13 +640,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) } if (gimple_range_ssa_p (op1)) { - rel = handler->lhs_op1_relation (r, range1, range2, rel); + rel = handler.lhs_op1_relation (r, range1, range2, rel); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op1); } if (gimple_range_ssa_p (op2)) { - rel= handler->lhs_op2_relation (r, range1, range2, rel); + rel= handler.lhs_op2_relation (r, range1, range2, rel); if (rel != VREL_VARYING) src.register_relation (s, rel, lhs, op2); } @@ -921,7 +921,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR); tree type = gimple_range_type (call); - range_operator *op = range_op_handler (code, type); + range_op_handler op (code, type); gcc_checking_assert (op); int_range_max ir0, ir1; tree arg0 = gimple_call_arg (call, 0); @@ -935,7 +935,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, // Pretend the arithmetic is wrapping. If there is any overflow, // we'll complain, but will actually do wrapping operation. flag_wrapv = 1; - op->fold_range (r, type, ir0, ir1, relation); + op.fold_range (r, type, ir0, ir1, relation); flag_wrapv = saved_flag_wrapv; // If for both arguments vrp_valueize returned non-NULL, this should @@ -1391,8 +1391,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, else if (ssa1_dep1 != ssa2_dep2 || ssa1_dep2 != ssa2_dep1) return; - range_operator *handler1 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa1)); - range_operator *handler2 = gimple_range_handler (SSA_NAME_DEF_STMT (ssa2)); + range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1)); + range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2)); // If either handler is not present, no relation is found. if (!handler1 || !handler2) @@ -1400,8 +1400,8 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, int_range<2> bool_one (boolean_true_node, boolean_true_node); - relation_kind relation1 = handler1->op1_op2_relation (bool_one); - relation_kind relation2 = handler2->op1_op2_relation (bool_one); + relation_kind relation1 = handler1.op1_op2_relation (bool_one); + relation_kind relation2 = handler2.op1_op2_relation (bool_one); if (relation1 == VREL_VARYING || relation2 == VREL_VARYING) return; @@ -1441,7 +1441,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge int_range_max r; int_range<2> e0_range, e1_range; tree name; - range_operator *handler; basic_block bb = gimple_bb (s); if (e0) @@ -1472,17 +1471,17 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s)); if (ssa1 && ssa2) { - handler = gimple_range_handler (s); + range_op_handler handler (s); gcc_checking_assert (handler); if (e0) { - relation_kind relation = handler->op1_op2_relation (e0_range); + relation_kind relation = handler.op1_op2_relation (e0_range); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1) { - relation_kind relation = handler->op1_op2_relation (e1_range); + relation_kind relation = handler.op1_op2_relation (e1_range); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } @@ -1501,7 +1500,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE) continue; gimple *stmt = SSA_NAME_DEF_STMT (name); - handler = gimple_range_handler (stmt); + range_op_handler handler (stmt); if (!handler) continue; tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); @@ -1511,14 +1510,14 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler->op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r); if (relation != VREL_VARYING) register_relation (e0, relation, ssa1, ssa2); } if (e1 && gori ()->outgoing_edge_range_p (r, e1, name, *m_query) && r.singleton_p ()) { - relation_kind relation = handler->op1_op2_relation (r); + relation_kind relation = handler.op1_op2_relation (r); if (relation != VREL_VARYING) register_relation (e1, relation, ssa1, ssa2); } diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 20cb73dabb9..4b5d4b6e0b8 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -41,21 +41,6 @@ bool fold_range (irange &r, gimple *s, irange &r1); bool fold_range (irange &r, gimple *s, irange &r1, irange &r2); bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector); -// Return the range_operator pointer for this statement. This routine -// can also be used to gate whether a routine is range-ops enabled. - -static inline range_operator * -gimple_range_handler (const gimple *s) -{ - if (const gassign *ass = dyn_cast (s)) - return range_op_handler (gimple_assign_rhs_code (ass), - TREE_TYPE (gimple_assign_lhs (ass))); - if (const gcond *cond = dyn_cast (s)) - return range_op_handler (gimple_cond_code (cond), - TREE_TYPE (gimple_cond_lhs (cond))); - return NULL; -} - // Return the type of range which statement S calculates. If the type is // unsupported or no type can be determined, return NULL_TREE. diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 3e15eb5192d..0e0cf2128e7 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -44,9 +44,9 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range) // Unary operations require the type of the first operand in the // second range position. tree type = TREE_TYPE (gimple_range_operand1 (stmt)); - int_range<2> type_range (type); - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - type_range); + tmp_range type_range (type); + type_range.set_varying (type); + return range_op_handler (stmt).op1_range (r, type, lhs_range, type_range); } // Calculate what we can determine of the range of this statement's @@ -72,12 +72,12 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, // This is sometimes invoked on single operand stmts. if (gimple_num_ops (stmt) < 3) return false; - int_range<2> trange (TREE_TYPE (gimple_range_operand2 (stmt))); - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - trange); + tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt)); + tmp_range trange (op2_type); + trange.set_varying (op2_type); + return range_op_handler (stmt).op1_range (r, type, lhs_range, trange); } - return gimple_range_handler (stmt)->op1_range (r, type, lhs_range, - op2_range); + return range_op_handler (stmt).op1_range (r, type, lhs_range, op2_range); } // Calculate what we can determine of the range of this statement's @@ -97,12 +97,13 @@ gimple_range_calc_op2 (irange &r, const gimple *stmt, // If op1 is undefined, solve as if it is varying. if (op1_range.undefined_p ()) { - int_range<2> trange (TREE_TYPE (gimple_range_operand1 (stmt))); - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range, - trange); + tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt)); + tmp_range trange (op1_type); + trange.set_varying (op1_type); + return range_op_handler (stmt).op2_range (r, type, lhs_range, trange); } - return gimple_range_handler (stmt)->op2_range (r, type, lhs_range, - op1_range); + return range_op_handler (stmt).op2_range (r, type, lhs_range, + op1_range); } // Return TRUE if GS is a logical && or || expression. @@ -346,7 +347,7 @@ range_def_chain::get_def_chain (tree name) } gimple *stmt = SSA_NAME_DEF_STMT (name); - if (gimple_range_handler (stmt)) + if (range_op_handler (stmt)) { ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt)); @@ -707,7 +708,7 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt, if (is_a (stmt)) return compute_operand_range_switch (r, as_a (stmt), lhs, name, src); - if (!gimple_range_handler (stmt)) + if (!range_op_handler (stmt)) return false; tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); @@ -1328,7 +1329,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, tree type = TREE_TYPE (gimple_assign_rhs1 (cond_def)); if (!range_compatible_p (type, TREE_TYPE (gimple_assign_rhs2 (cond_def)))) return false; - range_operator *hand = range_op_handler (gimple_assign_rhs_code (cond_def), type); + range_op_handler hand (gimple_assign_rhs_code (cond_def), type); if (!hand) return false; @@ -1351,18 +1352,18 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, // the op1 or op2 routines based on its location. if (c1) { - if (!hand->op1_range (cond_false, type, m_bool_zero, cr)) + if (!hand.op1_range (cond_false, type, m_bool_zero, cr)) return false; - if (!hand->op1_range (cond_true, type, m_bool_one, cr)) + if (!hand.op1_range (cond_true, type, m_bool_one, cr)) return false; cond_false.intersect (cl); cond_true.intersect (cl); } else { - if (!hand->op2_range (cond_false, type, m_bool_zero, cl)) + if (!hand.op2_range (cond_false, type, m_bool_zero, cl)) return false; - if (!hand->op2_range (cond_true, type, m_bool_one, cl)) + if (!hand.op2_range (cond_true, type, m_bool_one, cl)) return false; cond_false.intersect (cr); cond_true.intersect (cr); diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index f5e9e77bc71..32d57c9e3db 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -339,7 +339,7 @@ gimple_ranger::prefill_name (irange &r, tree name) if (!gimple_range_ssa_p (name)) return; gimple *stmt = SSA_NAME_DEF_STMT (name); - if (!gimple_range_handler (stmt) && !is_a (stmt)) + if (!range_op_handler (stmt) && !is_a (stmt)) return; bool current; @@ -363,7 +363,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) gcc_checking_assert (stmt && gimple_bb (stmt)); // Only pre-process range-ops and phis. - if (!gimple_range_handler (stmt) && !is_a (stmt)) + if (!range_op_handler (stmt) && !is_a (stmt)) return; // Mark where on the stack we are starting. @@ -419,7 +419,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) } else { - gcc_checking_assert (gimple_range_handler (stmt)); + gcc_checking_assert (range_op_handler (stmt)); tree op = gimple_range_operand2 (stmt); if (op) prefill_name (r, op); diff --git a/gcc/range-op.cc b/gcc/range-op.cc index c88da8caa6c..6f6d2da573a 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -420,7 +420,7 @@ create_possibly_reversed_range (irange &r, tree type, // return the equivalent range for TYPE in R; if FALSE/TRUE, do nothing. bool_range_state -get_bool_state (irange &r, const irange &lhs, tree val_type) +get_bool_state (vrange &r, const vrange &lhs, tree val_type) { // If there is no result, then this is unexecutable. if (lhs.undefined_p ()) @@ -446,6 +446,9 @@ get_bool_state (irange &r, const irange &lhs, tree val_type) class operator_equal : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -562,6 +565,9 @@ operator_equal::op2_range (irange &r, tree type, class operator_not_equal : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -738,6 +744,9 @@ build_ge (irange &r, tree type, const wide_int &val) class operator_lt : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -846,6 +855,9 @@ operator_lt::op2_range (irange &r, tree type, class operator_le : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -954,6 +966,9 @@ operator_le::op2_range (irange &r, tree type, class operator_gt : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -1061,6 +1076,9 @@ operator_gt::op2_range (irange &r, tree type, class operator_ge : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -1169,6 +1187,10 @@ operator_ge::op2_range (irange &r, tree type, class operator_plus : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; + using range_operator::lhs_op1_relation; + using range_operator::lhs_op2_relation; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1286,7 +1308,7 @@ operator_plus::op1_range (irange &r, tree type, const irange &op2, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op2); } bool @@ -1295,12 +1317,15 @@ operator_plus::op2_range (irange &r, tree type, const irange &op1, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, lhs, op1); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, lhs, op1); } class operator_minus : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1445,7 +1470,7 @@ operator_minus::op1_range (irange &r, tree type, const irange &op2, relation_kind rel ATTRIBUTE_UNUSED) const { - return range_op_handler (PLUS_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (PLUS_EXPR, type).fold_range (r, type, lhs, op2); } bool @@ -1597,6 +1622,8 @@ cross_product_operator::wi_cross_product (irange &r, tree type, class operator_mult : public cross_product_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -1629,8 +1656,8 @@ operator_mult::op1_range (irange &r, tree type, return false; if (op2.singleton_p (&offset) && !integer_zerop (offset)) - return range_op_handler (TRUNC_DIV_EXPR, type)->fold_range (r, type, - lhs, op2); + return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type, + lhs, op2); return false; } @@ -1857,6 +1884,7 @@ operator_div op_ceil_div (CEIL_DIV_EXPR); class operator_exact_divide : public operator_div { + using range_operator::op1_range; public: operator_exact_divide () : operator_div (TRUNC_DIV_EXPR) { } virtual bool op1_range (irange &r, tree type, @@ -1881,13 +1909,15 @@ operator_exact_divide::op1_range (irange &r, tree type, // 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)) - return range_op_handler (MULT_EXPR, type)->fold_range (r, type, lhs, op2); + return range_op_handler (MULT_EXPR, type).fold_range (r, type, lhs, op2); return false; } class operator_lshift : public cross_product_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -1909,6 +1939,9 @@ public: class operator_rshift : public cross_product_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::lhs_op1_relation; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -2248,6 +2281,8 @@ operator_rshift::wi_fold (irange &r, tree type, class operator_cast: public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -2417,10 +2452,9 @@ operator_cast::op1_range (irange &r, tree type, // Add this to the unsigned LHS range(s). int_range_max lim_range (type, lim, lim); int_range_max lhs_neg; - range_op_handler (PLUS_EXPR, type)->fold_range (lhs_neg, - type, - converted_lhs, - lim_range); + range_op_handler (PLUS_EXPR, type).fold_range (lhs_neg, type, + converted_lhs, + lim_range); // lhs_neg now has all the negative versions of the LHS. // Now union in all the values from SIGNED MIN (0x80000) to // lim-1 in order to fill in all the ranges with the upper @@ -2469,6 +2503,9 @@ operator_cast::op1_range (irange &r, tree type, class operator_logical_and : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -2542,6 +2579,9 @@ operator_logical_and::op2_range (irange &r, tree type, class operator_bitwise_and : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -2988,6 +3028,9 @@ operator_bitwise_and::op2_range (irange &r, tree type, class operator_logical_or : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3051,6 +3094,8 @@ operator_logical_or::op2_range (irange &r, tree type, class operator_bitwise_or : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -3155,6 +3200,8 @@ operator_bitwise_or::op2_range (irange &r, tree type, class operator_bitwise_xor : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3296,6 +3343,8 @@ operator_bitwise_xor::op2_range (irange &r, tree type, class operator_trunc_mod : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3432,6 +3481,8 @@ operator_trunc_mod::op2_range (irange &r, tree type, class operator_logical_not : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3487,6 +3538,8 @@ operator_logical_not::op1_range (irange &r, class operator_bitwise_not : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &lh, @@ -3513,8 +3566,7 @@ operator_bitwise_not::fold_range (irange &r, tree type, // ~X is simply -1 - X. int_range<1> minusone (type, wi::minus_one (TYPE_PRECISION (type)), wi::minus_one (TYPE_PRECISION (type))); - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, minusone, - lh); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, minusone, lh); } bool @@ -3533,6 +3585,7 @@ operator_bitwise_not::op1_range (irange &r, tree type, class operator_cst : public range_operator { + using range_operator::fold_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3553,6 +3606,9 @@ operator_cst::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, class operator_identity : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::lhs_op1_relation; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3605,6 +3661,7 @@ operator_identity::op1_range (irange &r, tree type ATTRIBUTE_UNUSED, class operator_unknown : public range_operator { + using range_operator::fold_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3625,6 +3682,7 @@ operator_unknown::fold_range (irange &r, tree type, class operator_abs : public range_operator { + using range_operator::op1_range; public: virtual void wi_fold (irange &r, tree type, const wide_int &lh_lb, @@ -3790,6 +3848,8 @@ operator_absu::wi_fold (irange &r, tree type, class operator_negate : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3810,9 +3870,8 @@ operator_negate::fold_range (irange &r, tree type, if (empty_range_varying (r, type, lh, rh)) return true; // -X is simply 0 - X. - return range_op_handler (MINUS_EXPR, type)->fold_range (r, type, - range_zero (type), - lh); + return range_op_handler (MINUS_EXPR, type).fold_range (r, type, + range_zero (type), lh); } bool @@ -3828,6 +3887,8 @@ operator_negate::op1_range (irange &r, tree type, class operator_addr_expr : public range_operator { + using range_operator::fold_range; + using range_operator::op1_range; public: virtual bool fold_range (irange &r, tree type, const irange &op1, @@ -3978,6 +4039,8 @@ pointer_and_operator::wi_fold (irange &r, tree type, class pointer_or_operator : public range_operator { + using range_operator::op1_range; + using range_operator::op2_range; public: virtual bool op1_range (irange &r, tree type, const irange &lhs, @@ -4139,8 +4202,8 @@ pointer_table::pointer_table () // The tables are hidden and accessed via a simple extern function. -range_operator * -range_op_handler (enum tree_code code, tree type) +static inline range_operator * +get_handler (enum tree_code code, tree type) { // First check if there is a pointer specialization. if (POINTER_TYPE_P (type)) @@ -4150,16 +4213,120 @@ range_op_handler (enum tree_code code, tree type) return NULL; } +range_op_handler::range_op_handler (tree_code code, tree type) +{ + m_op = get_handler (code, type); +} + +range_op_handler::range_op_handler (const gimple *s) +{ + if (const gassign *ass = dyn_cast (s)) + { + enum tree_code code = gimple_assign_rhs_code (ass); + // The LHS of a comparison is always an int, so we must look at + // the operands. + if (TREE_CODE_CLASS (code) == tcc_comparison) + m_op = get_handler (code, TREE_TYPE (gimple_assign_rhs1 (ass))); + else + m_op = get_handler (code, TREE_TYPE (gimple_assign_lhs (ass))); + } + else if (const gcond *cond = dyn_cast (s)) + m_op = get_handler (gimple_cond_code (cond), + TREE_TYPE (gimple_cond_lhs (cond))); + else + m_op = NULL; +} + +bool +range_op_handler::fold_range (vrange &r, tree type, + const vrange &lh, + const vrange &rh, + relation_kind rel) const +{ + if (is_a (lh)) + return m_op->fold_range (as_a (r), type, + as_a (lh), + as_a (rh), rel); + gcc_unreachable (); + return false; +} + +bool +range_op_handler::op1_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (r)) + return m_op->op1_range (as_a (r), type, + as_a (lhs), + as_a (op2), rel); + gcc_unreachable (); + return false; +} + +bool +range_op_handler::op2_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op1, + relation_kind rel) const +{ + if (is_a (r)) + return m_op->op2_range (as_a (r), type, + as_a (lhs), + as_a (op1), rel); + gcc_unreachable (); + return false; +} + +relation_kind +range_op_handler::lhs_op1_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (op1)) + return m_op->lhs_op1_relation (as_a (lhs), + as_a (op1), as_a (op2), rel); + gcc_unreachable (); + return VREL_VARYING; +} + +relation_kind +range_op_handler::lhs_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind rel) const +{ + if (is_a (op1)) + return m_op->lhs_op2_relation (as_a (lhs), + as_a (op1), as_a (op2), rel); + gcc_unreachable (); + return VREL_VARYING; +} + +relation_kind +range_op_handler::op1_op2_relation (const vrange &lhs) const +{ + return m_op->op1_op2_relation (as_a (lhs)); +} + // Cast the range in R to TYPE. -void -range_cast (irange &r, tree type) +bool +range_cast (vrange &r, tree type) { - int_range_max tmp = r; - range_operator *op = range_op_handler (CONVERT_EXPR, type); + tmp_range tmp (r); + tmp_range varying (type); + varying.set_varying (type); + range_op_handler op (CONVERT_EXPR, type); // Call op_convert, if it fails, the result is varying. - if (!op->fold_range (r, type, tmp, int_range<1> (type))) - r.set_varying (type); + if (!op || !op.fold_range (r, type, tmp, varying)) + { + r.set_varying (type); + return false; + } + return true; } #if CHECKING_P diff --git a/gcc/range-op.h b/gcc/range-op.h index 5fdda326d4b..d0f50689897 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -108,8 +108,39 @@ protected: const wide_int &rh_ub) const; }; -extern range_operator *range_op_handler (enum tree_code code, tree type); -extern void range_cast (irange &, tree type); +class range_op_handler +{ +public: + range_op_handler (enum tree_code code, tree type); + range_op_handler (const gimple *s); + operator bool () const { return m_op; } + + bool fold_range (vrange &r, tree type, + const vrange &lh, + const vrange &rh, + relation_kind rel = VREL_VARYING) const; + bool op1_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op2, + relation_kind rel = VREL_VARYING) const; + bool op2_range (vrange &r, tree type, + const vrange &lhs, + const vrange &op1, + relation_kind rel = VREL_VARYING) const; + relation_kind lhs_op1_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind = VREL_VARYING) const; + relation_kind lhs_op2_relation (const vrange &lhs, + const vrange &op1, + const vrange &op2, + relation_kind = VREL_VARYING) const; + relation_kind op1_op2_relation (const vrange &lhs) const; +private: + range_operator *m_op; +}; + +extern bool range_cast (vrange &, tree type); extern void wi_set_zero_nonzero_bits (tree type, const wide_int &, const wide_int &, wide_int &maybe_nonzero, @@ -124,7 +155,7 @@ relation_kind gt_op1_op2_relation (const irange &lhs); relation_kind ge_op1_op2_relation (const irange &lhs); enum bool_range_state { BRS_FALSE, BRS_TRUE, BRS_EMPTY, BRS_FULL }; -bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type); +bool_range_state get_bool_state (vrange &r, const vrange &lhs, tree val_type); // If the range of either op1 or op2 is undefined, set the result to // varying and return TRUE. If the caller truely cares about a result, @@ -132,8 +163,8 @@ bool_range_state get_bool_state (irange &r, const irange &lhs, tree val_type); // treated as a varying. inline bool -empty_range_varying (irange &r, tree type, - const irange &op1, const irange & op2) +empty_range_varying (vrange &r, tree type, + const vrange &op1, const vrange & op2) { if (op1.undefined_p () || op2.undefined_p ()) { @@ -150,8 +181,8 @@ empty_range_varying (irange &r, tree type, // return false. inline bool -relop_early_resolve (irange &r, tree type, const irange &op1, - const irange &op2, relation_kind rel, +relop_early_resolve (irange &r, tree type, const vrange &op1, + const vrange &op2, relation_kind rel, relation_kind my_rel) { // If known relation is a complete subset of this relation, always true. diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index 397792c3584..ae05fe74b95 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -593,8 +593,8 @@ compute_distributive_range (tree type, value_range &op0_range, gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)); if (result_range) { - range_operator *op = range_op_handler (code, type); - op->fold_range (*result_range, type, op0_range, op1_range); + range_op_handler op (code, type); + op.fold_range (*result_range, type, op0_range, op1_range); } /* The distributive property guarantees that if TYPE is no narrower @@ -639,10 +639,10 @@ compute_distributive_range (tree type, value_range &op0_range, range_cast (op0_range, ssizetype); range_cast (op1_range, ssizetype); value_range wide_range; - range_operator *op = range_op_handler (code, ssizetype); + range_op_handler op (code, ssizetype); bool saved_flag_wrapv = flag_wrapv; flag_wrapv = 1; - op->fold_range (wide_range, ssizetype, op0_range, op1_range); + op.fold_range (wide_range, ssizetype, op0_range, op1_range); flag_wrapv = saved_flag_wrapv; if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range)) return false; diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index 0784d658567..3c7b5af4737 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -924,20 +924,6 @@ extract_range_from_plus_minus_expr (value_range *vr, vr->set (min, max, kind); } -/* Return the range-ops handler for CODE and EXPR_TYPE. If no - suitable operator is found, return NULL and set VR to VARYING. */ - -static const range_operator * -get_range_op_handler (value_range *vr, - enum tree_code code, - tree expr_type) -{ - const range_operator *op = range_op_handler (code, expr_type); - if (!op) - vr->set_varying (expr_type); - return op; -} - /* If the types passed are supported, return TRUE, otherwise set VR to VARYING and return FALSE. */ @@ -1005,10 +991,12 @@ range_fold_binary_symbolics_p (value_range *vr, &vr0, &vr1); return true; } - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); + if (!op) + vr->set_varying (expr_type); vr0.normalize_symbolics (); vr1.normalize_symbolics (); - return op->fold_range (*vr, expr_type, vr0, vr1); + return op.fold_range (*vr, expr_type, vr0, vr1); } return false; } @@ -1040,10 +1028,12 @@ range_fold_unary_symbolics_p (value_range *vr, range_fold_binary_expr (vr, MINUS_EXPR, expr_type, &minusone, vr0); return true; } - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); + if (!op) + vr->set_varying (expr_type); value_range vr0_cst (*vr0); vr0_cst.normalize_symbolics (); - return op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); + return op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); } return false; } @@ -1060,9 +1050,12 @@ range_fold_binary_expr (value_range *vr, if (!supported_types_p (vr, expr_type) || !defined_ranges_p (vr, vr0_, vr1_)) return; - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); if (!op) - return; + { + vr->set_varying (expr_type); + return; + } if (range_fold_binary_symbolics_p (vr, code, expr_type, vr0_, vr1_)) return; @@ -1075,7 +1068,7 @@ range_fold_binary_expr (value_range *vr, vr1.set_varying (expr_type); vr0.normalize_addresses (); vr1.normalize_addresses (); - op->fold_range (*vr, expr_type, vr0, vr1); + op.fold_range (*vr, expr_type, vr0, vr1); } /* Perform a unary operation on a range. */ @@ -1089,16 +1082,19 @@ range_fold_unary_expr (value_range *vr, if (!supported_types_p (vr, expr_type, vr0_type) || !defined_ranges_p (vr, vr0)) return; - const range_operator *op = get_range_op_handler (vr, code, expr_type); + range_op_handler op (code, expr_type); if (!op) - return; + { + vr->set_varying (expr_type); + return; + } if (range_fold_unary_symbolics_p (vr, code, expr_type, vr0)) return; value_range vr0_cst (*vr0); vr0_cst.normalize_addresses (); - op->fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); + op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); } /* If the range of values taken by OP can be inferred after STMT executes, diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 26e3858103b..31e56eeae53 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -234,13 +234,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) } if (BINARY_CLASS_P (expr)) { - range_operator *op = range_op_handler (TREE_CODE (expr), type); + range_op_handler op (TREE_CODE (expr), type); if (op) { int_range_max r0, r1; range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); range_of_expr (r1, TREE_OPERAND (expr, 1), stmt); - op->fold_range (r, type, r0, r1); + op.fold_range (r, type, r0, r1); } else r.set_varying (type); @@ -248,13 +248,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) } if (UNARY_CLASS_P (expr)) { - range_operator *op = range_op_handler (TREE_CODE (expr), type); + range_op_handler op (TREE_CODE (expr), type); tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0)); if (op && irange::supports_type_p (op0_type)) { int_range_max r0; range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); - op->fold_range (r, type, r0, int_range<1> (type)); + op.fold_range (r, type, r0, int_range<1> (type)); } else r.set_varying (type); From patchwork Mon May 30 13:27:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54529 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 743F1382CF2C for ; Mon, 30 May 2022 13:30:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 743F1382CF2C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917438; bh=Gnpb4l3ZCIo2QIiJXepevsA7LW2YdVjlq1XzT6ggWwg=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=uO21Fo1A6Z68SCRL97qtvgyRVjeB3Bc4mrnnsndOhpZ7cSuu0W6DnG80t7ywUQp/e FgnGClj35v7/LPFdoHW2uVPK/DgfgxkpgAY2gP/lzY86c2fHg2231PJZ6qhRfxKENV 49T5pFvo9B9iRBwXLsOY3MKi4oEpeMQvEi5Xl2r4= 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.133.124]) by sourceware.org (Postfix) with ESMTPS id E333B3857822 for ; Mon, 30 May 2022 13:28:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E333B3857822 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-300-CFMEsdsDNQe3mtOvHbTP9Q-1; Mon, 30 May 2022 09:28:05 -0400 X-MC-Unique: CFMEsdsDNQe3mtOvHbTP9Q-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 25C43802814 for ; Mon, 30 May 2022 13:28:05 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A41B58288C; Mon, 30 May 2022 13:28:04 +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 24UDS3Ed1752186 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:03 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS3lT1752185; Mon, 30 May 2022 15:28:03 +0200 To: GCC patches Subject: [PATCH 4/5] Revamp irange_allocator to handle vranges. Date: Mon, 30 May 2022 15:27:50 +0200 Message-Id: <20220530132751.1752112-4-aldyh@redhat.com> In-Reply-To: <20220530132751.1752112-1-aldyh@redhat.com> References: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.5 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, 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch revamps the range allocator to handle generic vrange's. I've cleaned it up somehow to make it obvious the various things you can allocate with it. I've also moved away from overloads into distinct names when appropriate. The various entry points are now: // Allocate a range of TYPE. vrange *alloc_vrange (tree type); // Allocate a memory block of BYTES. void *alloc (unsigned bytes); // Return a clone of SRC. template T *clone (const T &src); It is now possible to allocate a clone of an irange, or any future range types: irange *i = allocator.clone (some_irange); frange *f = allocator.clone (some_frange); You can actually do so without the <>, but I find it clearer to specify the vrange type. So with it you can allocate a specific range type, or vrange, or a block of memory. I have rewritten the C style casts to C++ casts, since casts tend to be hints of problematic designs. With the C++ casts you can at least grep for them easier. Speak of which, the next patch, which converts ranger to vrange, will further clean this space by removing some unnecessary casts. Tested on x86-64 Linux and ppc64le Linux. * gimple-range-cache.cc (sbr_vector::sbr_vector): Adjust for vrange allocator. (sbr_vector::grow): Same. (sbr_vector::set_bb_range): Same. (sbr_sparse_bitmap::sbr_sparse_bitmap): Same. (sbr_sparse_bitmap::set_bb_range): Same. (block_range_cache::~block_range_cache): Same. (block_range_cache::set_bb_range): Same. (ssa_global_cache::ssa_global_cache): Same. (ssa_global_cache::~ssa_global_cache): Same. (ssa_global_cache::set_global_range): Same. * gimple-range-cache.h (block_range_cache): Same. (ssa_global_cache): Same. * gimple-range-edge.cc (gimple_outgoing_range::calc_switch_ranges): Same. * gimple-range-edge.h (gimple_outgoing_range): Same. * gimple-range-side-effect.cc (side_effect_manager::get_nonzero): Same. (side_effect_manager::add_range): Same. * gimple-range-side-effect.h (class side_effect_manager): Same. * value-range.h (class irange_allocator): Rename to... (class vrange_allocator): ...this. (irange_allocator::irange_allocator): New. (vrange_allocator::vrange_allocator): New. (irange_allocator::~irange_allocator): New. (vrange_allocator::~vrange_allocator): New. (irange_allocator::get_memory): Rename to... (vrange_allocator::alloc): ...this. (vrange_allocator::alloc_vrange): Rename from... (irange_allocator::allocate): ...this. (vrange_allocator::alloc_irange): New. --- gcc/gimple-range-cache.cc | 55 +++++++++++----------- gcc/gimple-range-cache.h | 4 +- gcc/gimple-range-edge.cc | 4 +- gcc/gimple-range-edge.h | 2 +- gcc/gimple-range-side-effect.cc | 13 ++++-- gcc/gimple-range-side-effect.h | 2 +- gcc/value-range.h | 82 +++++++++++++++++++++------------ 7 files changed, 96 insertions(+), 66 deletions(-) diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index c726393b380..9c541993fb6 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -75,7 +75,7 @@ ssa_block_ranges::dump (FILE *f) class sbr_vector : public ssa_block_ranges { public: - sbr_vector (tree t, irange_allocator *allocator); + sbr_vector (tree t, vrange_allocator *allocator); virtual bool set_bb_range (const_basic_block bb, const irange &r) override; virtual bool get_bb_range (irange &r, const_basic_block bb) override; @@ -86,20 +86,21 @@ protected: int_range<2> m_varying; int_range<2> m_undefined; tree m_type; - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; void grow (); }; // Initialize a block cache for an ssa_name of type T. -sbr_vector::sbr_vector (tree t, irange_allocator *allocator) +sbr_vector::sbr_vector (tree t, vrange_allocator *allocator) { gcc_checking_assert (TYPE_P (t)); m_type = t; - m_irange_allocator = allocator; + m_range_allocator = allocator; m_tab_size = last_basic_block_for_fn (cfun) + 1; - m_tab = (irange **)allocator->get_memory (m_tab_size * sizeof (irange *)); + m_tab = static_cast + (allocator->alloc (m_tab_size * sizeof (irange *))); memset (m_tab, 0, m_tab_size * sizeof (irange *)); // Create the cached type range. @@ -121,8 +122,8 @@ sbr_vector::grow () int new_size = inc + curr_bb_size; // Allocate new memory, copy the old vector and clear the new space. - irange **t = (irange **)m_irange_allocator->get_memory (new_size - * sizeof (irange *)); + irange **t = static_cast + (m_range_allocator->alloc (new_size * sizeof (irange *))); memcpy (t, m_tab, m_tab_size * sizeof (irange *)); memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *)); @@ -143,7 +144,7 @@ sbr_vector::set_bb_range (const_basic_block bb, const irange &r) else if (r.undefined_p ()) m = &m_undefined; else - m = m_irange_allocator->allocate (r); + m = m_range_allocator->clone (r); m_tab[bb->index] = m; return true; } @@ -191,14 +192,14 @@ sbr_vector::bb_range_p (const_basic_block bb) class sbr_sparse_bitmap : public ssa_block_ranges { public: - sbr_sparse_bitmap (tree t, irange_allocator *allocator, bitmap_obstack *bm); + sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm); virtual bool set_bb_range (const_basic_block bb, const irange &r) override; virtual bool get_bb_range (irange &r, const_basic_block bb) override; virtual bool bb_range_p (const_basic_block bb) override; private: void bitmap_set_quad (bitmap head, int quad, int quad_value); int bitmap_get_quad (const_bitmap head, int quad); - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; irange *m_range[SBR_NUM]; bitmap_head bitvec; tree m_type; @@ -206,23 +207,25 @@ private: // Initialize a block cache for an ssa_name of type T. -sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, irange_allocator *allocator, - bitmap_obstack *bm) +sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator, + bitmap_obstack *bm) { gcc_checking_assert (TYPE_P (t)); m_type = t; bitmap_initialize (&bitvec, bm); bitmap_tree_view (&bitvec); - m_irange_allocator = allocator; + m_range_allocator = allocator; // Pre-cache varying. - m_range[0] = m_irange_allocator->allocate (2); + m_range[0] = static_cast (m_range_allocator->alloc_vrange (t)); m_range[0]->set_varying (t); // Pre-cache zero and non-zero values for pointers. if (POINTER_TYPE_P (t)) { - m_range[1] = m_irange_allocator->allocate (2); + m_range[1] + = static_cast (m_range_allocator->alloc_vrange (t)); m_range[1]->set_nonzero (t); - m_range[2] = m_irange_allocator->allocate (2); + m_range[2] + = static_cast (m_range_allocator->alloc_vrange (t)); m_range[2]->set_zero (t); } else @@ -267,7 +270,7 @@ sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r) if (!m_range[x] || r == *(m_range[x])) { if (!m_range[x]) - m_range[x] = m_irange_allocator->allocate (r); + m_range[x] = m_range_allocator->clone (r); bitmap_set_quad (&bitvec, bb->index, x + 1); return true; } @@ -312,14 +315,14 @@ block_range_cache::block_range_cache () bitmap_obstack_initialize (&m_bitmaps); m_ssa_ranges.create (0); m_ssa_ranges.safe_grow_cleared (num_ssa_names); - m_irange_allocator = new irange_allocator; + m_range_allocator = new vrange_allocator; } // Remove any m_block_caches which have been created. block_range_cache::~block_range_cache () { - delete m_irange_allocator; + delete m_range_allocator; // Release the vector itself. m_ssa_ranges.release (); bitmap_obstack_release (&m_bitmaps); @@ -341,17 +344,17 @@ block_range_cache::set_bb_range (tree name, const_basic_block bb, // Use sparse representation if there are too many basic blocks. if (last_basic_block_for_fn (cfun) > param_evrp_sparse_threshold) { - void *r = m_irange_allocator->get_memory (sizeof (sbr_sparse_bitmap)); + void *r = m_range_allocator->alloc (sizeof (sbr_sparse_bitmap)); m_ssa_ranges[v] = new (r) sbr_sparse_bitmap (TREE_TYPE (name), - m_irange_allocator, + m_range_allocator, &m_bitmaps); } else { // Otherwise use the default vector implemntation. - void *r = m_irange_allocator->get_memory (sizeof (sbr_vector)); + void *r = m_range_allocator->alloc (sizeof (sbr_vector)); m_ssa_ranges[v] = new (r) sbr_vector (TREE_TYPE (name), - m_irange_allocator); + m_range_allocator); } } return m_ssa_ranges[v]->set_bb_range (bb, r); @@ -467,7 +470,7 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying) ssa_global_cache::ssa_global_cache () { m_tab.create (0); - m_irange_allocator = new irange_allocator; + m_range_allocator = new vrange_allocator; } // Deconstruct a global cache. @@ -475,7 +478,7 @@ ssa_global_cache::ssa_global_cache () ssa_global_cache::~ssa_global_cache () { m_tab.release (); - delete m_irange_allocator; + delete m_range_allocator; } // Retrieve the global range of NAME from cache memory if it exists. @@ -509,7 +512,7 @@ ssa_global_cache::set_global_range (tree name, const irange &r) if (m && m->fits_p (r)) *m = r; else - m_tab[v] = m_irange_allocator->allocate (r); + m_tab[v] = m_range_allocator->clone (r); return m != NULL; } diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index 555fe32513f..2472cd04f47 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -44,7 +44,7 @@ private: vec m_ssa_ranges; ssa_block_ranges &get_block_ranges (tree name); ssa_block_ranges *query_block_ranges (tree name); - irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; bitmap_obstack m_bitmaps; }; @@ -64,7 +64,7 @@ public: void dump (FILE *f = stderr); private: vec m_tab; - class irange_allocator *m_irange_allocator; + vrange_allocator *m_range_allocator; }; // This class provides all the caches a global ranger may need, and makes diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 5bbe23ae03d..5264e627c9a 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -166,13 +166,13 @@ gimple_outgoing_range::calc_switch_ranges (gswitch *sw) // If there was an existing range and it doesn't fit, we lose the memory. // It'll get reclaimed when the obstack is freed. This seems less // intrusive than allocating max ranges for each case. - slot = m_range_allocator.allocate (case_range); + slot = m_range_allocator.clone (case_range); } irange *&slot = m_edge_table->get_or_insert (default_edge, &existed); // This should be the first call into this switch. gcc_checking_assert (!existed); - irange *dr = m_range_allocator.allocate (default_range); + irange *dr = m_range_allocator.clone (default_range); slot = dr; } diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h index c131b3309cc..ce383b0aa6f 100644 --- a/gcc/gimple-range-edge.h +++ b/gcc/gimple-range-edge.h @@ -47,7 +47,7 @@ private: int m_max_edges; hash_map *m_edge_table; - irange_allocator m_range_allocator; + vrange_allocator m_range_allocator; }; // If there is a range control statement at the end of block BB, return it. diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc index 2c8c77dc569..8d2ac35bc8d 100644 --- a/gcc/gimple-range-side-effect.cc +++ b/gcc/gimple-range-side-effect.cc @@ -189,8 +189,10 @@ side_effect_manager::get_nonzero (tree name) m_nonzero.safe_grow_cleared (num_ssa_names + 20); if (!m_nonzero[v]) { - m_nonzero[v] = m_range_allocator.allocate (2); - m_nonzero[v]->set_nonzero (TREE_TYPE (name)); + tree type = TREE_TYPE (name); + m_nonzero[v] + = static_cast (m_range_allocator.alloc_vrange (type)); + m_nonzero[v]->set_nonzero (type); } return *(m_nonzero[v]); } @@ -259,14 +261,17 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r) if (ptr->range->fits_p (cur)) *(ptr->range) = cur; else - ptr->range = m_range_allocator.allocate (cur); + { + vrange &v = cur; + ptr->range = static_cast (m_range_allocator.clone (v)); + } return; } // Otherwise create a record. bitmap_set_bit (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name)); ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range)); - ptr->range = m_range_allocator.allocate (r); + ptr->range = m_range_allocator.clone (r); ptr->name = name; ptr->next = m_on_exit[bb->index].head; m_on_exit[bb->index].head = ptr; diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h index 848d94ba6d7..d76d6eb34f2 100644 --- a/gcc/gimple-range-side-effect.h +++ b/gcc/gimple-range-side-effect.h @@ -76,7 +76,7 @@ private: bitmap m_seen; bitmap_obstack m_bitmaps; struct obstack m_list_obstack; - irange_allocator m_range_allocator; + vrange_allocator m_range_allocator; }; #endif // GCC_GIMPLE_RANGE_SIDE_H diff --git a/gcc/value-range.h b/gcc/value-range.h index d51998145da..a5da53f595e 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -92,7 +92,7 @@ protected: class GTY((user)) irange : public vrange { - friend class irange_allocator; + friend class vrange_allocator; public: // In-place setters. virtual void set (tree, tree, value_range_kind = VR_RANGE) override; @@ -892,56 +892,63 @@ vrp_val_min (const_tree type) return NULL_TREE; } -// This is the irange storage class. It is used to allocate the -// minimum amount of storage needed for a given irange. Storage is -// automatically freed at destruction of the storage class. -// -// It is meant for long term storage, as opposed to int_range_max -// which is meant for intermediate temporary results on the stack. -// -// The newly allocated irange is initialized to the empty set -// (undefined_p() is true). +// This is the range storage class. It is used to allocate the +// minimum amount of storage needed for a given range. Storage is +// automatically freed at destruction of the class. -class irange_allocator +class vrange_allocator { public: - irange_allocator (); - ~irange_allocator (); - // Return a new range with NUM_PAIRS. - irange *allocate (unsigned num_pairs); - // Return a copy of SRC with the minimum amount of sub-ranges needed - // to represent it. - irange *allocate (const irange &src); - void *get_memory (unsigned num_bytes); + vrange_allocator (); + ~vrange_allocator (); + // Allocate a range of TYPE. + vrange *alloc_vrange (tree type); + // Allocate a memory block of BYTES. + void *alloc (unsigned bytes); + // Return a clone of SRC. + template T *clone (const T &src); private: - DISABLE_COPY_AND_ASSIGN (irange_allocator); + irange *alloc_irange (unsigned pairs); + DISABLE_COPY_AND_ASSIGN (vrange_allocator); struct obstack m_obstack; }; inline -irange_allocator::irange_allocator () +vrange_allocator::vrange_allocator () { obstack_init (&m_obstack); } inline -irange_allocator::~irange_allocator () +vrange_allocator::~vrange_allocator () { obstack_free (&m_obstack, NULL); } // Provide a hunk of memory from the obstack. + inline void * -irange_allocator::get_memory (unsigned num_bytes) +vrange_allocator::alloc (unsigned bytes) { - void *r = obstack_alloc (&m_obstack, num_bytes); - return r; + return obstack_alloc (&m_obstack, bytes); +} + +// Return a new range to hold ranges of TYPE. The newly allocated +// range is initialized to VR_UNDEFINED. + +inline vrange * +vrange_allocator::alloc_vrange (tree type) +{ + if (irange::supports_type_p (type)) + return alloc_irange (2); + + gcc_unreachable (); } // Return a new range with NUM_PAIRS. inline irange * -irange_allocator::allocate (unsigned num_pairs) +vrange_allocator::alloc_irange (unsigned num_pairs) { // Never allocate 0 pairs. // Don't allocate 1 either, or we get legacy value_range's. @@ -951,17 +958,32 @@ irange_allocator::allocate (unsigned num_pairs) size_t nbytes = sizeof (tree) * 2 * num_pairs; // Allocate the irange and required memory for the vector. - void *r = obstack_alloc (&m_obstack, sizeof (irange)); - tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes); + void *r = alloc (sizeof (irange)); + tree *mem = static_cast (alloc (nbytes)); return new (r) irange (mem, num_pairs); } +// Return a clone of an irange. + +template <> inline irange * -irange_allocator::allocate (const irange &src) +vrange_allocator::clone (const irange &src) { - irange *r = allocate (src.num_pairs ()); + irange *r = alloc_irange (src.num_pairs ()); *r = src; return r; } +// Return a clone of a vrange. + +template <> +inline vrange * +vrange_allocator::clone (const vrange &src) +{ + if (is_a (src)) + return clone (as_a (src)); + + gcc_unreachable (); +} + #endif // GCC_VALUE_RANGE_H From patchwork Mon May 30 13:27:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 54531 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2BDDC382F0B6 for ; Mon, 30 May 2022 13:32:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2BDDC382F0B6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653917574; bh=jyImD3Hgkdl9aI7jIaQJItJpyk79tOi2sLaihOQBGrM=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=KUocgqJEFraRmT14k9tD67e/puO6mkvaJ4jCEgXBKs7E6o1jcWaUSschqlm7rqgWR hKYl8cGIw5NwKpgp/QRqPVa//9G557SQ2/6Zfdp7bex36qSIQCSuG15hkb2SYokHRl YEvndhJ1CxXivPr29NCnvL1ygMWcXprOdwIomWk0= 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 8F2383850413 for ; Mon, 30 May 2022 13:28:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8F2383850413 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-477-7Zgq58-NO6CtfjdCwcHUQQ-1; Mon, 30 May 2022 09:28:05 -0400 X-MC-Unique: 7Zgq58-NO6CtfjdCwcHUQQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 909703803911 for ; Mon, 30 May 2022 13:28:05 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.194.246]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CEABD82890; Mon, 30 May 2022 13:28:04 +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 24UDS3n01752190 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 30 May 2022 15:28:03 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 24UDS3Uj1752189; Mon, 30 May 2022 15:28:03 +0200 To: GCC patches Subject: [PATCH 5/5] Convert ranger and clients to vrange. Date: Mon, 30 May 2022 15:27:51 +0200 Message-Id: <20220530132751.1752112-5-aldyh@redhat.com> In-Reply-To: <20220530132751.1752112-1-aldyh@redhat.com> References: <20220530132751.1752112-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Finally, the meat of the work. Convert ranger and associated clients to vrange. Everything's relatively mechanical given the previous patches. I did include a minor cleanup in the edge code. There's no need to check that the type of the switch is an integer as non-integer switches are invalid. I verified this with an appropriately coded assert. Tested on x86-64 & ppc64le Linux. gcc/ChangeLog: * gimple-range-cache.cc (ssa_block_ranges::dump): Convert to vrange. (sbr_vector::sbr_vector): Same. (sbr_vector::grow): Same. (sbr_vector::set_bb_range): Same. (sbr_vector::get_bb_range): Same. (sbr_sparse_bitmap::sbr_sparse_bitmap): Same. (sbr_sparse_bitmap::set_bb_range): Same. (sbr_sparse_bitmap::get_bb_range): Same. (block_range_cache::set_bb_range): Same. (block_range_cache::get_bb_range): Same. (block_range_cache::dump): Same. (ssa_global_cache::get_global_range): Same. (ssa_global_cache::set_global_range): Same. (ssa_global_cache::clear): Same. (ssa_global_cache::dump): Same. (ranger_cache::get_global_range): Same. (ranger_cache::set_global_range): Same. (ranger_cache::range_of_def): Same. (ranger_cache::entry_range): Same. (ranger_cache::exit_range): Same. (ranger_cache::edge_range): Same. (ranger_cache::range_of_expr): Same. (ranger_cache::range_on_edge): Same. (ranger_cache::block_range): Same. (ranger_cache::propagate_cache): Same. (ranger_cache::fill_block_cache): Same. (ranger_cache::range_from_dom): Same. * gimple-range-cache.h: Same. * gimple-range-edge.cc (gimple_outgoing_range::get_edge_range): Same. (gimple_outgoing_range::switch_edge_range): Same. (gimple_outgoing_range::edge_range_p): Same. * gimple-range-edge.h: Same. * gimple-range-fold.cc (fur_source::get_operand): Same. (fur_source::get_phi_operand): Same. (fur_edge::get_operand): Same. (fur_edge::get_phi_operand): Same. (fur_stmt::get_operand): Same. (fur_stmt::get_phi_operand): Same. (fur_list::fur_list): Same. (fur_list::get_operand): Same. (fur_list::get_phi_operand): Same. (fold_range): Same. (adjust_imagpart_expr): Same. (adjust_realpart_expr): Same. (gimple_range_adjustment): Same. (fold_using_range::fold_stmt): Same. (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_address): Same. (fold_using_range::range_of_phi): Same. (fold_using_range::range_of_call): Same. (fold_using_range::range_of_builtin_call): Same. (fold_using_range::range_of_builtin_int_call): Same. (fold_using_range::range_of_cond_expr): Same. (fur_source::register_outgoing_edges): Same. * gimple-range-fold.h (fold_range): Same. (gimple_range_type): Same. (gimple_range_ssa_p): Same. * gimple-range-gori.cc (gimple_range_calc_op1): Same. (gimple_range_calc_op2): Same. (gori_compute::compute_operand_range_switch): Same. (gori_compute::compute_operand_range): Same. (gori_compute::logical_combine): Same. (gori_compute::compute_logical_operands): Same. (gori_compute::compute_operand1_range): Same. (gori_compute::compute_operand2_range): Same. (gori_compute::compute_operand1_and_operand2_range): Same. (gori_compute::outgoing_edge_range_p): Same. (gori_compute::condexpr_adjust): Same. * gimple-range-gori.h (gimple_range_calc_op1): Same. (gimple_range_calc_op2): Same. * gimple-range-path.cc (path_range_query::get_cache): Same. (path_range_query::set_cache): Same. (path_range_query::range_on_path_entry): Same. (path_range_query::internal_range_of_expr): Same. (path_range_query::range_of_expr): Same. (path_range_query::ssa_range_in_phi): Same. (path_range_query::range_defined_in_block): Same. (path_range_query::compute_ranges_in_phis): Same. (path_range_query::compute_ranges_in_block): Same. (path_range_query::add_to_imports): Same. (path_range_query::range_of_stmt): Same. * gimple-range-path.h: Same. * gimple-range-side-effect.cc (stmt_side_effects::add_range): Same. (side_effect_manager::~side_effect_manager): Same. (side_effect_manager::get_nonzero): Same. (side_effect_manager::maybe_adjust_range): Same. (side_effect_manager::add_range): Same. * gimple-range-side-effect.h: Same. * gimple-range-tests.cc: Same. * gimple-range-trace.cc (range_tracer::trailer): Same. (debug_seed_ranger): Same. * gimple-range-trace.h: Same. * gimple-range.cc (gimple_ranger::range_of_expr): Same. (gimple_ranger::range_on_entry): Same. (gimple_ranger::range_on_exit): Same. (gimple_ranger::range_on_edge): Same. (gimple_ranger::fold_range_internal): Same. (gimple_ranger::range_of_stmt): Same. (gimple_ranger::prefill_name): Same. (gimple_ranger::prefill_stmt_dependencies): Same. (gimple_ranger::export_global_ranges): Same. (gimple_ranger::dump_bb): Same. * gimple-range.h: Same. * gimple-ssa-warn-access.cc (check_nul_terminated_array): Same. (memmodel_to_uhwi): Same. * tree-ssa-loop-niter.cc (refine_value_range_using_guard): Same. (determine_value_range): Same. (record_nonwrapping_iv): Same. (infer_loop_bounds_from_signedness): Same. (scev_var_range_cant_overflow): Same. * tree-ssa-threadedge.cc (hybrid_jt_simplifier::simplify): Same. * value-query.cc (range_query::range_on_edge): Same. (range_query::range_of_stmt): Same. (range_query::value_of_expr): Same. (range_query::value_on_edge): Same. (range_query::value_of_stmt): Same. (range_query::get_tree_range): Same. (update_global_range): Same. (get_range_global): Same. (gimple_range_global): Same. (global_range_query::range_of_expr): Same. (range_query::query_relation): Same. * value-query.h (gimple_range_global): Same. (update_global_range): Same. * vr-values.cc (vr_values::range_of_expr): Same. (bounds_of_var_in_loop): Same. (simplify_using_ranges::vrp_visit_cond_stmt): Same. * vr-values.h (class vr_values): Same. --- gcc/gimple-range-cache.cc | 136 ++++++++++++++++-------------- gcc/gimple-range-cache.h | 32 +++---- gcc/gimple-range-edge.cc | 12 +-- gcc/gimple-range-edge.h | 2 +- gcc/gimple-range-fold.cc | 144 +++++++++++++++++++------------- gcc/gimple-range-fold.h | 37 ++++---- gcc/gimple-range-gori.cc | 116 ++++++++++++++----------- gcc/gimple-range-gori.h | 42 +++++----- gcc/gimple-range-path.cc | 47 ++++++----- gcc/gimple-range-path.h | 16 ++-- gcc/gimple-range-side-effect.cc | 20 ++--- gcc/gimple-range-side-effect.h | 14 ++-- gcc/gimple-range-tests.cc | 3 +- gcc/gimple-range-trace.cc | 9 +- gcc/gimple-range-trace.h | 2 +- gcc/gimple-range.cc | 44 ++++++---- gcc/gimple-range.h | 14 ++-- gcc/gimple-ssa-warn-access.cc | 7 +- gcc/tree-ssa-loop-niter.cc | 16 ++-- gcc/tree-ssa-threadedge.cc | 4 +- gcc/value-query.cc | 73 ++++++++-------- gcc/value-query.h | 16 ++-- gcc/vr-values.cc | 29 ++++--- gcc/vr-values.h | 2 +- 24 files changed, 457 insertions(+), 380 deletions(-) diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index 9c541993fb6..4983e4d3aa7 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -44,11 +44,14 @@ along with GCC; see the file COPYING3. If not see class ssa_block_ranges { public: - virtual bool set_bb_range (const_basic_block bb, const irange &r) = 0; - virtual bool get_bb_range (irange &r, const_basic_block bb) = 0; + ssa_block_ranges (tree t) : m_type (t) { } + virtual bool set_bb_range (const_basic_block bb, const vrange &r) = 0; + virtual bool get_bb_range (vrange &r, const_basic_block bb) = 0; virtual bool bb_range_p (const_basic_block bb) = 0; void dump(FILE *f); +private: + tree m_type; }; // Print the list of known ranges for file F in a nice format. @@ -57,7 +60,7 @@ void ssa_block_ranges::dump (FILE *f) { basic_block bb; - int_range_max r; + tmp_range r (m_type); FOR_EACH_BB_FN (bb, cfun) if (get_bb_range (r, bb)) @@ -77,14 +80,14 @@ class sbr_vector : public ssa_block_ranges public: sbr_vector (tree t, vrange_allocator *allocator); - virtual bool set_bb_range (const_basic_block bb, const irange &r) override; - virtual bool get_bb_range (irange &r, const_basic_block bb) override; + virtual bool set_bb_range (const_basic_block bb, const vrange &r) override; + virtual bool get_bb_range (vrange &r, const_basic_block bb) override; virtual bool bb_range_p (const_basic_block bb) override; protected: - irange **m_tab; // Non growing vector. + vrange **m_tab; // Non growing vector. int m_tab_size; - int_range<2> m_varying; - int_range<2> m_undefined; + vrange *m_varying; + vrange *m_undefined; tree m_type; vrange_allocator *m_range_allocator; void grow (); @@ -94,18 +97,21 @@ protected: // Initialize a block cache for an ssa_name of type T. sbr_vector::sbr_vector (tree t, vrange_allocator *allocator) + : ssa_block_ranges (t) { gcc_checking_assert (TYPE_P (t)); m_type = t; m_range_allocator = allocator; m_tab_size = last_basic_block_for_fn (cfun) + 1; - m_tab = static_cast - (allocator->alloc (m_tab_size * sizeof (irange *))); - memset (m_tab, 0, m_tab_size * sizeof (irange *)); + m_tab = static_cast + (allocator->alloc (m_tab_size * sizeof (vrange *))); + memset (m_tab, 0, m_tab_size * sizeof (vrange *)); // Create the cached type range. - m_varying.set_varying (t); - m_undefined.set_undefined (); + m_varying = m_range_allocator->alloc_vrange (t); + m_undefined = m_range_allocator->alloc_vrange (t); + m_varying->set_varying (t); + m_undefined->set_undefined (); } // Grow the vector when the CFG has increased in size. @@ -122,10 +128,10 @@ sbr_vector::grow () int new_size = inc + curr_bb_size; // Allocate new memory, copy the old vector and clear the new space. - irange **t = static_cast - (m_range_allocator->alloc (new_size * sizeof (irange *))); - memcpy (t, m_tab, m_tab_size * sizeof (irange *)); - memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (irange *)); + vrange **t = static_cast + (m_range_allocator->alloc (new_size * sizeof (vrange *))); + memcpy (t, m_tab, m_tab_size * sizeof (vrange *)); + memset (t + m_tab_size, 0, (new_size - m_tab_size) * sizeof (vrange *)); m_tab = t; m_tab_size = new_size; @@ -134,15 +140,15 @@ sbr_vector::grow () // Set the range for block BB to be R. bool -sbr_vector::set_bb_range (const_basic_block bb, const irange &r) +sbr_vector::set_bb_range (const_basic_block bb, const vrange &r) { - irange *m; + vrange *m; if (bb->index >= m_tab_size) grow (); if (r.varying_p ()) - m = &m_varying; + m = m_varying; else if (r.undefined_p ()) - m = &m_undefined; + m = m_undefined; else m = m_range_allocator->clone (r); m_tab[bb->index] = m; @@ -153,11 +159,11 @@ sbr_vector::set_bb_range (const_basic_block bb, const irange &r) // there is no range. bool -sbr_vector::get_bb_range (irange &r, const_basic_block bb) +sbr_vector::get_bb_range (vrange &r, const_basic_block bb) { if (bb->index >= m_tab_size) return false; - irange *m = m_tab[bb->index]; + vrange *m = m_tab[bb->index]; if (m) { r = *m; @@ -193,14 +199,14 @@ class sbr_sparse_bitmap : public ssa_block_ranges { public: sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm); - virtual bool set_bb_range (const_basic_block bb, const irange &r) override; - virtual bool get_bb_range (irange &r, const_basic_block bb) override; + virtual bool set_bb_range (const_basic_block bb, const vrange &r) override; + virtual bool get_bb_range (vrange &r, const_basic_block bb) override; virtual bool bb_range_p (const_basic_block bb) override; private: void bitmap_set_quad (bitmap head, int quad, int quad_value); int bitmap_get_quad (const_bitmap head, int quad); vrange_allocator *m_range_allocator; - irange *m_range[SBR_NUM]; + vrange *m_range[SBR_NUM]; bitmap_head bitvec; tree m_type; }; @@ -209,6 +215,7 @@ private: sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_obstack *bm) + : ssa_block_ranges (t) { gcc_checking_assert (TYPE_P (t)); m_type = t; @@ -216,16 +223,14 @@ sbr_sparse_bitmap::sbr_sparse_bitmap (tree t, vrange_allocator *allocator, bitmap_tree_view (&bitvec); m_range_allocator = allocator; // Pre-cache varying. - m_range[0] = static_cast (m_range_allocator->alloc_vrange (t)); + m_range[0] = m_range_allocator->alloc_vrange (t); m_range[0]->set_varying (t); // Pre-cache zero and non-zero values for pointers. if (POINTER_TYPE_P (t)) { - m_range[1] - = static_cast (m_range_allocator->alloc_vrange (t)); + m_range[1] = m_range_allocator->alloc_vrange (t); m_range[1]->set_nonzero (t); - m_range[2] - = static_cast (m_range_allocator->alloc_vrange (t)); + m_range[2] = m_range_allocator->alloc_vrange (t); m_range[2]->set_zero (t); } else @@ -257,7 +262,7 @@ sbr_sparse_bitmap::bitmap_get_quad (const_bitmap head, int quad) // Set the range on entry to basic block BB to R. bool -sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r) +sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const vrange &r) { if (r.undefined_p ()) { @@ -283,7 +288,7 @@ sbr_sparse_bitmap::set_bb_range (const_basic_block bb, const irange &r) // there is no range. bool -sbr_sparse_bitmap::get_bb_range (irange &r, const_basic_block bb) +sbr_sparse_bitmap::get_bb_range (vrange &r, const_basic_block bb) { int value = bitmap_get_quad (&bitvec, bb->index); @@ -333,7 +338,7 @@ block_range_cache::~block_range_cache () bool block_range_cache::set_bb_range (tree name, const_basic_block bb, - const irange &r) + const vrange &r) { unsigned v = SSA_NAME_VERSION (name); if (v >= m_ssa_ranges.length ()) @@ -379,7 +384,7 @@ block_range_cache::query_block_ranges (tree name) // is one. bool -block_range_cache::get_bb_range (irange &r, tree name, const_basic_block bb) +block_range_cache::get_bb_range (vrange &r, tree name, const_basic_block bb) { ssa_block_ranges *ptr = query_block_ranges (name); if (ptr) @@ -423,12 +428,13 @@ void block_range_cache::dump (FILE *f, basic_block bb, bool print_varying) { unsigned x; - int_range_max r; bool summarize_varying = false; for (x = 1; x < m_ssa_ranges.length (); ++x) { if (!gimple_range_ssa_p (ssa_name (x))) continue; + + tmp_range r (TREE_TYPE (ssa_name (x))); if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb)) { if (!print_varying && r.varying_p ()) @@ -450,6 +456,8 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying) { if (!gimple_range_ssa_p (ssa_name (x))) continue; + + tmp_range r (TREE_TYPE (ssa_name (x))); if (m_ssa_ranges[x] && m_ssa_ranges[x]->get_bb_range (r, bb)) { if (r.varying_p ()) @@ -485,13 +493,13 @@ ssa_global_cache::~ssa_global_cache () // Return the value in R. bool -ssa_global_cache::get_global_range (irange &r, tree name) const +ssa_global_cache::get_global_range (vrange &r, tree name) const { unsigned v = SSA_NAME_VERSION (name); if (v >= m_tab.length ()) return false; - irange *stow = m_tab[v]; + vrange *stow = m_tab[v]; if (!stow) return false; r = *stow; @@ -502,13 +510,13 @@ ssa_global_cache::get_global_range (irange &r, tree name) const // Return TRUE if there was already a range set, otherwise false. bool -ssa_global_cache::set_global_range (tree name, const irange &r) +ssa_global_cache::set_global_range (tree name, const vrange &r) { unsigned v = SSA_NAME_VERSION (name); if (v >= m_tab.length ()) m_tab.safe_grow_cleared (num_ssa_names + 1); - irange *m = m_tab[v]; + vrange *m = m_tab[v]; if (m && m->fits_p (r)) *m = r; else @@ -533,7 +541,7 @@ void ssa_global_cache::clear () { if (m_tab.address ()) - memset (m_tab.address(), 0, m_tab.length () * sizeof (irange *)); + memset (m_tab.address(), 0, m_tab.length () * sizeof (vrange *)); } // Dump the contents of the global cache to F. @@ -545,8 +553,9 @@ ssa_global_cache::dump (FILE *f) bool print_header = true; for (unsigned x = 1; x < num_ssa_names; x++) { - int_range_max r; + tmp_range r; if (gimple_range_ssa_p (ssa_name (x)) && + r.init (TREE_TYPE (ssa_name (x))) && get_global_range (r, ssa_name (x)) && !r.varying_p ()) { if (print_header) @@ -809,11 +818,11 @@ ranger_cache::dump_bb (FILE *f, basic_block bb) // global range is not set, and return the legacy global value in R. bool -ranger_cache::get_global_range (irange &r, tree name) const +ranger_cache::get_global_range (vrange &r, tree name) const { if (m_globals.get_global_range (r, name)) return true; - r = gimple_range_global (name); + gimple_range_global (r, name); return false; } @@ -825,7 +834,7 @@ ranger_cache::get_global_range (irange &r, tree name) const // After this call, the global cache will have a value. bool -ranger_cache::get_global_range (irange &r, tree name, bool ¤t_p) +ranger_cache::get_global_range (vrange &r, tree name, bool ¤t_p) { bool had_global = get_global_range (r, name); @@ -847,7 +856,7 @@ ranger_cache::get_global_range (irange &r, tree name, bool ¤t_p) // Set the global range of NAME to R and give it a timestamp. void -ranger_cache::set_global_range (tree name, const irange &r) +ranger_cache::set_global_range (tree name, const vrange &r) { if (m_globals.set_global_range (name, r)) { @@ -882,7 +891,7 @@ ranger_cache::set_global_range (tree name, const irange &r) // get the best global value available. void -ranger_cache::range_of_def (irange &r, tree name, basic_block bb) +ranger_cache::range_of_def (vrange &r, tree name, basic_block bb) { gcc_checking_assert (gimple_range_ssa_p (name)); gcc_checking_assert (!bb || bb == gimple_bb (SSA_NAME_DEF_STMT (name))); @@ -895,7 +904,7 @@ ranger_cache::range_of_def (irange &r, tree name, basic_block bb) if (gimple_get_lhs (s) == name) fold_range (r, s, get_global_range_query ()); else - r = gimple_range_global (name); + gimple_range_global (r, name); } } @@ -903,12 +912,12 @@ ranger_cache::range_of_def (irange &r, tree name, basic_block bb) // lookups. void -ranger_cache::entry_range (irange &r, tree name, basic_block bb, +ranger_cache::entry_range (vrange &r, tree name, basic_block bb, enum rfd_mode mode) { if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) { - r = gimple_range_global (name); + gimple_range_global (r, name); return; } @@ -923,12 +932,12 @@ ranger_cache::entry_range (irange &r, tree name, basic_block bb, // lookups. void -ranger_cache::exit_range (irange &r, tree name, basic_block bb, +ranger_cache::exit_range (vrange &r, tree name, basic_block bb, enum rfd_mode mode) { if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) { - r = gimple_range_global (name); + gimple_range_global (r, name); return; } @@ -944,7 +953,7 @@ ranger_cache::exit_range (irange &r, tree name, basic_block bb, // Always returns a range and true. bool -ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode) +ranger_cache::edge_range (vrange &r, edge e, tree name, enum rfd_mode mode) { exit_range (r, name, e->src, mode); // If this is not an abnormal edge, check for side effects on exit. @@ -961,7 +970,7 @@ ranger_cache::edge_range (irange &r, edge e, tree name, enum rfd_mode mode) // Implement range_of_expr. bool -ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt) +ranger_cache::range_of_expr (vrange &r, tree name, gimple *stmt) { if (!gimple_range_ssa_p (name)) { @@ -985,7 +994,7 @@ ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt) // the current cache values. bool -ranger_cache::range_on_edge (irange &r, edge e, tree expr) +ranger_cache::range_on_edge (vrange &r, edge e, tree expr) { if (gimple_range_ssa_p (expr)) return edge_range (r, e, expr, RFD_NONE); @@ -997,7 +1006,7 @@ ranger_cache::range_on_edge (irange &r, edge e, tree expr) // def block for NAME. Otherwise, return false if the cache is empty. bool -ranger_cache::block_range (irange &r, basic_block bb, tree name, bool calc) +ranger_cache::block_range (vrange &r, basic_block bb, tree name, bool calc) { gcc_checking_assert (gimple_range_ssa_p (name)); @@ -1041,9 +1050,10 @@ ranger_cache::propagate_cache (tree name) basic_block bb; edge_iterator ei; edge e; - int_range_max new_range; - int_range_max current_range; - int_range_max e_range; + tree type = TREE_TYPE (name); + tmp_range new_range (type); + tmp_range current_range (type); + tmp_range e_range (type); // Process each block by seeing if its calculated range on entry is // the same as its cached value. If there is a difference, update @@ -1178,8 +1188,8 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) { edge_iterator ei; edge e; - int_range_max block_result; - int_range_max undefined; + tmp_range block_result (TREE_TYPE (name)); + tmp_range undefined (TREE_TYPE (name)); // At this point we shouldn't be looking at the def, entry or exit block. gcc_checking_assert (bb != def_bb && bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) && @@ -1232,7 +1242,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) FOR_EACH_EDGE (e, ei, node->preds) { basic_block pred = e->src; - int_range_max r; + tmp_range r (TREE_TYPE (name)); if (DEBUG_RANGE_CACHE) fprintf (dump_file, " %d->%d ",e->src->index, e->dest->index); @@ -1306,7 +1316,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) // dominator tree based on MODE. bool -ranger_cache::range_from_dom (irange &r, tree name, basic_block start_bb, +ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb, enum rfd_mode mode) { if (mode == RFD_NONE || !dom_info_available_p (CDI_DOMINATORS)) diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index 2472cd04f47..d17950c7154 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -34,8 +34,8 @@ public: block_range_cache (); ~block_range_cache (); - bool set_bb_range (tree name, const_basic_block bb, const irange &r); - bool get_bb_range (irange &r, tree name, const_basic_block bb); + bool set_bb_range (tree name, const_basic_block bb, const vrange &v); + bool get_bb_range (vrange &v, tree name, const_basic_block bb); bool bb_range_p (tree name, const_basic_block bb); void dump (FILE *f); @@ -57,13 +57,13 @@ class ssa_global_cache public: ssa_global_cache (); ~ssa_global_cache (); - bool get_global_range (irange &r, tree name) const; - bool set_global_range (tree name, const irange &r); + bool get_global_range (vrange &r, tree name) const; + bool set_global_range (tree name, const vrange &r); void clear_global_range (tree name); void clear (); void dump (FILE *f = stderr); private: - vec m_tab; + vec m_tab; vrange_allocator *m_range_allocator; }; @@ -77,13 +77,13 @@ public: ranger_cache (int not_executable_flag, bool use_imm_uses); ~ranger_cache (); - virtual bool range_of_expr (irange &r, tree name, gimple *stmt); - virtual bool range_on_edge (irange &r, edge e, tree expr); - bool block_range (irange &r, basic_block bb, tree name, bool calc = true); + virtual bool range_of_expr (vrange &r, tree name, gimple *stmt); + virtual bool range_on_edge (vrange &r, edge e, tree expr); + bool block_range (vrange &r, basic_block bb, tree name, bool calc = true); - bool get_global_range (irange &r, tree name) const; - bool get_global_range (irange &r, tree name, bool ¤t_p); - void set_global_range (tree name, const irange &r); + bool get_global_range (vrange &r, tree name) const; + bool get_global_range (vrange &r, tree name, bool ¤t_p); + void set_global_range (tree name, const vrange &r); void propagate_updated_value (tree name, basic_block bb); @@ -106,11 +106,11 @@ private: RFD_READ_ONLY, // Scan DOM tree, do not write to cache. RFD_FILL // Scan DOM tree, updating important nodes. }; - bool range_from_dom (irange &r, tree name, basic_block bb, enum rfd_mode); - void range_of_def (irange &r, tree name, basic_block bb = NULL); - void entry_range (irange &r, tree expr, basic_block bb, enum rfd_mode); - void exit_range (irange &r, tree expr, basic_block bb, enum rfd_mode); - bool edge_range (irange &r, edge e, tree name, enum rfd_mode); + bool range_from_dom (vrange &r, tree name, basic_block bb, enum rfd_mode); + void range_of_def (vrange &r, tree name, basic_block bb = NULL); + void entry_range (vrange &r, tree expr, basic_block bb, enum rfd_mode); + void exit_range (vrange &r, tree expr, basic_block bb, enum rfd_mode); + bool edge_range (vrange &r, edge e, tree name, enum rfd_mode); vec m_workback; class update_list *m_update; diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 5264e627c9a..6fe33408f7e 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -83,11 +83,8 @@ gimple_outgoing_range::~gimple_outgoing_range () // Use a cached value if it exists, or calculate it if not. bool -gimple_outgoing_range::get_edge_range (irange &r, gimple *s, edge e) +gimple_outgoing_range::switch_edge_range (irange &r, gswitch *sw, edge e) { - gcc_checking_assert (is_a (s)); - gswitch *sw = as_a (s); - // ADA currently has cases where the index is 64 bits and the case // arguments are 32 bit, causing a trap when we create a case_range. // Until this is resolved (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87798) @@ -204,12 +201,9 @@ gimple_outgoing_range::edge_range_p (irange &r, edge e) gcc_checking_assert (is_a (s)); gswitch *sw = as_a (s); - tree type = TREE_TYPE (gimple_switch_index (sw)); - - if (!irange::supports_type_p (type)) - return NULL; - if (get_edge_range (r, sw, e)) + // Switches can only be integers. + if (switch_edge_range (as_a (r), sw, e)) return s; return NULL; diff --git a/gcc/gimple-range-edge.h b/gcc/gimple-range-edge.h index ce383b0aa6f..a9c4af8715b 100644 --- a/gcc/gimple-range-edge.h +++ b/gcc/gimple-range-edge.h @@ -43,7 +43,7 @@ public: gimple *edge_range_p (irange &r, edge e); private: void calc_switch_ranges (gswitch *sw); - bool get_edge_range (irange &r, gimple *s, edge e); + bool switch_edge_range (irange &r, gswitch *sw, edge e); int m_max_edges; hash_map *m_edge_table; diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index c53d2863d5e..7fed5a99513 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -60,7 +60,7 @@ fur_source::fur_source (range_query *q) // Invoke range_of_expr on EXPR. bool -fur_source::get_operand (irange &r, tree expr) +fur_source::get_operand (vrange &r, tree expr) { return m_query->range_of_expr (r, expr); } @@ -69,7 +69,7 @@ fur_source::get_operand (irange &r, tree expr) // range_query to get the range on the edge. bool -fur_source::get_phi_operand (irange &r, tree expr, edge e) +fur_source::get_phi_operand (vrange &r, tree expr, edge e) { return m_query->range_on_edge (r, e, expr); } @@ -109,8 +109,8 @@ class fur_edge : public fur_source { public: fur_edge (edge e, range_query *q = NULL); - virtual bool get_operand (irange &r, tree expr) override; - virtual bool get_phi_operand (irange &r, tree expr, edge e) override; + virtual bool get_operand (vrange &r, tree expr) override; + virtual bool get_phi_operand (vrange &r, tree expr, edge e) override; private: edge m_edge; }; @@ -126,7 +126,7 @@ fur_edge::fur_edge (edge e, range_query *q) : fur_source (q) // Get the value of EXPR on edge m_edge. bool -fur_edge::get_operand (irange &r, tree expr) +fur_edge::get_operand (vrange &r, tree expr) { return m_query->range_on_edge (r, m_edge, expr); } @@ -135,7 +135,7 @@ fur_edge::get_operand (irange &r, tree expr) // range_query to get the range on the edge. bool -fur_edge::get_phi_operand (irange &r, tree expr, edge e) +fur_edge::get_phi_operand (vrange &r, tree expr, edge e) { // Edge to edge recalculations not supoprted yet, until we sort it out. gcc_checking_assert (e == m_edge); @@ -152,7 +152,7 @@ fur_stmt::fur_stmt (gimple *s, range_query *q) : fur_source (q) // Retreive range of EXPR as it occurs as a use on stmt M_STMT. bool -fur_stmt::get_operand (irange &r, tree expr) +fur_stmt::get_operand (vrange &r, tree expr) { return m_query->range_of_expr (r, expr, m_stmt); } @@ -161,7 +161,7 @@ fur_stmt::get_operand (irange &r, tree expr) // range_query to get the range on the edge. bool -fur_stmt::get_phi_operand (irange &r, tree expr, edge e) +fur_stmt::get_phi_operand (vrange &r, tree expr, edge e) { // Pick up the range of expr from edge E. fur_edge e_src (e, m_query); @@ -214,42 +214,42 @@ fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2) class fur_list : public fur_source { public: - fur_list (irange &r1); - fur_list (irange &r1, irange &r2); - fur_list (unsigned num, irange *list); - virtual bool get_operand (irange &r, tree expr) override; - virtual bool get_phi_operand (irange &r, tree expr, edge e) override; + fur_list (vrange &r1); + fur_list (vrange &r1, vrange &r2); + fur_list (unsigned num, vrange **list); + virtual bool get_operand (vrange &r, tree expr) override; + virtual bool get_phi_operand (vrange &r, tree expr, edge e) override; private: - int_range_max m_local[2]; - irange *m_list; + vrange *m_local[2]; + vrange **m_list; unsigned m_index; unsigned m_limit; }; // One range supplied for unary operations. -fur_list::fur_list (irange &r1) : fur_source (NULL) +fur_list::fur_list (vrange &r1) : fur_source (NULL) { m_list = m_local; m_index = 0; m_limit = 1; - m_local[0] = r1; + m_local[0] = &r1; } // Two ranges supplied for binary operations. -fur_list::fur_list (irange &r1, irange &r2) : fur_source (NULL) +fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL) { m_list = m_local; m_index = 0; m_limit = 2; - m_local[0] = r1; - m_local[1] = r2; + m_local[0] = &r1; + m_local[1] = &r2; } // Arbitrary number of ranges in a vector. -fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL) +fur_list::fur_list (unsigned num, vrange **list) : fur_source (NULL) { m_list = list; m_index = 0; @@ -259,18 +259,18 @@ fur_list::fur_list (unsigned num, irange *list) : fur_source (NULL) // Get the next operand from the vector, ensure types are compatible. bool -fur_list::get_operand (irange &r, tree expr) +fur_list::get_operand (vrange &r, tree expr) { if (m_index >= m_limit) return m_query->range_of_expr (r, expr); - r = m_list[m_index++]; + r = *m_list[m_index++]; gcc_checking_assert (range_compatible_p (TREE_TYPE (expr), r.type ())); return true; } // This will simply pick the next operand from the vector. bool -fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED) +fur_list::get_phi_operand (vrange &r, tree expr, edge e ATTRIBUTE_UNUSED) { return get_operand (r, expr); } @@ -278,7 +278,7 @@ fur_list::get_phi_operand (irange &r, tree expr, edge e ATTRIBUTE_UNUSED) // Fold stmt S into range R using R1 as the first operand. bool -fold_range (irange &r, gimple *s, irange &r1) +fold_range (vrange &r, gimple *s, vrange &r1) { fold_using_range f; fur_list src (r1); @@ -288,7 +288,7 @@ fold_range (irange &r, gimple *s, irange &r1) // Fold stmt S into range R using R1 and R2 as the first two operands. bool -fold_range (irange &r, gimple *s, irange &r1, irange &r2) +fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2) { fold_using_range f; fur_list src (r1, r2); @@ -299,7 +299,7 @@ fold_range (irange &r, gimple *s, irange &r1, irange &r2) // operands encountered. bool -fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector) +fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector) { fold_using_range f; fur_list src (num_elements, vector); @@ -309,7 +309,7 @@ fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector) // Fold stmt S into range R using range query Q. bool -fold_range (irange &r, gimple *s, range_query *q) +fold_range (vrange &r, gimple *s, range_query *q) { fold_using_range f; fur_stmt src (s, q); @@ -319,7 +319,7 @@ fold_range (irange &r, gimple *s, range_query *q) // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE. bool -fold_range (irange &r, gimple *s, edge on_edge, range_query *q) +fold_range (vrange &r, gimple *s, edge on_edge, range_query *q) { fold_using_range f; fur_edge src (on_edge, q); @@ -370,7 +370,7 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt) // Adjust the range for an IMAGPART_EXPR. static void -adjust_imagpart_expr (irange &res, const gimple *stmt) +adjust_imagpart_expr (vrange &res, const gimple *stmt) { tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); @@ -413,7 +413,7 @@ adjust_imagpart_expr (irange &res, const gimple *stmt) // Adjust the range for a REALPART_EXPR. static void -adjust_realpart_expr (irange &res, const gimple *stmt) +adjust_realpart_expr (vrange &res, const gimple *stmt) { tree name = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); @@ -442,12 +442,12 @@ adjust_realpart_expr (irange &res, const gimple *stmt) // this statement. static void -gimple_range_adjustment (irange &res, const gimple *stmt) +gimple_range_adjustment (vrange &res, const gimple *stmt) { switch (gimple_expr_code (stmt)) { case POINTER_DIFF_EXPR: - adjust_pointer_diff_expr (res, stmt); + adjust_pointer_diff_expr (as_a (res), stmt); return; case IMAGPART_EXPR: @@ -536,7 +536,7 @@ gimple_range_operand2 (const gimple *stmt) // be calculated, return false. bool -fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) +fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) { bool res = false; // If name and S are specified, make sure it is an LHS of S. @@ -549,7 +549,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) // Process addresses. if (gimple_code (s) == GIMPLE_ASSIGN && gimple_assign_rhs_code (s) == ADDR_EXPR) - return range_of_address (r, s, src); + return range_of_address (as_a (r), s, src); if (range_op_handler (s)) res = range_of_range_op (r, s, src); @@ -566,7 +566,7 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) if (!name || !gimple_range_ssa_p (name)) return false; // We don't understand the stmt, so return the global range. - r = gimple_range_global (name); + gimple_range_global (r, name); return true; } @@ -587,9 +587,8 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name) // If a range cannot be calculated, return false. bool -fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) +fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src) { - int_range_max range1, range2; tree type = gimple_range_type (s); if (!type) return false; @@ -599,13 +598,16 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) tree lhs = gimple_get_lhs (s); tree op1 = gimple_range_operand1 (s); tree op2 = gimple_range_operand2 (s); + tmp_range range1 (TREE_TYPE (op1)); + tmp_range range2; if (src.get_operand (range1, op1)) { if (!op2) { // Fold range, and register any dependency if available. - int_range<2> r2 (type); + tmp_range r2 (type); + r2.set_varying (type); handler.fold_range (r, type, range1, r2); if (lhs && gimple_range_ssa_p (op1)) { @@ -617,7 +619,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) src.register_relation (s, rel, lhs, op1); } } - else if (src.get_operand (range2, op2)) + else if (range2.init (TREE_TYPE (op2)) + && src.get_operand (range2, op2)) { relation_kind rel = src.query_relation (op1, op2); if (dump_file && (dump_flags & TDF_DETAILS) && rel != VREL_VARYING) @@ -630,7 +633,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) } // Fold range, and register any dependency if available. handler.fold_range (r, type, range1, range2, rel); - relation_fold_and_or (r, s, src); + if (irange::supports_type_p (type)) + relation_fold_and_or (as_a (r), s, src); if (lhs) { if (src.gori ()) @@ -663,7 +667,8 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src) e0 = NULL; if (!single_pred_p (e1->dest)) e1 = NULL; - src.register_outgoing_edges (as_a (s), r, e0, e1); + src.register_outgoing_edges (as_a (s), + as_a (r), e0, e1); } } else @@ -729,12 +734,12 @@ 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 (!range_includes_zero_p (&r)) + if (r.undefined_p () || !r.contains_p (build_zero_cst (r.type ()))) { /* We could here instead adjust r by off >> LOG2_BITS_PER_UNIT using POINTER_PLUS_EXPR if off_cst and just fall back to this. */ - r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); + r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } } @@ -746,22 +751,22 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src) && known_ne (off, 0) && (flag_delete_null_pointer_checks || known_gt (off, 0))) { - r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); + r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } - r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } // Handle "= &a". if (tree_single_nonzero_warnv_p (expr, &strict_overflow_p)) { - r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); + r.set_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } // Otherwise return varying. - r = int_range<2> (TREE_TYPE (gimple_assign_rhs1 (stmt))); + r.set_varying (TREE_TYPE (gimple_assign_rhs1 (stmt))); return true; } @@ -769,12 +774,12 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src) // If a range cannot be calculated, return false. bool -fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src) +fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src) { tree phi_def = gimple_phi_result (phi); tree type = gimple_range_type (phi); - int_range_max arg_range; - int_range_max equiv_range; + tmp_range arg_range (type); + tmp_range equiv_range (type); unsigned x; if (!type) @@ -881,7 +886,7 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src) // If a range cannot be calculated, return false. bool -fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src) +fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src) { tree type = gimple_range_type (call); if (!type) @@ -893,18 +898,18 @@ fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src) if (range_of_builtin_call (r, call, src)) ; else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p)) - r.set (build_int_cst (type, 0), TYPE_MAX_VALUE (type)); + r.set_nonnegative (type); else if (gimple_call_nonnull_result_p (call) || gimple_call_nonnull_arg (call)) - r = range_nonzero (type); + r.set_nonzero (type); else r.set_varying (type); // If there is an LHS, intersect that with what is known. if (lhs) { - value_range def; - def = gimple_range_global (lhs); + tmp_range def (TREE_TYPE (lhs)); + gimple_range_global (def, lhs); r.intersect (def); } return true; @@ -971,13 +976,30 @@ get_letter_range (tree type, irange &lowers, irange &uppers) // TRUE. Otherwise return FALSE. bool -fold_using_range::range_of_builtin_call (irange &r, gcall *call, +fold_using_range::range_of_builtin_call (vrange &r, gcall *call, fur_source &src) { combined_fn func = gimple_call_combined_fn (call); if (func == CFN_LAST) return false; + tree type = gimple_range_type (call); + gcc_checking_assert (type); + + if (irange::supports_type_p (type)) + return range_of_builtin_int_call (as_a (r), call, src); + + return false; +} + +bool +fold_using_range::range_of_builtin_int_call (irange &r, gcall *call, + fur_source &src) +{ + combined_fn func = gimple_call_combined_fn (call); + if (func == CFN_LAST) + return false; + tree type = gimple_range_type (call); tree arg; int mini, maxi, zerov = 0, prec; @@ -1256,9 +1278,8 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call, // If a range cannot be calculated, return false. bool -fold_using_range::range_of_cond_expr (irange &r, gassign *s, fur_source &src) +fold_using_range::range_of_cond_expr (vrange &r, gassign *s, fur_source &src) { - int_range_max cond_range, range1, range2; tree cond = gimple_assign_rhs1 (s); tree op1 = gimple_assign_rhs2 (s); tree op2 = gimple_assign_rhs3 (s); @@ -1267,6 +1288,9 @@ fold_using_range::range_of_cond_expr (irange &r, gassign *s, fur_source &src) if (!type) return false; + tmp_range range1 (TREE_TYPE (op1)); + tmp_range range2 (TREE_TYPE (op2)); + tmp_range cond_range (TREE_TYPE (cond)); gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR); gcc_checking_assert (range_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2))); src.get_operand (cond_range, cond); @@ -1438,7 +1462,6 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, void fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e1) { - int_range_max r; int_range<2> e0_range, e1_range; tree name; basic_block bb = gimple_bb (s); @@ -1505,6 +1528,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge continue; tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt)); + tmp_range r (TREE_TYPE (name)); if (ssa1 && ssa2) { if (e0 && gori ()->outgoing_edge_range_p (r, e0, name, *m_query) diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 4b5d4b6e0b8..df24280ee40 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_GIMPLE_RANGE_FOLD_H // This file is the main include point for gimple range folding. -// These routines will fold stmt S into the result irange R. +// These routines will fold stmt S into the result range R. // Any ssa_names on the stmt will be calculated using the range_query // parameter via a call to range_of_expr. // If no range_query is provided, current global range info will be used. @@ -31,15 +31,15 @@ along with GCC; see the file COPYING3. If not see // it appeared on that edge. // Fold stmt S into range R using range query Q. -bool fold_range (irange &r, gimple *s, range_query *q = NULL); +bool fold_range (vrange &r, gimple *s, range_query *q = NULL); // Recalculate stmt S into R using range query Q as if it were on edge ON_EDGE. -bool fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL); +bool fold_range (vrange &v, gimple *s, edge on_edge, range_query *q = NULL); // These routines the operands to be specified when manually folding. // Any excess queries will be drawn from the current range_query. -bool fold_range (irange &r, gimple *s, irange &r1); -bool fold_range (irange &r, gimple *s, irange &r1, irange &r2); -bool fold_range (irange &r, gimple *s, unsigned num_elements, irange *vector); +bool fold_range (vrange &r, gimple *s, vrange &r1); +bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2); +bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector); // Return the type of range which statement S calculates. If the type is // unsupported or no type can be determined, return NULL_TREE. @@ -66,7 +66,7 @@ gimple_range_type (const gimple *s) type = TREE_TYPE (type); } } - if (type && irange::supports_type_p (type)) + if (type && vrange::supports_type_p (type)) return type; return NULL_TREE; } @@ -79,7 +79,7 @@ gimple_range_ssa_p (tree exp) if (exp && TREE_CODE (exp) == SSA_NAME && !SSA_NAME_IS_VIRTUAL_OPERAND (exp) && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) && - irange::supports_type_p (TREE_TYPE (exp))) + vrange::supports_type_p (TREE_TYPE (exp))) return exp; return NULL_TREE; } @@ -108,8 +108,8 @@ public: fur_source (range_query *q = NULL); inline range_query *query () { return m_query; } inline class gori_compute *gori () { return m_gori; }; - virtual bool get_operand (irange &r, tree expr); - virtual bool get_phi_operand (irange &r, tree expr, edge e); + virtual bool get_operand (vrange &r, tree expr); + virtual bool get_phi_operand (vrange &r, tree expr, edge e); virtual relation_kind query_relation (tree op1, tree op2); virtual void register_relation (gimple *stmt, relation_kind k, tree op1, tree op2); @@ -128,8 +128,8 @@ class fur_stmt : public fur_source { public: fur_stmt (gimple *s, range_query *q = NULL); - virtual bool get_operand (irange &r, tree expr) override; - virtual bool get_phi_operand (irange &r, tree expr, edge e) override; + virtual bool get_operand (vrange &r, tree expr) override; + virtual bool get_phi_operand (vrange &r, tree expr, edge e) override; virtual relation_kind query_relation (tree op1, tree op2) override; private: gimple *m_stmt; @@ -161,17 +161,18 @@ extern tree gimple_range_operand2 (const gimple *s); class fold_using_range { public: - bool fold_stmt (irange &r, gimple *s, class fur_source &src, + bool fold_stmt (vrange &r, gimple *s, class fur_source &src, tree name = NULL_TREE); protected: - bool range_of_range_op (irange &r, gimple *s, fur_source &src); - bool range_of_call (irange &r, gcall *call, fur_source &src); - bool range_of_cond_expr (irange &r, gassign* cond, fur_source &src); + bool range_of_range_op (vrange &r, gimple *s, fur_source &src); + bool range_of_call (vrange &r, gcall *call, fur_source &src); + bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src); bool range_of_address (irange &r, gimple *s, fur_source &src); - bool range_of_builtin_call (irange &r, gcall *call, fur_source &src); + bool range_of_builtin_call (vrange &r, gcall *call, fur_source &src); + bool range_of_builtin_int_call (irange &r, gcall *call, fur_source &src); void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code, fur_source &src); - bool range_of_phi (irange &r, gphi *phi, fur_source &src); + bool range_of_phi (vrange &r, gphi *phi, fur_source &src); void range_of_ssa_name_with_loop_info (irange &, tree, class loop *, gphi *, fur_source &src); void relation_fold_and_or (irange& lhs_range, gimple *s, fur_source &src); diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 0e0cf2128e7..47d0dab8cb9 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see // LHS_RANGE. Return false if nothing can be determined. bool -gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range) +gimple_range_calc_op1 (vrange &r, const gimple *stmt, const vrange &lhs_range) { gcc_checking_assert (gimple_num_ops (stmt) < 3); // Give up on empty ranges. @@ -55,8 +55,8 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, const irange &lhs_range) // nothing can be determined. bool -gimple_range_calc_op1 (irange &r, const gimple *stmt, - const irange &lhs_range, const irange &op2_range) +gimple_range_calc_op1 (vrange &r, const gimple *stmt, + const vrange &lhs_range, const vrange &op2_range) { // Give up on empty ranges. if (lhs_range.undefined_p ()) @@ -86,8 +86,8 @@ gimple_range_calc_op1 (irange &r, const gimple *stmt, // nothing can be determined. bool -gimple_range_calc_op2 (irange &r, const gimple *stmt, - const irange &lhs_range, const irange &op1_range) +gimple_range_calc_op2 (vrange &r, const gimple *stmt, + const vrange &lhs_range, const vrange &op1_range) { // Give up on empty ranges. if (lhs_range.undefined_p ()) @@ -663,8 +663,8 @@ gori_compute::gori_compute (int not_executable_flag) // was not resolvable. bool -gori_compute::compute_operand_range_switch (irange &r, gswitch *s, - const irange &lhs, +gori_compute::compute_operand_range_switch (vrange &r, gswitch *s, + const vrange &lhs, tree name, fur_source &src) { tree op1 = gimple_switch_index (s); @@ -691,8 +691,8 @@ gori_compute::compute_operand_range_switch (irange &r, gswitch *s, // store the evaluation in R, otherwise return FALSE. bool -gori_compute::compute_operand_range (irange &r, gimple *stmt, - const irange &lhs, tree name, +gori_compute::compute_operand_range (vrange &r, gimple *stmt, + const vrange &lhs, tree name, fur_source &src) { // If the lhs doesn't tell us anything, neither will unwinding further. @@ -743,13 +743,18 @@ gori_compute::compute_operand_range (irange &r, gimple *stmt, print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } - int_range_max op1_trange, op1_frange; - int_range_max op2_trange, op2_frange; - compute_logical_operands (op1_trange, op1_frange, stmt, lhs, + tree type = TREE_TYPE (name); + tmp_range op1_trange (type), op1_frange (type); + tmp_range op2_trange (type), op2_frange (type); + compute_logical_operands (op1_trange, op1_frange, stmt, + as_a (lhs), name, src, op1, op1_in_chain); - compute_logical_operands (op2_trange, op2_frange, stmt, lhs, + compute_logical_operands (op2_trange, op2_frange, stmt, + as_a (lhs), name, src, op2, op2_in_chain); - res = logical_combine (r, gimple_expr_code (stmt), lhs, + res = logical_combine (r, + gimple_expr_code (stmt), + as_a (lhs), op1_trange, op1_frange, op2_trange, op2_frange); if (idx) tracer.trailer (idx, "compute_operand", res, name, r); @@ -789,10 +794,10 @@ range_is_either_true_or_false (const irange &r) // the LHS. bool -gori_compute::logical_combine (irange &r, enum tree_code code, +gori_compute::logical_combine (vrange &r, enum tree_code code, const irange &lhs, - const irange &op1_true, const irange &op1_false, - const irange &op2_true, const irange &op2_false) + const vrange &op1_true, const vrange &op1_false, + const vrange &op2_true, const vrange &op2_false) { if (op1_true.varying_p () && op1_false.varying_p () && op2_true.varying_p () && op2_false.varying_p ()) @@ -868,7 +873,7 @@ gori_compute::logical_combine (irange &r, enum tree_code code, if (!range_is_either_true_or_false (lhs)) { bool res; - int_range_max r1; + tmp_range r1 (r); if (logical_combine (r1, code, m_bool_zero, op1_true, op1_false, op2_true, op2_false) && logical_combine (r, code, m_bool_one, op1_true, op1_false, @@ -898,11 +903,11 @@ gori_compute::logical_combine (irange &r, enum tree_code code, else { // The FALSE side is the union of the other 3 cases. - int_range_max ff (op1_false); + tmp_range ff (op1_false); ff.intersect (op2_false); - int_range_max tf (op1_true); + tmp_range tf (op1_true); tf.intersect (op2_false); - int_range_max ft (op1_false); + tmp_range ft (op1_false); ft.intersect (op2_true); r = ff; r.union_ (tf); @@ -925,11 +930,11 @@ gori_compute::logical_combine (irange &r, enum tree_code code, { // The TRUE side of an OR operation will be the union of // the other three combinations. - int_range_max tt (op1_true); + tmp_range tt (op1_true); tt.intersect (op2_true); - int_range_max tf (op1_true); + tmp_range tf (op1_true); tf.intersect (op2_false); - int_range_max ft (op1_false); + tmp_range ft (op1_false); ft.intersect (op2_true); r = tt; r.union_ (tf); @@ -951,7 +956,7 @@ gori_compute::logical_combine (irange &r, enum tree_code code, // OP_IN_CHAIN is true. void -gori_compute::compute_logical_operands (irange &true_range, irange &false_range, +gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range, gimple *stmt, const irange &lhs, tree name, fur_source &src, @@ -1007,13 +1012,15 @@ gori_compute::compute_logical_operands (irange &true_range, irange &false_range, // R, or false if no range could be calculated. bool -gori_compute::compute_operand1_range (irange &r, gimple *stmt, - const irange &lhs, tree name, +gori_compute::compute_operand1_range (vrange &r, gimple *stmt, + const vrange &lhs, tree name, fur_source &src) { - int_range_max op1_range, op2_range; tree op1 = gimple_range_operand1 (stmt); tree op2 = gimple_range_operand2 (stmt); + tmp_range op1_range (TREE_TYPE (op1)); + tmp_range tmp (TREE_TYPE (op1)); + tmp_range op2_range; // Fetch the known range for op1 in this block. src.get_operand (op1_range, op1); @@ -1021,8 +1028,9 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, // Now range-op calcuate and put that result in r. if (op2) { + op2_range.init (TREE_TYPE (op2)); src.get_operand (op2_range, op2); - if (!gimple_range_calc_op1 (r, stmt, lhs, op2_range)) + if (!gimple_range_calc_op1 (tmp, stmt, lhs, op2_range)) return false; } else @@ -1030,7 +1038,7 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, // We pass op1_range to the unary operation. Nomally it's a // hidden range_for_type parameter, but sometimes having the // actual range can result in better information. - if (!gimple_range_calc_op1 (r, stmt, lhs, op1_range)) + if (!gimple_range_calc_op1 (tmp, stmt, lhs, op1_range)) return false; } @@ -1053,7 +1061,7 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, tracer.print (idx, "Computes "); print_generic_expr (dump_file, op1, TDF_SLIM); fprintf (dump_file, " = "); - r.dump (dump_file); + tmp.dump (dump_file); fprintf (dump_file, " intersect Known range : "); op1_range.dump (dump_file); fputc ('\n', dump_file); @@ -1061,13 +1069,14 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, // Intersect the calculated result with the known result and return if done. if (op1 == name) { - r.intersect (op1_range); + tmp.intersect (op1_range); + r = tmp; if (idx) tracer.trailer (idx, "produces ", true, name, r); return true; } // If the calculation continues, we're using op1_range as the new LHS. - op1_range.intersect (r); + op1_range.intersect (tmp); if (idx) tracer.trailer (idx, "produces ", true, op1, op1_range); @@ -1084,19 +1093,21 @@ gori_compute::compute_operand1_range (irange &r, gimple *stmt, // R, or false if no range could be calculated. bool -gori_compute::compute_operand2_range (irange &r, gimple *stmt, - const irange &lhs, tree name, +gori_compute::compute_operand2_range (vrange &r, gimple *stmt, + const vrange &lhs, tree name, fur_source &src) { - int_range_max op1_range, op2_range; tree op1 = gimple_range_operand1 (stmt); tree op2 = gimple_range_operand2 (stmt); + tmp_range op1_range (TREE_TYPE (op1)); + tmp_range op2_range (TREE_TYPE (op2)); + tmp_range tmp (TREE_TYPE (op2)); src.get_operand (op1_range, op1); src.get_operand (op2_range, op2); // Intersect with range for op2 based on lhs and op1. - if (!gimple_range_calc_op2 (r, stmt, lhs, op1_range)) + if (!gimple_range_calc_op2 (tmp, stmt, lhs, op1_range)) return false; unsigned idx; @@ -1118,7 +1129,7 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt, tracer.print (idx, "Computes "); print_generic_expr (dump_file, op2, TDF_SLIM); fprintf (dump_file, " = "); - r.dump (dump_file); + tmp.dump (dump_file); fprintf (dump_file, " intersect Known range : "); op2_range.dump (dump_file); fputc ('\n', dump_file); @@ -1126,13 +1137,14 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt, // Intersect the calculated result with the known result and return if done. if (op2 == name) { - r.intersect (op2_range); + tmp.intersect (op2_range); + r = tmp; if (idx) tracer.trailer (idx, " produces ", true, NULL_TREE, r); return true; } // If the calculation continues, we're using op2_range as the new LHS. - op2_range.intersect (r); + op2_range.intersect (tmp); if (idx) tracer.trailer (idx, " produces ", true, op2, op2_range); @@ -1149,13 +1161,13 @@ gori_compute::compute_operand2_range (irange &r, gimple *stmt, // R, or false if no range could be calculated. bool -gori_compute::compute_operand1_and_operand2_range (irange &r, +gori_compute::compute_operand1_and_operand2_range (vrange &r, gimple *stmt, - const irange &lhs, + const vrange &lhs, tree name, fur_source &src) { - int_range_max op_range; + tmp_range op_range (TREE_TYPE (name)); // Calculate a good a range for op2. Since op1 == op2, this will // have already included whatever the actual range of name is. @@ -1236,10 +1248,9 @@ gori_compute::has_edge_range_p (tree name, edge e) // control edge or NAME is not defined by this edge. bool -gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name, +gori_compute::outgoing_edge_range_p (vrange &r, edge e, tree name, range_query &q) { - int_range_max lhs; unsigned idx; if ((e->flags & m_not_executable_flag)) @@ -1252,6 +1263,7 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name, } gcc_checking_assert (gimple_range_ssa_p (name)); + int_range_max lhs; // Determine if there is an outgoing edge. gimple *stmt = outgoing.edge_range_p (lhs, e); if (!stmt) @@ -1312,10 +1324,9 @@ gori_compute::outgoing_edge_range_p (irange &r, edge e, tree name, // edge and OP2 on the false edge. bool -gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, +gori_compute::condexpr_adjust (vrange &r1, vrange &r2, gimple *, tree cond, tree op1, tree op2, fur_source &src) { - int_range_max tmp, cond_true, cond_false; tree ssa1 = gimple_range_ssa_p (op1); tree ssa2 = gimple_range_ssa_p (op2); if (!ssa1 && !ssa2) @@ -1341,15 +1352,19 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, return false; // Pick up the current values of each part of the condition. - int_range_max cl, cr; - src.get_operand (cl, gimple_assign_rhs1 (cond_def)); - src.get_operand (cr, gimple_assign_rhs2 (cond_def)); + tree rhs1 = gimple_assign_rhs1 (cond_def); + tree rhs2 = gimple_assign_rhs2 (cond_def); + tmp_range cl (TREE_TYPE (rhs1)); + tmp_range cr (TREE_TYPE (rhs2)); + src.get_operand (cl, rhs1); + src.get_operand (cr, rhs2); tree cond_name = c1 ? c1 : c2; gimple *def_stmt = SSA_NAME_DEF_STMT (cond_name); // Evaluate the value of COND_NAME on the true and false edges, using either // the op1 or op2 routines based on its location. + tmp_range cond_true (type), cond_false (type); if (c1) { if (!hand.op1_range (cond_false, type, m_bool_zero, cr)) @@ -1380,6 +1395,7 @@ gori_compute::condexpr_adjust (irange &r1, irange &r2, gimple *, tree cond, } // Now solve for SSA1 or SSA2 if they are in the dependency chain. + tmp_range tmp (type); if (ssa1 && in_chain_p (ssa1, cond_name)) { if (compute_operand_range (tmp, def_stmt, cond_true, ssa1, src)) diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h index 605884e2e53..f5f691fe424 100644 --- a/gcc/gimple-range-gori.h +++ b/gcc/gimple-range-gori.h @@ -121,7 +121,7 @@ private: // on *ANY* edge that has been seen. FALSE indicates that the global value // is applicable everywhere that has been processed. // -// outgoing_edge_range_p (irange &range, edge e, tree name) +// outgoing_edge_range_p (vrange &range, edge e, tree name) // Actually does the calculation of RANGE for name on E // This represents application of whatever static range effect edge E // may have on NAME, not any cumulative effect. @@ -157,8 +157,8 @@ class gori_compute : public gori_map { public: gori_compute (int not_executable_flag = 0); - bool outgoing_edge_range_p (irange &r, edge e, tree name, range_query &q); - bool condexpr_adjust (irange &r1, irange &r2, gimple *s, tree cond, tree op1, + bool outgoing_edge_range_p (vrange &r, edge e, tree name, range_query &q); + bool condexpr_adjust (vrange &r1, vrange &r2, gimple *s, tree cond, tree op1, tree op2, fur_source &src); bool has_edge_range_p (tree name, basic_block bb = NULL); bool has_edge_range_p (tree name, edge e); @@ -166,24 +166,24 @@ public: private: bool may_recompute_p (tree name, edge e); bool may_recompute_p (tree name, basic_block bb = NULL); - bool compute_operand_range (irange &r, gimple *stmt, const irange &lhs, + bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs, tree name, class fur_source &src); - bool compute_operand_range_switch (irange &r, gswitch *s, const irange &lhs, + bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs, tree name, fur_source &src); - bool compute_operand1_range (irange &r, gimple *stmt, const irange &lhs, + bool compute_operand1_range (vrange &r, gimple *stmt, const vrange &lhs, tree name, fur_source &src); - bool compute_operand2_range (irange &r, gimple *stmt, const irange &lhs, + bool compute_operand2_range (vrange &r, gimple *stmt, const vrange &lhs, tree name, fur_source &src); - bool compute_operand1_and_operand2_range (irange &r, gimple *stmt, - const irange &lhs, tree name, + bool compute_operand1_and_operand2_range (vrange &r, gimple *stmt, + const vrange &lhs, tree name, fur_source &src); - void compute_logical_operands (irange &true_range, irange &false_range, + void compute_logical_operands (vrange &true_range, vrange &false_range, gimple *stmt, const irange &lhs, tree name, fur_source &src, tree op, bool op_in_chain); - bool logical_combine (irange &r, enum tree_code code, const irange &lhs, - const irange &op1_true, const irange &op1_false, - const irange &op2_true, const irange &op2_false); + bool logical_combine (vrange &r, enum tree_code code, const irange &lhs, + const vrange &op1_true, const vrange &op1_false, + const vrange &op2_true, const vrange &op2_false); int_range<2> m_bool_zero; // Boolean false cached. int_range<2> m_bool_one; // Boolean true cached. @@ -193,14 +193,14 @@ private: }; // These routines provide a GIMPLE interface to the range-ops code. -extern bool gimple_range_calc_op1 (irange &r, const gimple *s, - const irange &lhs_range); -extern bool gimple_range_calc_op1 (irange &r, const gimple *s, - const irange &lhs_range, - const irange &op2_range); -extern bool gimple_range_calc_op2 (irange &r, const gimple *s, - const irange &lhs_range, - const irange &op1_range); +extern bool gimple_range_calc_op1 (vrange &r, const gimple *s, + const vrange &lhs_range); +extern bool gimple_range_calc_op1 (vrange &r, const gimple *s, + const vrange &lhs_range, + const vrange &op2_range); +extern bool gimple_range_calc_op2 (vrange &r, const gimple *s, + const vrange &lhs_range, + const vrange &op1_range); // For each name that is an import into BB's exports.. #define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name) \ diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index 66f433dd1d5..4819332f358 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -83,7 +83,7 @@ path_range_query::clear_cache (tree name) // If NAME has a cache entry, return it in R, and return TRUE. inline bool -path_range_query::get_cache (irange &r, tree name) +path_range_query::get_cache (vrange &r, tree name) { if (!gimple_range_ssa_p (name)) return get_global_range_query ()->range_of_expr (r, name); @@ -98,7 +98,7 @@ path_range_query::get_cache (irange &r, tree name) // Set the cache entry for NAME to R. void -path_range_query::set_cache (const irange &r, tree name) +path_range_query::set_cache (const vrange &r, tree name) { unsigned v = SSA_NAME_VERSION (name); bitmap_set_bit (m_has_cache_entry, v); @@ -149,7 +149,7 @@ path_range_query::defined_outside_path (tree name) // Return the range of NAME on entry to the path. void -path_range_query::range_on_path_entry (irange &r, tree name) +path_range_query::range_on_path_entry (vrange &r, tree name) { gcc_checking_assert (defined_outside_path (name)); basic_block entry = entry_bb (); @@ -168,7 +168,7 @@ path_range_query::range_on_path_entry (irange &r, tree name) // block. This can happen when we're querying a block with only an // outgoing edge (no statement but the fall through edge), but for // which we can determine a range on entry to the block. - int_range_max tmp; + tmp_range tmp (TREE_TYPE (name)); bool changed = false; r.set_undefined (); for (unsigned i = 0; i < EDGE_COUNT (entry->preds); ++i) @@ -190,9 +190,9 @@ path_range_query::range_on_path_entry (irange &r, tree name) // Return the range of NAME at the end of the path being analyzed. bool -path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt) +path_range_query::internal_range_of_expr (vrange &r, tree name, gimple *stmt) { - if (!irange::supports_type_p (TREE_TYPE (name))) + if (!vrange::supports_type_p (TREE_TYPE (name))) return false; if (get_cache (r, name)) @@ -209,18 +209,22 @@ path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt) && range_defined_in_block (r, name, gimple_bb (stmt))) { if (TREE_CODE (name) == SSA_NAME) - r.intersect (gimple_range_global (name)); + { + tmp_range glob (TREE_TYPE (name)); + gimple_range_global (glob, name); + r.intersect (glob); + } set_cache (r, name); return true; } - r = gimple_range_global (name); + gimple_range_global (r, name); return true; } bool -path_range_query::range_of_expr (irange &r, tree name, gimple *stmt) +path_range_query::range_of_expr (vrange &r, tree name, gimple *stmt) { if (internal_range_of_expr (r, name, stmt)) { @@ -269,7 +273,7 @@ path_range_query::ssa_defined_in_bb (tree name, basic_block bb) // calculating the PHI's range must not trigger additional lookups. void -path_range_query::ssa_range_in_phi (irange &r, gphi *phi) +path_range_query::ssa_range_in_phi (vrange &r, gphi *phi) { tree name = gimple_phi_result (phi); basic_block bb = gimple_bb (phi); @@ -283,7 +287,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi) // Try to fold the phi exclusively with global or cached values. // This will get things like PHI <5(99), 6(88)>. We do this by // calling range_of_expr with no context. - int_range_max arg_range; + tmp_range arg_range (TREE_TYPE (name)); r.set_undefined (); for (size_t i = 0; i < nargs; ++i) { @@ -312,7 +316,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi) { if (m_resolve) { - int_range_max tmp; + tmp_range tmp (TREE_TYPE (name)); // Using both the range on entry to the path, and the // range on this edge yields significantly better // results. @@ -335,7 +339,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi) // TRUE. Otherwise, return FALSE. bool -path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb) +path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb) { gimple *def_stmt = SSA_NAME_DEF_STMT (name); basic_block def_bb = gimple_bb (def_stmt); @@ -377,7 +381,6 @@ path_range_query::range_defined_in_block (irange &r, tree name, basic_block bb) void path_range_query::compute_ranges_in_phis (basic_block bb) { - int_range_max r; auto_bitmap phi_set; // PHIs must be resolved simultaneously on entry to the block @@ -390,7 +393,11 @@ path_range_query::compute_ranges_in_phis (basic_block bb) gphi *phi = iter.phi (); tree name = gimple_phi_result (phi); - if (import_p (name) && range_defined_in_block (r, name, bb)) + if (!import_p (name)) + continue; + + tmp_range r (TREE_TYPE (name)); + if (range_defined_in_block (r, name, bb)) { unsigned v = SSA_NAME_VERSION (name); set_cache (r, name); @@ -423,7 +430,6 @@ void path_range_query::compute_ranges_in_block (basic_block bb) { bitmap_iterator bi; - int_range_max r, cached_range; unsigned i; if (m_resolve && !at_entry ()) @@ -444,6 +450,7 @@ path_range_query::compute_ranges_in_block (basic_block bb) EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi) { tree name = ssa_name (i); + tmp_range r (TREE_TYPE (name)); if (gimple_code (SSA_NAME_DEF_STMT (name)) != GIMPLE_PHI && range_defined_in_block (r, name, bb)) @@ -480,8 +487,10 @@ path_range_query::compute_ranges_in_block (basic_block bb) if (bitmap_bit_p (exports, i)) { + tmp_range r (TREE_TYPE (name)); if (g.outgoing_edge_range_p (r, e, name, *this)) { + tmp_range cached_range (TREE_TYPE (name)); if (get_cache (cached_range, name)) r.intersect (cached_range); @@ -539,7 +548,7 @@ bool path_range_query::add_to_imports (tree name, bitmap imports) { if (TREE_CODE (name) == SSA_NAME - && irange::supports_type_p (TREE_TYPE (name))) + && vrange::supports_type_p (TREE_TYPE (name))) return bitmap_set_bit (imports, SSA_NAME_VERSION (name)); return false; } @@ -751,11 +760,11 @@ jt_fur_source::query_relation (tree op1, tree op2) // Return the range of STMT at the end of the path being analyzed. bool -path_range_query::range_of_stmt (irange &r, gimple *stmt, tree) +path_range_query::range_of_stmt (vrange &r, gimple *stmt, tree) { tree type = gimple_range_type (stmt); - if (!type || !irange::supports_type_p (type)) + if (!type || !vrange::supports_type_p (type)) return false; // If resolving unknowns, fold the statement making use of any diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h index 914983bb0aa..2c4624e4cef 100644 --- a/gcc/gimple-range-path.h +++ b/gcc/gimple-range-path.h @@ -38,29 +38,29 @@ public: const bitmap_head *imports = NULL); void compute_ranges (edge e); void compute_imports (bitmap imports, basic_block exit); - bool range_of_expr (irange &r, tree name, gimple * = NULL) override; - bool range_of_stmt (irange &r, gimple *, tree name = NULL) override; + bool range_of_expr (vrange &r, tree name, gimple * = NULL) override; + bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override; bool unreachable_path_p (); void dump (FILE *) override; void debug (); private: - bool internal_range_of_expr (irange &r, tree name, gimple *); + bool internal_range_of_expr (vrange &r, tree name, gimple *); bool defined_outside_path (tree name); - void range_on_path_entry (irange &r, tree name); + void range_on_path_entry (vrange &r, tree name); path_oracle *get_path_oracle () { return (path_oracle *)m_oracle; } // Cache manipulation. - void set_cache (const irange &r, tree name); - bool get_cache (irange &r, tree name); + void set_cache (const vrange &r, tree name); + bool get_cache (vrange &r, tree name); void clear_cache (tree name); // Methods to compute ranges for the given path. - bool range_defined_in_block (irange &, tree name, basic_block bb); + bool range_defined_in_block (vrange &, tree name, basic_block bb); void compute_ranges_in_block (basic_block bb); void compute_ranges_in_phis (basic_block bb); void adjust_for_non_null_uses (basic_block bb); - void ssa_range_in_phi (irange &r, gphi *phi); + void ssa_range_in_phi (vrange &r, gphi *phi); void compute_outgoing_relations (basic_block bb, basic_block next); void compute_phi_relations (basic_block bb, basic_block prev); void maybe_register_phi_relation (gphi *, edge e); diff --git a/gcc/gimple-range-side-effect.cc b/gcc/gimple-range-side-effect.cc index 8d2ac35bc8d..aae087b7227 100644 --- a/gcc/gimple-range-side-effect.cc +++ b/gcc/gimple-range-side-effect.cc @@ -58,7 +58,7 @@ non_null_loadstore (gimple *, tree op, tree, void *data) // Add NAME and RANGE to the the side effect summary. void -stmt_side_effects::add_range (tree name, irange &range) +stmt_side_effects::add_range (tree name, vrange &range) { m_names[num_args] = name; m_ranges[num_args] = range; @@ -126,7 +126,7 @@ class exit_range { public: tree name; - irange *range; + vrange *range; exit_range *next; }; @@ -181,7 +181,7 @@ side_effect_manager::~side_effect_manager () // Return a non-zero range value of the appropriate type for NAME from // the cache, creating it if necessary. -const irange& +const vrange& side_effect_manager::get_nonzero (tree name) { unsigned v = SSA_NAME_VERSION (name); @@ -189,10 +189,8 @@ side_effect_manager::get_nonzero (tree name) m_nonzero.safe_grow_cleared (num_ssa_names + 20); if (!m_nonzero[v]) { - tree type = TREE_TYPE (name); - m_nonzero[v] - = static_cast (m_range_allocator.alloc_vrange (type)); - m_nonzero[v]->set_nonzero (type); + m_nonzero[v] = m_range_allocator.alloc_vrange (TREE_TYPE (name)); + m_nonzero[v]->set_nonzero (TREE_TYPE (name)); } return *(m_nonzero[v]); } @@ -219,7 +217,7 @@ side_effect_manager::has_range_p (tree name, basic_block bb) // to include it. bool -side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb) +side_effect_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb) { if (!has_range_p (name, bb)) return false; @@ -232,7 +230,7 @@ side_effect_manager::maybe_adjust_range (irange &r, tree name, basic_block bb) // Add range R as a side effect for NAME in block BB. void -side_effect_manager::add_range (tree name, basic_block bb, const irange &r) +side_effect_manager::add_range (tree name, basic_block bb, const vrange &r) { if (bb->index >= (int)m_on_exit.length ()) m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1); @@ -254,7 +252,7 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r) exit_range *ptr = m_on_exit[bb->index].find_ptr (name); if (ptr) { - int_range_max cur = r; + tmp_range cur (r); // If no new info is added, just return. if (!cur.intersect (*(ptr->range))) return; @@ -263,7 +261,7 @@ side_effect_manager::add_range (tree name, basic_block bb, const irange &r) else { vrange &v = cur; - ptr->range = static_cast (m_range_allocator.clone (v)); + ptr->range = m_range_allocator.clone (v); } return; } diff --git a/gcc/gimple-range-side-effect.h b/gcc/gimple-range-side-effect.h index d76d6eb34f2..a7625646ed1 100644 --- a/gcc/gimple-range-side-effect.h +++ b/gcc/gimple-range-side-effect.h @@ -33,15 +33,15 @@ public: inline unsigned num () const { return num_args; } inline tree name (unsigned index) const { gcc_checking_assert (index < num_args); return m_names[index]; } - inline const irange& range (unsigned index) const + inline const vrange& range (unsigned index) const { gcc_checking_assert (index < num_args); return m_ranges[index]; } - void add_range (tree name, irange &range); + void add_range (tree name, vrange &range); void add_nonzero (tree name); private: unsigned num_args; static const int size_limit = 10; tree m_names[size_limit]; - int_range<3> m_ranges[size_limit]; + tmp_range m_ranges[size_limit]; inline void bump_index () { if (num_args < size_limit - 1) num_args++; } }; @@ -56,10 +56,10 @@ class side_effect_manager public: side_effect_manager (bool do_search); ~side_effect_manager (); - void add_range (tree name, basic_block bb, const irange &r); + void add_range (tree name, basic_block bb, const vrange &r); void add_nonzero (tree name, basic_block bb); bool has_range_p (tree name, basic_block bb); - bool maybe_adjust_range (irange &r, tree name, basic_block bb); + bool maybe_adjust_range (vrange &r, tree name, basic_block bb); private: class exit_range_head { @@ -71,8 +71,8 @@ private: }; void register_all_uses (tree name); vec m_on_exit; - const irange &get_nonzero (tree name); - vec m_nonzero; + const vrange &get_nonzero (tree name); + vec m_nonzero; bitmap m_seen; bitmap_obstack m_bitmaps; struct obstack m_list_obstack; diff --git a/gcc/gimple-range-tests.cc b/gcc/gimple-range-tests.cc index 572acd33d7f..84ecc486889 100644 --- a/gcc/gimple-range-tests.cc +++ b/gcc/gimple-range-tests.cc @@ -42,8 +42,9 @@ public: ASSERT_TRUE (r == expect); } - virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) override + virtual bool range_of_expr (vrange &v, tree expr, gimple * = NULL) override { + irange &r = as_a (v); if (expr == op0) { r.set (build_int_cst (type, 5), build_int_cst (type, 10)); diff --git a/gcc/gimple-range-trace.cc b/gcc/gimple-range-trace.cc index 39971093e6d..37cf37ca885 100644 --- a/gcc/gimple-range-trace.cc +++ b/gcc/gimple-range-trace.cc @@ -102,7 +102,7 @@ range_tracer::print (unsigned counter, const char *str) void range_tracer::trailer (unsigned counter, const char *caller, bool result, - tree name, const irange &r) + tree name, const vrange &r) { gcc_checking_assert (tracing && counter != 0); @@ -141,7 +141,6 @@ debug_seed_ranger (gimple_ranger &ranger) } basic_block bb; - int_range_max r; gimple_stmt_iterator gsi; FOR_EACH_BB_FN (bb, cfun) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -151,7 +150,11 @@ debug_seed_ranger (gimple_ranger &ranger) if (is_gimple_debug (stmt)) continue; - ranger.range_of_stmt (r, stmt); + if (tree type = gimple_range_type (stmt)) + { + tmp_range r (type); + ranger.range_of_stmt (r, stmt); + } } } diff --git a/gcc/gimple-range-trace.h b/gcc/gimple-range-trace.h index 302afda3104..3f92e51803b 100644 --- a/gcc/gimple-range-trace.h +++ b/gcc/gimple-range-trace.h @@ -32,7 +32,7 @@ public: range_tracer (const char *name = ""); unsigned header (const char *str); void trailer (unsigned counter, const char *caller, bool result, tree name, - const irange &r); + const vrange &r); void print (unsigned counter, const char *str); inline void enable_trace () { tracing = true; } inline void disable_trace () { tracing = false; } diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 32d57c9e3db..1118feb41a5 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -71,7 +71,7 @@ gimple_ranger::~gimple_ranger () } bool -gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt) +gimple_ranger::range_of_expr (vrange &r, tree expr, gimple *stmt) { unsigned idx; if (!gimple_range_ssa_p (expr)) @@ -93,7 +93,7 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt) // If there is no statement, just get the global value. if (!stmt) { - int_range_max tmp; + tmp_range tmp (TREE_TYPE (expr)); m_cache.get_global_range (r, expr); // Pick up implied context information from the on-entry cache // if current_bb is set. Do not attempt any new calculations. @@ -137,9 +137,9 @@ gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt) // Return the range of NAME on entry to block BB in R. void -gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name) +gimple_ranger::range_on_entry (vrange &r, basic_block bb, tree name) { - int_range_max entry_range; + tmp_range entry_range (TREE_TYPE (name)); gcc_checking_assert (gimple_range_ssa_p (name)); unsigned idx; @@ -164,7 +164,7 @@ gimple_ranger::range_on_entry (irange &r, basic_block bb, tree name) // Return false if no range can be calculated. void -gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name) +gimple_ranger::range_on_exit (vrange &r, basic_block bb, tree name) { // on-exit from the exit block? gcc_checking_assert (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)); @@ -198,10 +198,10 @@ gimple_ranger::range_on_exit (irange &r, basic_block bb, tree name) // Calculate a range for NAME on edge E and return it in R. bool -gimple_ranger::range_on_edge (irange &r, edge e, tree name) +gimple_ranger::range_on_edge (vrange &r, edge e, tree name) { - int_range_max edge_range; - gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name))); + tmp_range edge_range (TREE_TYPE (name)); + gcc_checking_assert (vrange::supports_type_p (TREE_TYPE (name))); // Do not process values along abnormal edges. if (e->flags & EDGE_ABNORMAL) @@ -249,7 +249,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name) // fold_range wrapper for range_of_stmt to use as an internal client. bool -gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name) +gimple_ranger::fold_range_internal (vrange &r, gimple *s, tree name) { fold_using_range f; fur_depend src (s, &(gori ()), this); @@ -263,7 +263,7 @@ gimple_ranger::fold_range_internal (irange &r, gimple *s, tree name) // avoided. If a range cannot be calculated, return false and UNDEFINED. bool -gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) +gimple_ranger::range_of_stmt (vrange &r, gimple *s, tree name) { bool res; r.set_undefined (); @@ -313,7 +313,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) prefill_stmt_dependencies (name); // Calculate a new value. - int_range_max tmp; + tmp_range tmp (TREE_TYPE (name)); fold_range_internal (tmp, s, name); // Combine the new value with the old value. This is required because @@ -334,7 +334,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) // stack if so. R is a scratch range. inline void -gimple_ranger::prefill_name (irange &r, tree name) +gimple_ranger::prefill_name (tmp_range &r, tree name) { if (!gimple_range_ssa_p (name)) return; @@ -343,6 +343,7 @@ gimple_ranger::prefill_name (irange &r, tree name) return; bool current; + r.init (TREE_TYPE (name)); // If this op has not been processed yet, then push it on the stack if (!m_cache.get_global_range (r, name, current)) m_stmt_list.safe_push (name); @@ -357,7 +358,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) if (SSA_NAME_IS_DEFAULT_DEF (ssa)) return; - int_range_max r; + tmp_range r; unsigned idx; gimple *stmt = SSA_NAME_DEF_STMT (ssa); gcc_checking_assert (stmt && gimple_bb (stmt)); @@ -388,6 +389,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) { // Fold and save the value for NAME. stmt = SSA_NAME_DEF_STMT (name); + r.init (TREE_TYPE (name)); fold_range_internal (r, stmt, name); // Make sure we don't lose any current global info. int_range_max tmp; @@ -488,10 +490,11 @@ gimple_ranger::export_global_ranges () bool print_header = true; for (unsigned x = 1; x < num_ssa_names; x++) { - int_range_max r; + tmp_range r; tree name = ssa_name (x); if (name && !SSA_NAME_IN_FREE_LIST (name) && gimple_range_ssa_p (name) + && r.init (TREE_TYPE (name)) && m_cache.get_global_range (r, name) && !r.varying_p()) { @@ -508,13 +511,17 @@ gimple_ranger::export_global_ranges () print_header = false; } - value_range vr = r; + if (!irange::supports_type_p (TREE_TYPE (name))) + continue; + + vrange &v = r; + value_range vr = as_a (v); print_generic_expr (dump_file, name , TDF_SLIM); fprintf (dump_file, " : "); vr.dump (dump_file); fprintf (dump_file, "\n"); int_range_max same = vr; - if (same != r) + if (same != as_a (v)) { fprintf (dump_file, " irange : "); r.dump (dump_file); @@ -532,7 +539,7 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb) unsigned x; edge_iterator ei; edge e; - int_range_max range, tmp_range; + tmp_range range, tmp_range; fprintf (f, "\n=========== BB %d ============\n", bb->index); m_cache.dump_bb (f, bb); @@ -543,6 +550,7 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb) { tree name = ssa_name (x); if (gimple_range_ssa_p (name) && SSA_NAME_DEF_STMT (name) && + range.init (TREE_TYPE (name)) && gimple_bb (SSA_NAME_DEF_STMT (name)) == bb && m_cache.get_global_range (range, name)) { @@ -564,9 +572,11 @@ gimple_ranger::dump_bb (FILE *f, basic_block bb) { tree name = gimple_range_ssa_p (ssa_name (x)); if (name && gori ().has_edge_range_p (name, e) + && range.init (TREE_TYPE (name)) && m_cache.range_on_edge (range, e, name)) { gimple *s = SSA_NAME_DEF_STMT (name); + tmp_range.init (TREE_TYPE (name)); // Only print the range if this is the def block, or // the on entry cache for either end of the edge is // set. diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 13d4c77883e..ca5a33e65c6 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -48,11 +48,11 @@ class gimple_ranger : public range_query public: gimple_ranger (bool use_imm_uses = true); ~gimple_ranger (); - virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL) override; - virtual bool range_of_expr (irange &r, tree name, gimple * = NULL) override; - virtual bool range_on_edge (irange &r, edge e, tree name) override; - void range_on_entry (irange &r, basic_block bb, tree name); - void range_on_exit (irange &r, basic_block bb, tree name); + virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override; + virtual bool range_of_expr (vrange &r, tree name, gimple * = NULL) override; + virtual bool range_on_edge (vrange &r, edge e, tree name) override; + void range_on_entry (vrange &r, basic_block bb, tree name); + void range_on_exit (vrange &r, basic_block bb, tree name); void export_global_ranges (); inline gori_compute &gori () { return m_cache.m_gori; } virtual void dump (FILE *f) override; @@ -62,8 +62,8 @@ public: bool fold_stmt (gimple_stmt_iterator *gsi, tree (*) (tree)); void register_side_effects (gimple *s); protected: - bool fold_range_internal (irange &r, gimple *s, tree name); - void prefill_name (irange &r, tree name); + bool fold_range_internal (vrange &r, gimple *s, tree name); + void prefill_name (tmp_range &r, tree name); void prefill_stmt_dependencies (tree ssa); ranger_cache m_cache; range_tracer tracer; diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 9357a4e576a..132d82a5240 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -328,11 +328,11 @@ check_nul_terminated_array (GimpleOrTree expr, tree src, tree bound) wide_int bndrng[2]; if (bound) { - value_range r; + tmp_range r (TREE_TYPE (bound)); get_global_range_query ()->range_of_expr (r, bound); - if (r.kind () != VR_RANGE) + if (r.undefined_p () || r.varying_p ()) return true; bndrng[0] = r.lower_bound (); @@ -2790,9 +2790,8 @@ memmodel_to_uhwi (tree ord, gimple *stmt, unsigned HOST_WIDE_INT *cstval) { /* Use the range query to determine constant values in the absence of constant propagation (such as at -O0). */ - value_range rng; + tmp_range rng (TREE_TYPE (ord)); if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt) - || !rng.constant_p () || !rng.singleton_p (&ord)) return false; diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index afa51064953..8907e310c19 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -221,7 +221,7 @@ refine_value_range_using_guard (tree type, tree var, get_type_static_bounds (type, mint, maxt); mpz_init (minc1); mpz_init (maxc1); - value_range r; + tmp_range r (TREE_TYPE (varc1)); /* Setup range information for varc1. */ if (integer_zerop (varc1)) { @@ -374,7 +374,7 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off, gphi_iterator gsi; /* Either for VAR itself... */ - value_range var_range; + tmp_range var_range (TREE_TYPE (var)); get_range_query (cfun)->range_of_expr (var_range, var); rtype = var_range.kind (); if (!var_range.undefined_p ()) @@ -385,10 +385,10 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off, /* Or for PHI results in loop->header where VAR is used as PHI argument from the loop preheader edge. */ + tmp_range phi_range (TREE_TYPE (var)); for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) { gphi *phi = gsi.phi (); - value_range phi_range; if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var && get_range_query (cfun)->range_of_expr (phi_range, gimple_phi_result (phi)) @@ -410,7 +410,7 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off, involved. */ if (wi::gt_p (minv, maxv, sgn)) { - value_range vr; + tmp_range vr (TREE_TYPE (var)); get_range_query (cfun)->range_of_expr (vr, var); rtype = vr.kind (); if (!vr.undefined_p ()) @@ -3650,7 +3650,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt, if (tree_int_cst_sign_bit (step)) { wide_int max; - value_range base_range; + tmp_range base_range (TREE_TYPE (orig_base)); if (get_range_query (cfun)->range_of_expr (base_range, orig_base) && !base_range.undefined_p ()) max = base_range.upper_bound (); @@ -3672,7 +3672,7 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt, else { wide_int min; - value_range base_range; + tmp_range base_range (TREE_TYPE (orig_base)); if (get_range_query (cfun)->range_of_expr (base_range, orig_base) && !base_range.undefined_p ()) min = base_range.lower_bound (); @@ -3947,7 +3947,7 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt) low = lower_bound_in_type (type, type); high = upper_bound_in_type (type, type); - value_range r; + tmp_range r (TREE_TYPE (def)); get_range_query (cfun)->range_of_expr (r, def); if (r.kind () == VR_RANGE) { @@ -4997,7 +4997,7 @@ scev_var_range_cant_overflow (tree var, tree step, class loop *loop) if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb)) return false; - value_range r; + tmp_range r (TREE_TYPE (var)); get_range_query (cfun)->range_of_expr (r, var); if (r.kind () != VR_RANGE) return false; diff --git a/gcc/tree-ssa-threadedge.cc b/gcc/tree-ssa-threadedge.cc index 4eb65ca7cac..d5e285d5d4d 100644 --- a/gcc/tree-ssa-threadedge.cc +++ b/gcc/tree-ssa-threadedge.cc @@ -1409,19 +1409,19 @@ tree hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block, jt_state *state) { - int_range_max r; - compute_ranges_from_state (stmt, state); if (gimple_code (stmt) == GIMPLE_COND || gimple_code (stmt) == GIMPLE_ASSIGN) { + tmp_range r (gimple_range_type (stmt)); tree ret; if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret)) return ret; } else if (gimple_code (stmt) == GIMPLE_SWITCH) { + int_range_max r; gswitch *switch_stmt = dyn_cast (stmt); tree index = gimple_switch_index (switch_stmt); if (m_query->range_of_expr (r, index, stmt)) diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 31e56eeae53..463ac179a00 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -57,13 +57,13 @@ value_query::value_of_stmt (gimple *stmt, tree name) // range_query default methods. bool -range_query::range_on_edge (irange &r, edge, tree expr) +range_query::range_on_edge (vrange &r, edge, tree expr) { return range_of_expr (r, expr); } bool -range_query::range_of_stmt (irange &r, gimple *stmt, tree name) +range_query::range_of_stmt (vrange &r, gimple *stmt, tree name) { if (!name) name = gimple_get_lhs (stmt); @@ -79,11 +79,12 @@ tree range_query::value_of_expr (tree expr, gimple *stmt) { tree t; - int_range_max r; - if (!irange::supports_type_p (TREE_TYPE (expr))) + if (!vrange::supports_type_p (TREE_TYPE (expr))) return NULL_TREE; + tmp_range r (TREE_TYPE (expr)); + if (range_of_expr (r, expr, stmt)) { // A constant used in an unreachable block oftens returns as UNDEFINED. @@ -100,10 +101,10 @@ tree range_query::value_on_edge (edge e, tree expr) { tree t; - int_range_max r; - if (!irange::supports_type_p (TREE_TYPE (expr))) + if (!vrange::supports_type_p (TREE_TYPE (expr))) return NULL_TREE; + tmp_range r (TREE_TYPE (expr)); if (range_on_edge (r, e, expr)) { // A constant used in an unreachable block oftens returns as UNDEFINED. @@ -121,15 +122,15 @@ tree range_query::value_of_stmt (gimple *stmt, tree name) { tree t; - int_range_max r; if (!name) name = gimple_get_lhs (stmt); gcc_checking_assert (!name || name == gimple_get_lhs (stmt)); - if (!name || !irange::supports_type_p (TREE_TYPE (name))) + if (!name || !vrange::supports_type_p (TREE_TYPE (name))) return NULL_TREE; + tmp_range r (TREE_TYPE (name)); if (range_of_stmt (r, stmt, name) && r.singleton_p (&t)) return t; return NULL_TREE; @@ -187,7 +188,7 @@ range_query::~range_query () // representable, and UNDEFINED/false if not. bool -range_query::get_tree_range (irange &r, tree expr, gimple *stmt) +range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) { tree type; if (TYPE_P (expr)) @@ -195,7 +196,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) else type = TREE_TYPE (expr); - if (!irange::supports_type_p (type)) + if (!vrange::supports_type_p (type)) { r.set_undefined (); return false; @@ -214,7 +215,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) return true; case SSA_NAME: - r = gimple_range_global (expr); + gimple_range_global (r, expr); return true; case ADDR_EXPR: @@ -223,7 +224,7 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) bool ov; if (tree_single_nonzero_warnv_p (expr, &ov)) { - r = range_nonzero (type); + r.set_nonzero (type); return true; } break; @@ -237,7 +238,8 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) range_op_handler op (TREE_CODE (expr), type); if (op) { - int_range_max r0, r1; + tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0))); + tmp_range r1 (TREE_TYPE (TREE_OPERAND (expr, 1))); range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); range_of_expr (r1, TREE_OPERAND (expr, 1), stmt); op.fold_range (r, type, r0, r1); @@ -250,11 +252,13 @@ range_query::get_tree_range (irange &r, tree expr, gimple *stmt) { range_op_handler op (TREE_CODE (expr), type); tree op0_type = TREE_TYPE (TREE_OPERAND (expr, 0)); - if (op && irange::supports_type_p (op0_type)) + if (op && vrange::supports_type_p (op0_type)) { - int_range_max r0; + tmp_range r0 (TREE_TYPE (TREE_OPERAND (expr, 0))); + tmp_range r1 (type); + r1.set_varying (type); range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); - op.fold_range (r, type, r0, int_range<1> (type)); + op.fold_range (r, type, r0, r1); } else r.set_varying (type); @@ -311,7 +315,7 @@ get_ssa_name_ptr_info_nonnull (const_tree name) // updated. bool -update_global_range (irange &r, tree name) +update_global_range (vrange &r, tree name) { tree type = TREE_TYPE (name); @@ -330,8 +334,7 @@ update_global_range (irange &r, tree name) if (r.undefined_p ()) return false; - value_range vr = r; - set_range_info (name, vr); + set_range_info (name, as_a (r)); return true; } else if (POINTER_TYPE_P (type)) @@ -349,7 +352,7 @@ update_global_range (irange &r, tree name) // return VARYING. static void -get_range_global (irange &r, tree name) +get_range_global (vrange &r, tree name) { tree type = TREE_TYPE (name); @@ -369,7 +372,7 @@ get_range_global (irange &r, tree name) r.set_nonzero (type); else if (INTEGRAL_TYPE_P (type)) { - get_ssa_name_range_info (r, name); + get_ssa_name_range_info (as_a (r), name); if (r.undefined_p ()) r.set_varying (type); } @@ -384,7 +387,8 @@ get_range_global (irange &r, tree name) } else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name)) { - get_ssa_name_range_info (r, name); + gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name))); + get_ssa_name_range_info (as_a (r), name); if (r.undefined_p ()) r.set_varying (type); } @@ -414,21 +418,19 @@ get_range_global (irange &r, tree name) // See discussion here: // https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571709.html -value_range -gimple_range_global (tree name) +void +gimple_range_global (vrange &r, tree name) { tree type = TREE_TYPE (name); - gcc_checking_assert (TREE_CODE (name) == SSA_NAME - && irange::supports_type_p (type)); + gcc_checking_assert (TREE_CODE (name) == SSA_NAME); if (SSA_NAME_IS_DEFAULT_DEF (name) || (cfun && cfun->after_inlining) || is_a (SSA_NAME_DEF_STMT (name))) { - value_range vr; - get_range_global (vr, name); - return vr; + get_range_global (r, name); + return; } - return value_range (type); + r.set_varying (type); } // ---------------------------------------------- @@ -437,7 +439,7 @@ gimple_range_global (tree name) global_range_query global_ranges; bool -global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt) +global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt) { tree type = TREE_TYPE (expr); @@ -456,15 +458,16 @@ global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt) relation_kind range_query::query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range) { - int_range_max tmp; if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME) return VREL_VARYING; // Ensure ssa1 and ssa2 have both been evaluated. if (get_range) { - range_of_expr (tmp, ssa1, s); - range_of_expr (tmp, ssa2, s); + tmp_range tmp1 (TREE_TYPE (ssa1)); + tmp_range tmp2 (TREE_TYPE (ssa2)); + range_of_expr (tmp1, ssa1, s); + range_of_expr (tmp2, ssa2, s); } return m_oracle->query_relation (gimple_bb (s), ssa1, ssa2); } @@ -477,7 +480,6 @@ relation_kind range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range) { basic_block bb; - int_range_max tmp; if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME) return VREL_VARYING; @@ -492,6 +494,7 @@ range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range) // Ensure ssa1 and ssa2 have both been evaluated. if (get_range) { + tmp_range tmp (TREE_TYPE (ssa1)); range_on_edge (tmp, e, ssa1); range_on_edge (tmp, e, ssa2); } diff --git a/gcc/value-query.h b/gcc/value-query.h index cf1a1d74de3..280e47e3f6b 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -89,9 +89,9 @@ public: // // Note that range_of_expr must always return TRUE unless ranges are // unsupported for EXPR's type (supports_type_p is false). - virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) = 0; - virtual bool range_on_edge (irange &r, edge, tree expr); - virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL); + virtual bool range_of_expr (vrange &r, tree expr, gimple * = NULL) = 0; + virtual bool range_on_edge (vrange &r, edge, tree expr); + virtual bool range_of_stmt (vrange &r, gimple *, tree name = NULL); // Query if there is any relation between SSA1 and SSA2. relation_kind query_relation (gimple *s, tree ssa1, tree ssa2, @@ -110,8 +110,8 @@ public: protected: class value_range_equiv *allocate_value_range_equiv (); void free_value_range_equiv (class value_range_equiv *); - bool get_tree_range (irange &r, tree expr, gimple *stmt); - bool get_arith_expr_range (irange &r, tree expr, gimple *stmt); + bool get_tree_range (vrange &v, tree expr, gimple *stmt); + bool get_arith_expr_range (vrange &r, tree expr, gimple *stmt); relation_oracle *m_oracle; private: @@ -123,7 +123,7 @@ private: class global_range_query : public range_query { public: - bool range_of_expr (irange &r, tree expr, gimple * = NULL) override; + bool range_of_expr (vrange &r, tree expr, gimple * = NULL) override; }; extern global_range_query global_ranges; @@ -143,7 +143,7 @@ get_range_query (const struct function *fun) return fun->x_range_query ? fun->x_range_query : &global_ranges; } -extern value_range gimple_range_global (tree name); -extern bool update_global_range (irange &r, tree name); +extern void gimple_range_global (vrange &v, tree name); +extern bool update_global_range (vrange &v, tree name); #endif // GCC_QUERY_H diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 6f8583c8d01..9b681a46905 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -177,7 +177,7 @@ vr_values::get_value_range (const_tree var, } bool -vr_values::range_of_expr (irange &r, tree expr, gimple *stmt) +vr_values::range_of_expr (vrange &r, tree expr, gimple *stmt) { if (!gimple_range_ssa_p (expr)) return get_tree_range (r, expr, stmt); @@ -1640,6 +1640,8 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, { tree init, step, chrec, tmin, tmax, type = TREE_TYPE (var); enum ev_direction dir; + tmp_range trange; + int_range<2> r; chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var)); @@ -1661,11 +1663,15 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, /* If INIT is an SSA with a singleton range, set INIT to said singleton, otherwise leave INIT alone. */ - if (TREE_CODE (init) == SSA_NAME) - query->get_value_range (init, stmt)->singleton_p (&init); + if (TREE_CODE (init) == SSA_NAME + && trange.init (TREE_TYPE (init)) + && query->range_of_expr (trange, init, stmt)) + trange.singleton_p (&init); /* Likewise for step. */ - if (TREE_CODE (step) == SSA_NAME) - query->get_value_range (step, stmt)->singleton_p (&step); + if (TREE_CODE (step) == SSA_NAME + && trange.init (TREE_TYPE (step)) + && query->range_of_expr (trange, step, stmt)) + trange.singleton_p (&step); /* If STEP is symbolic, we can't know whether INIT will be the minimum or maximum value in the range. Also, unless INIT is @@ -1699,7 +1705,8 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, if (TREE_CODE (step) == INTEGER_CST && is_gimple_val (init) && (TREE_CODE (init) != SSA_NAME - || query->get_value_range (init, stmt)->kind () == VR_RANGE)) + || (query->range_of_expr (r, init, stmt) + && r.kind () == VR_RANGE))) { widest_int nit; @@ -1724,7 +1731,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, { value_range maxvr, vr0, vr1; if (TREE_CODE (init) == SSA_NAME) - vr0 = *(query->get_value_range (init, stmt)); + query->range_of_expr (vr0, init, stmt); else if (is_gimple_min_invariant (init)) vr0.set (init); else @@ -1737,10 +1744,10 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, /* Likewise if the addition did. */ if (maxvr.kind () == VR_RANGE) { - value_range initvr; + int_range<2> initvr; if (TREE_CODE (init) == SSA_NAME) - initvr = *(query->get_value_range (init, stmt)); + query->range_of_expr (initvr, init, stmt); else if (is_gimple_min_invariant (init)) initvr.set (init); else @@ -2446,7 +2453,9 @@ simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) fprintf (dump_file, "\t"); print_generic_expr (dump_file, use); fprintf (dump_file, ": "); - dump_value_range (dump_file, query->get_value_range (use, stmt)); + tmp_range r (TREE_TYPE (use)); + query->range_of_expr (r, use, stmt); + r.dump (dump_file); } fprintf (dump_file, "\n"); diff --git a/gcc/vr-values.h b/gcc/vr-values.h index 7a377cebd01..f018d0dfc4b 100644 --- a/gcc/vr-values.h +++ b/gcc/vr-values.h @@ -109,7 +109,7 @@ class vr_values : public range_query vr_values (void); ~vr_values (void); - virtual bool range_of_expr (irange &r, tree expr, gimple *stmt) override; + virtual bool range_of_expr (vrange &r, tree expr, gimple *stmt) override; virtual tree value_of_expr (tree, gimple * = NULL) override; virtual tree value_on_edge (edge, tree) override; virtual tree value_of_stmt (gimple *, tree = NULL_TREE) override;