aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/function-tests.c5
-rw-r--r--gcc/gimple-range-cache.cc4
-rw-r--r--gcc/gimple-range-tests.cc72
-rw-r--r--gcc/gimple-range.cc64
-rw-r--r--gcc/gimple-range.h7
-rw-r--r--gcc/selftest.h1
-rw-r--r--gcc/value-query.cc84
-rw-r--r--gcc/value-query.h2
-rw-r--r--gcc/vr-values.c2
9 files changed, 172 insertions, 69 deletions
diff --git a/gcc/function-tests.c b/gcc/function-tests.c
index 1b8f665..0ac1d37 100644
--- a/gcc/function-tests.c
+++ b/gcc/function-tests.c
@@ -581,6 +581,11 @@ test_ranges ()
push_cfun (fun);
range_tests ();
range_op_tests ();
+
+ build_cfg (fndecl);
+ convert_to_ssa (fndecl);
+ gimple_range_tests ();
+
pop_cfun ();
}
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index cc27574..c58acf4 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -827,7 +827,7 @@ ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
{
if (!gimple_range_ssa_p (name))
{
- get_tree_range (r, name);
+ get_tree_range (r, name, stmt);
return true;
}
@@ -860,7 +860,7 @@ ranger_cache::range_of_expr (irange &r, tree name, gimple *stmt)
}
}
else
- get_tree_range (r, expr);
+ get_tree_range (r, expr, NULL);
return false;
}
diff --git a/gcc/gimple-range-tests.cc b/gcc/gimple-range-tests.cc
new file mode 100644
index 0000000..9ee4c5a
--- /dev/null
+++ b/gcc/gimple-range-tests.cc
@@ -0,0 +1,72 @@
+/* Unit tests for GIMPLE range related routines.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#if CHECKING_P
+
+#include "selftest.h"
+
+namespace selftest {
+
+// Test ranges of tree expressions.
+class test_expr_eval : public gimple_ranger
+{
+public:
+ test_expr_eval ()
+ {
+ type = integer_type_node;
+ op0 = make_ssa_name (type);
+ op1 = make_ssa_name (type);
+
+ // [5,10] + [15,20] => [20, 30]
+ tree expr = fold_build2 (PLUS_EXPR, type, op0, op1);
+ int_range<2> expect (build_int_cst (type, 20), build_int_cst (type, 30));
+ int_range_max r;
+
+ ASSERT_TRUE (range_of_expr (r, expr));
+ ASSERT_TRUE (r == expect);
+ }
+
+ virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) OVERRIDE
+ {
+ if (expr == op0)
+ {
+ r.set (build_int_cst (type, 5), build_int_cst (type, 10));
+ return true;
+ }
+ if (expr == op1)
+ {
+ r.set (build_int_cst (type, 15), build_int_cst (type, 20));
+ return true;
+ }
+ return gimple_ranger::range_of_expr (r, expr);
+ }
+
+private:
+ tree op0, op1, type;
+};
+
+void
+gimple_range_tests ()
+{
+ test_expr_eval e;
+}
+
+} // namespace selftest
+
+#endif // CHECKING_P
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index af42620..db8419b 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -54,16 +54,6 @@ along with GCC; see the file COPYING3. If not see
bool
fur_source::get_operand (irange &r, tree expr)
{
- if (!gimple_range_ssa_p (expr))
- return get_tree_range (r, expr);
-
- // If no query engine is present, simply get the global value.
- if (!m_query)
- {
- r = gimple_range_global (expr);
- return true;
- }
-
// First look for a stmt.
if (m_stmt)
return m_query->range_of_expr (r, expr, m_stmt);
@@ -168,56 +158,6 @@ gimple_range_adjustment (irange &res, const gimple *stmt)
}
}
-// Return a range in R for the tree EXPR. Return true if a range is
-// representable, and UNDEFINED/false if not.
-
-bool
-get_tree_range (irange &r, tree expr)
-{
- tree type;
- if (TYPE_P (expr))
- type = expr;
- else
- type = TREE_TYPE (expr);
-
- // Return false if the type isn't suported.
- if (!irange::supports_type_p (type))
- {
- r.set_undefined ();
- return false;
- }
-
- switch (TREE_CODE (expr))
- {
- case INTEGER_CST:
- if (TREE_OVERFLOW_P (expr))
- expr = drop_tree_overflow (expr);
- r.set (expr, expr);
- return true;
-
- case SSA_NAME:
- r = gimple_range_global (expr);
- return true;
-
- case ADDR_EXPR:
- {
- // Handle &var which can show up in phi arguments.
- bool ov;
- if (tree_single_nonzero_warnv_p (expr, &ov))
- {
- r = range_nonzero (type);
- return true;
- }
- break;
- }
-
- default:
- break;
- }
- r.set_varying (type);
- return true;
-}
-
// Return the base of the RHS of an assignment.
static tree
@@ -961,7 +901,7 @@ bool
gimple_ranger::range_of_expr (irange &r, tree expr, gimple *stmt)
{
if (!gimple_range_ssa_p (expr))
- return get_tree_range (r, expr);
+ return get_tree_range (r, expr, stmt);
// If there is no statement, just get the global value.
if (!stmt)
@@ -1466,3 +1406,5 @@ disable_ranger (struct function *fun)
fun->x_range_query = &global_ranges;
}
+
+#include "gimple-range-tests.cc"
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 65f62e4..02b891f 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -159,6 +159,8 @@ inline bool
fold_range (irange &r, gimple *s, range_query *q = NULL)
{
fold_using_range f;
+ if (q == NULL)
+ q = get_global_range_query ();
fur_source src (q, s);
return f.fold_stmt (r, s, src);
}
@@ -169,13 +171,12 @@ inline bool
fold_range (irange &r, gimple *s, edge on_edge, range_query *q = NULL)
{
fold_using_range f;
+ if (q == NULL)
+ q = get_global_range_query ();
fur_source src (q, on_edge);
return f.fold_stmt (r, s, src);
}
-// Calculate a basic range for a tree node expression.
-extern bool get_tree_range (irange &r, tree expr);
-
// These routines provide a GIMPLE interface to the range-ops code.
extern tree gimple_range_operand1 (const gimple *s);
extern tree gimple_range_operand2 (const gimple *s);
diff --git a/gcc/selftest.h b/gcc/selftest.h
index e609117..80459d6 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -249,6 +249,7 @@ extern void predict_c_tests ();
extern void pretty_print_c_tests ();
extern void range_tests ();
extern void range_op_tests ();
+extern void gimple_range_tests ();
extern void read_rtl_function_c_tests ();
extern void rtl_tests_c_tests ();
extern void sbitmap_c_tests ();
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 070d706..821f224 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -182,6 +182,86 @@ range_query::~range_query ()
delete equiv_alloc;
}
+// Return a range in R for the tree EXPR. Return true if a range is
+// representable, and UNDEFINED/false if not.
+
+bool
+range_query::get_tree_range (irange &r, tree expr, gimple *stmt)
+{
+ tree type;
+ if (TYPE_P (expr))
+ type = expr;
+ else
+ type = TREE_TYPE (expr);
+
+ if (!irange::supports_type_p (type))
+ {
+ r.set_undefined ();
+ return false;
+ }
+ if (expr == type)
+ {
+ r.set_varying (type);
+ return true;
+ }
+ switch (TREE_CODE (expr))
+ {
+ case INTEGER_CST:
+ if (TREE_OVERFLOW_P (expr))
+ expr = drop_tree_overflow (expr);
+ r.set (expr, expr);
+ return true;
+
+ case SSA_NAME:
+ r = gimple_range_global (expr);
+ return true;
+
+ case ADDR_EXPR:
+ {
+ // Handle &var which can show up in phi arguments.
+ bool ov;
+ if (tree_single_nonzero_warnv_p (expr, &ov))
+ {
+ r = range_nonzero (type);
+ return true;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ if (BINARY_CLASS_P (expr))
+ {
+ range_operator *op = range_op_handler (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);
+ }
+ else
+ r.set_varying (type);
+ return true;
+ }
+ if (UNARY_CLASS_P (expr))
+ {
+ range_operator *op = range_op_handler (TREE_CODE (expr), type);
+ if (op)
+ {
+ int_range_max r0;
+ range_of_expr (r0, TREE_OPERAND (expr, 0), stmt);
+ op->fold_range (r, type, r0, int_range<1> (type));
+ }
+ else
+ r.set_varying (type);
+ return true;
+ }
+ r.set_varying (type);
+ return true;
+}
+
// Return the range for NAME from SSA_NAME_RANGE_INFO.
static inline void
@@ -355,12 +435,12 @@ get_global_range_query ()
}
bool
-global_range_query::range_of_expr (irange &r, tree expr, gimple *)
+global_range_query::range_of_expr (irange &r, tree expr, gimple *stmt)
{
tree type = TREE_TYPE (expr);
if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
- return get_tree_range (r, expr);
+ return get_tree_range (r, expr, stmt);
get_range_global (r, expr);
diff --git a/gcc/value-query.h b/gcc/value-query.h
index d0512e4..77e49e9 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -100,6 +100,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);
private:
class equiv_allocator *equiv_alloc;
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 3d0be8e..509c8b0 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -180,7 +180,7 @@ bool
vr_values::range_of_expr (irange &r, tree expr, gimple *stmt)
{
if (!gimple_range_ssa_p (expr))
- return get_tree_range (r, expr);
+ return get_tree_range (r, expr, stmt);
if (const value_range *vr = get_value_range (expr, stmt))
{