From: Aldy Hernandez <aldyh@redhat.com>
To: Andrew MacLeod <amacleod@redhat.com>
Cc: GCC patches <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH 2/5] Implement generic range temporaries.
Date: Wed, 1 Jun 2022 11:01:14 +0200 [thread overview]
Message-ID: <CAGm3qMU6ycLbO-ApU4Ns2UOWCbjXLC0BY6f86Ta3C+Ddz7mRsA@mail.gmail.com> (raw)
In-Reply-To: <CAGm3qMX1FAJbcy1keFa6tkWY9uGoQYfzPh1OG-OLivMWcf-=+g@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2291 bytes --]
Final patch committed.
tmp_range has been renamed to Value_Range.
Value_Range::init() has been renamed to set_type() which is more obvious.
Default constructor for Value_Range now points the vrange to the
unsupported_range object, so we always have an object available.
Re-tested on x86-64 Linux.
On Tue, May 31, 2022 at 8:21 AM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> On Mon, May 30, 2022 at 4:56 PM Andrew MacLeod <amacleod@redhat.com> wrote:
> >
> > On 5/30/22 09:27, Aldy Hernandez wrote:
> > > 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.
> > >
> > I was going to suggest maybe renaming value_range to legacy_range or
> > something, and then start using value_range for ranges of any time.
> > Then it occurred to me that numerous places which use value_range
> > will/can continue to use value_range going forward.. ie
> >
> > value_range vr;
> > if (!rvals->range_of_expr (vr, name, stmt))
> > return -1;
> >
> > would be unaffected, to it would be pointless turmoil to rename that and
> > then rename it back to value_range.
> >
> > I also notice there are already a few instance of local variable named
> > tmp_range, which make name renames annoying. Perhaps we should use
> > Value_Range or something like that in the interim for the multi-type
> > ranges? Then the rename is trivial down the road, formatting will be
> > unaffected, and then we're kinda sorta using the end_goal name?
>
> OMG that is so ugly! Although I guess it would be temporary.
>
> Speaking of which, how far away are we from enabling ranger in VRP1?
> Because once we do that, we can start nuking legacy and cleaning all
> this up.
>
> Aldy
[-- Attachment #2: 0002-Implement-generic-range-temporaries.patch --]
[-- Type: text/x-patch, Size: 9458 bytes --]
From 59c8e96dd02383baec4c15665985da3caadaaa5e Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Mon, 14 Mar 2022 13:27:36 +0100
Subject: [PATCH] Implement generic range temporaries.
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 Value_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, Value_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:
Value_Range t (type);
t.set_nonzero (type);
foo (t);
You can also delay initialization, for use in loops for example:
Value_Range t;
...
t.set_type (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 Value_Range class will be augmented
to support them by adding the relevant bits in the initialization
code, etc.
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 (Value_Range::lower_bound): New.
(Value_Range::upper_bound): New.
(Value_Range::dump): New.
* value-range.h (class Value_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 | 135 ++++++++++++++++++++++++++++++++++++++-
5 files changed, 174 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..429672737a8 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
+Value_Range::lower_bound () const
+{
+ if (is_a <irange> (*m_vrange))
+ return as_a <irange> (*m_vrange).lower_bound ();
+ gcc_unreachable ();
+}
+
+// Convenience function only available for integers and pointers.
+
+wide_int
+Value_Range::upper_bound () const
+{
+ if (is_a <irange> (*m_vrange))
+ return as_a <irange> (*m_vrange).upper_bound ();
+ gcc_unreachable ();
+}
+
+void
+Value_Range::dump (FILE *out) const
+{
+ if (m_vrange)
+ m_vrange->dump (out);
+ else
+ fprintf (out, "NULL");
+}
+
+DEBUG_FUNCTION void
+debug (const Value_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 Value_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..b7ea8c76f87 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -54,6 +54,7 @@ enum value_range_discriminator
class vrange
{
template <typename T> friend bool is_a (vrange &);
+ friend class Value_Range;
public:
virtual void set (tree, tree, value_range_kind = VR_RANGE) = 0;
virtual tree type () const = 0;
@@ -313,6 +314,136 @@ 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 Value_Range
+{
+public:
+ Value_Range ();
+ Value_Range (const vrange &r);
+ Value_Range (tree type);
+ void set_type (tree type);
+ vrange& operator= (const vrange &);
+ bool operator== (const Value_Range &r) const;
+ bool operator!= (const Value_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:
+ void init (tree type);
+ static unsupported_range m_unsupported;
+ vrange *m_vrange;
+ int_range_max m_irange;
+ DISABLE_COPY_AND_ASSIGN (Value_Range);
+};
+
+inline
+Value_Range::Value_Range ()
+{
+ m_vrange = &m_unsupported;
+}
+
+// Copy constructor from a vrange.
+
+inline
+Value_Range::Value_Range (const vrange &r)
+{
+ *this = r;
+}
+
+// Copy constructor from a TYPE. The range of the temporary is set to
+// UNDEFINED.
+
+inline
+Value_Range::Value_Range (tree type)
+{
+ init (type);
+}
+
+// Initialize object so it is possible to store temporaries of TYPE
+// into it.
+
+inline void
+Value_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;
+}
+
+// Set the temporary to allow storing temporaries of TYPE. The range
+// of the temporary is set to UNDEFINED.
+
+inline void
+Value_Range::set_type (tree type)
+{
+ init (type);
+ m_vrange->set_undefined ();
+}
+
+// Assignment operator for temporaries. Copying incompatible types is
+// allowed.
+
+inline vrange &
+Value_Range::operator= (const vrange &r)
+{
+ if (is_a <irange> (r))
+ {
+ m_irange = as_a <irange> (r);
+ m_vrange = &m_irange;
+ }
+ else
+ gcc_unreachable ();
+
+ return *m_vrange;
+}
+
+inline bool
+Value_Range::operator== (const Value_Range &r) const
+{
+ return *m_vrange == *r.m_vrange;
+}
+
+inline bool
+Value_Range::operator!= (const Value_Range &r) const
+{
+ return *m_vrange != *r.m_vrange;
+}
+
+inline
+Value_Range::operator vrange &()
+{
+ return *m_vrange;
+}
+
+inline
+Value_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 +582,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
--
2.36.1
next prev parent reply other threads:[~2022-06-01 9:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-30 13:27 [PATCH 1/5] Implement abstract vrange class Aldy Hernandez
2022-05-30 13:27 ` [PATCH 2/5] Implement generic range temporaries Aldy Hernandez
2022-05-30 14:56 ` Andrew MacLeod
2022-05-31 6:21 ` Aldy Hernandez
2022-05-31 16:40 ` Andrew MacLeod
2022-06-01 9:01 ` Aldy Hernandez [this message]
2022-05-30 13:27 ` [PATCH 3/5] Convert range-op.* to vrange Aldy Hernandez
2022-06-01 9:01 ` Aldy Hernandez
2022-05-30 13:27 ` [PATCH 4/5] Revamp irange_allocator to handle vranges Aldy Hernandez
2022-06-01 9:02 ` Aldy Hernandez
2022-05-30 13:27 ` [PATCH 5/5] Convert ranger and clients to vrange Aldy Hernandez
2022-06-01 9:04 ` Aldy Hernandez
2022-06-27 0:33 ` Xi Ruoyao
2022-06-01 8:57 ` [PATCH 1/5] Implement abstract vrange class Aldy Hernandez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAGm3qMU6ycLbO-ApU4Ns2UOWCbjXLC0BY6f86Ta3C+Ddz7mRsA@mail.gmail.com \
--to=aldyh@redhat.com \
--cc=amacleod@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).