aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range.cc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2022-03-14 13:27:36 +0100
committerAldy Hernandez <aldyh@redhat.com>2022-06-01 10:55:45 +0200
commit59c8e96dd02383baec4c15665985da3caadaaa5e (patch)
tree141e126d9ba14b585c2c5a8883d7f8732f33cfc3 /gcc/value-range.cc
parent4f1bce19f6d51af1dfe1118cfbec19c55d3909fc (diff)
downloadgcc-59c8e96dd02383baec4c15665985da3caadaaa5e.zip
gcc-59c8e96dd02383baec4c15665985da3caadaaa5e.tar.gz
gcc-59c8e96dd02383baec4c15665985da3caadaaa5e.tar.bz2
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.
Diffstat (limited to 'gcc/value-range.cc')
-rw-r--r--gcc/value-range.cc38
1 files changed, 38 insertions, 0 deletions
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 97ff061..4296727 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.