public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aldyh/heads/ranger-staging)] One valuation class to rule them all.
@ 2020-08-21 18:11 Aldy Hernandez
0 siblings, 0 replies; only message in thread
From: Aldy Hernandez @ 2020-08-21 18:11 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:08ba3b773f9fdb303e6f789f71dc3c1628b401a1
commit 08ba3b773f9fdb303e6f789f71dc3c1628b401a1
Author: Aldy Hernandez <aldyh@redhat.com>
Date: Fri Aug 21 19:26:34 2020 +0200
One valuation class to rule them all.
Diff:
---
gcc/gimple-loop-versioning.cc | 28 +++++--
gcc/gimple-range-trace.h | 8 +-
gcc/gimple-range.cc | 48 +-----------
gcc/gimple-range.h | 15 ++--
gcc/gimple-ssa-evrp.c | 172 +++++++++++++++++++++++-------------------
gcc/tree-ssa-ccp.c | 41 +++++++---
gcc/tree-ssa-copy.c | 29 ++++---
gcc/tree-ssa-propagate.c | 24 +++---
gcc/tree-ssa-propagate.h | 11 ++-
gcc/tree-vrp.c | 17 +----
gcc/value-range-equiv.cc | 29 +++++++
gcc/value-range.cc | 44 +++++++++++
gcc/value-range.h | 32 ++++++++
gcc/vr-values.c | 77 ++++++++++++-------
gcc/vr-values.h | 40 +++-------
15 files changed, 361 insertions(+), 254 deletions(-)
diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc
index 002b2a68b96..ed9e45995a4 100644
--- a/gcc/gimple-loop-versioning.cc
+++ b/gcc/gimple-loop-versioning.cc
@@ -271,17 +271,27 @@ private:
evrp_range_analyzer m_range_analyzer;
};
+ class valuation : public valuation_query
+ {
+ public:
+ valuation (loop_info *li) : m_li (li) { }
+ private:
+ bool value_of_expr (tree &, tree name, gimple *) FINAL OVERRIDE;
+ loop_info *m_li;
+ };
+
/* Used to simplify statements based on conditions that are established
by the version checks. */
class name_prop : public substitute_and_fold_engine
{
public:
- name_prop (loop_info &li) : m_li (li) {}
- tree get_value (tree, gimple *) FINAL OVERRIDE;
+ name_prop (loop_info &li)
+ : substitute_and_fold_engine (&m_query), m_li (li), m_query (&m_li) {}
private:
/* Information about the versioning we've performed on the loop. */
loop_info &m_li;
+ valuation m_query;
};
loop_info &get_loop_info (class loop *loop) { return m_loops[loop->num]; }
@@ -533,14 +543,16 @@ loop_versioning::lv_dom_walker::after_dom_children (basic_block bb)
/* Decide whether to replace VAL with a new value in a versioned loop.
Return the new value if so, otherwise return null. */
-tree
-loop_versioning::name_prop::get_value (tree val,
- gimple *stmt ATTRIBUTE_UNUSED)
+bool
+loop_versioning::valuation::value_of_expr (tree &t, tree val, gimple *)
{
if (TREE_CODE (val) == SSA_NAME
- && bitmap_bit_p (&m_li.unity_names, SSA_NAME_VERSION (val)))
- return build_one_cst (TREE_TYPE (val));
- return NULL_TREE;
+ && bitmap_bit_p (&m_li->unity_names, SSA_NAME_VERSION (val)))
+ {
+ t = build_one_cst (TREE_TYPE (val));
+ return true;
+ }
+ return false;
}
/* Initialize the structure to optimize FN. */
diff --git a/gcc/gimple-range-trace.h b/gcc/gimple-range-trace.h
index 0b630f53081..e6987fbd103 100644
--- a/gcc/gimple-range-trace.h
+++ b/gcc/gimple-range-trace.h
@@ -4,7 +4,7 @@ public:
trace_ranger (bool use_loop_info);
virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
virtual bool range_of_expr (irange &r, tree name, gimple *s = NULL);
- virtual void range_on_edge (irange &r, edge e, tree name);
+ virtual bool range_on_edge (irange &r, edge e, tree name);
virtual void range_on_entry (irange &r, basic_block bb, tree name);
virtual void range_on_exit (irange &r, basic_block bb, tree name);
private:
@@ -81,7 +81,7 @@ trace_ranger::trailer (unsigned counter, const char *caller, bool result,
// Tracing version of range_on_edge. Call it with printing wrappers.
-void
+bool
trace_ranger::range_on_edge (irange &r, edge e, tree name)
{
unsigned idx = ++trace_count;
@@ -93,9 +93,9 @@ trace_ranger::range_on_edge (irange &r, edge e, tree name)
indent += bump;
}
- gimple_ranger::range_on_edge (r, e, name);
-
+ bool res = gimple_ranger::range_on_edge (r, e, name);
trailer (idx, "range_on_edge", true, name, r);
+ return res;
}
// Tracing version of range_on_entry. Call it with printing wrappers.
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 6574d997811..bd1e4a438c2 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -910,7 +910,7 @@ 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.
-void
+bool
gimple_ranger::range_on_edge (irange &r, edge e, tree name)
{
widest_irange edge_range;
@@ -920,7 +920,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
if (!gimple_range_ssa_p (name))
{
gcc_assert (range_of_expr (r, name));
- return;
+ return true;
}
range_on_exit (r, e->src, name);
@@ -937,6 +937,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name)
if (range_with_loop_info (loop_range, name))
r.intersect (loop_range);
}
+ return true;
}
// Calculate a range for statement S and return it in R. If NAME is
@@ -1111,54 +1112,13 @@ gimple_ranger::dump (FILE *f)
}
}
-// Bridge to provide a get_value_range() to range_of_var_in_loop.
-// As an alternative, gimple_ranger could inherit from range_query and
-// provide get_value_range, thus rendering this class unnecessary.
-
-class range_query_bridge : public range_query
-{
-public:
- range_query_bridge (gimple_ranger *ranger)
- : range_pool ("range_query_bridge range pool"),
- ranger (ranger) { }
- ~range_query_bridge ()
- {
- range_pool.release ();
- }
- const value_range_equiv *get_value_range (const_tree expr,
- gimple *stmt) OVERRIDE
- {
- widest_irange r;
- if (ranger->range_of_expr (r, const_cast<tree> (expr), stmt))
- return new (range_pool.allocate ()) value_range_equiv (r);
- return new (range_pool.allocate ()) value_range_equiv (TREE_TYPE (expr));
- }
-private:
- object_allocator<value_range_equiv> range_pool;
- gimple_ranger *ranger;
-};
-
-gimple_ranger::gimple_ranger (bool use_loop_info)
-{
- if (use_loop_info)
- m_range_query = new range_query_bridge (this);
- else
- m_range_query = NULL;
-}
-
-gimple_ranger::~gimple_ranger ()
-{
- if (loop_aware_p ())
- delete m_range_query;
-}
-
void
gimple_ranger::range_of_ssa_name_with_loop_info (irange &r, tree name,
class loop *l, gphi *phi)
{
gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
tree min, max, type = TREE_TYPE (name);
- if (bounds_of_var_in_loop (&min, &max, m_range_query, l, phi, name))
+ if (bounds_of_var_in_loop (&min, &max, this, l, phi, name))
{
// ?? We could do better here. Since MIN/MAX can only be an
// SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index d5517753ac4..5e301bc0827 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -42,14 +42,13 @@ along with GCC; see the file COPYING3. If not see
// related methods return whatever the current global value is.
-class gimple_ranger
+class gimple_ranger : public valuation_query
{
public:
- gimple_ranger (bool use_loop_info);
- ~gimple_ranger ();
- virtual bool range_of_stmt (irange &r, gimple *s, tree name = NULL_TREE);
- virtual bool range_of_expr (irange &r, tree name, gimple *stmt = NULL);
- virtual void range_on_edge (irange &r, edge e, tree name);
+ gimple_ranger (bool use_loop_info) : m_use_loop_info (use_loop_info) { }
+ 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;
virtual void range_on_entry (irange &r, basic_block bb, tree name);
virtual void range_on_exit (irange &r, basic_block bb, tree name);
void export_global_ranges ();
@@ -68,9 +67,9 @@ private:
bool range_with_loop_info (irange &r, tree name);
void range_of_ssa_name_with_loop_info (irange &, tree, class loop *,
gphi *);
- bool loop_aware_p () { return m_range_query != NULL; }
+ bool loop_aware_p () { return m_use_loop_info; }
- class range_query *m_range_query;
+ bool m_use_loop_info;
};
// Calculate a basic range for a tree expression.
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 75cdf80b1af..f61d6e9ca03 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -47,10 +47,13 @@ along with GCC; see the file COPYING3. If not see
class evrp_folder : public substitute_and_fold_engine
{
public:
- evrp_folder () : m_range_analyzer (/*update_global_ranges=*/true),
+ evrp_folder () :
+ substitute_and_fold_engine (),
+ m_range_analyzer (/*update_global_ranges=*/true),
m_vr_values (m_range_analyzer.get_vr_values ()),
simplifier (m_vr_values)
{
+ set_valuation_query (m_vr_values);
}
~evrp_folder ()
@@ -63,11 +66,6 @@ public:
}
}
- tree get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED) OVERRIDE
- {
- return m_vr_values->op_with_constant_singleton_value_range (op);
- }
-
void pre_fold_bb (basic_block bb) OVERRIDE
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -111,33 +109,17 @@ private:
// RVRP pass implementation using ranger.
-class rvrp_ranger : public range_query
+class rvrp_ranger : public gimple_ranger
{
public:
- rvrp_ranger ()
- : query (/*use_loop_info=*/true),
- range_pool ("rvrp value range pool") { }
- ~rvrp_ranger ()
+ rvrp_ranger (bool changes) :
+ gimple_ranger (/*use_loop_info=*/true),
+ allow_il_changes (changes)
+ { }
+
+ virtual bool value_of_expr (tree &t, tree name, gimple *stmt) OVERRIDE
{
- range_pool.release ();
- }
- // This is the range getter for the simplifier, but is really only
- // used for the conditional folding which still uses equivalences.
- virtual const value_range_equiv *get_value_range (const_tree expr,
- gimple *stmt)
- {
- widest_irange r;
- if (query.range_of_expr (r, const_cast<tree> (expr), stmt))
- return new (range_pool.allocate ()) value_range_equiv (r);
- return new (range_pool.allocate ()) value_range_equiv (TREE_TYPE (expr));
- }
- tree singleton_p (tree op, gimple *stmt)
- {
- widest_irange r;
- tree singleton;
- if (query.range_of_expr (r, op, stmt) && r.singleton_p (&singleton))
- return singleton;
- return NULL_TREE;
+ return gimple_ranger::value_of_expr (t, name, stmt) && allow_il_changes;
}
bool fold_cond (gcond *cond)
@@ -146,7 +128,7 @@ public:
return false;
widest_irange r;
- if (query.range_of_stmt (r, cond) && r.singleton_p ())
+ if (range_of_stmt (r, cond) && r.singleton_p () && allow_il_changes)
{
if (r.zero_p ())
gimple_cond_make_false (cond);
@@ -157,9 +139,8 @@ public:
return false;
}
- gimple_ranger query;
private:
- object_allocator<value_range_equiv> range_pool;
+ bool allow_il_changes;
};
class rvrp_folder : public substitute_and_fold_engine
@@ -167,21 +148,16 @@ class rvrp_folder : public substitute_and_fold_engine
public:
rvrp_ranger ranger;
- rvrp_folder (bool allow_il_changes)
- : ranger (), simplifier (&ranger), allow_il_changes (allow_il_changes) { }
+ rvrp_folder (bool allow_il_changes) :
+ substitute_and_fold_engine (&ranger),
+ ranger (allow_il_changes),
+ simplifier (&ranger),
+ allow_il_changes (allow_il_changes) { }
~rvrp_folder ()
{
if (dump_file && (dump_flags & TDF_DETAILS))
- ranger.query.dump (dump_file);
- }
-
- tree get_value (tree op, gimple *stmt) OVERRIDE
- {
- tree result = ranger.singleton_p (op, stmt);
- if (allow_il_changes && result)
- return result;
- return NULL_TREE;
+ ranger.dump (dump_file);
}
bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
@@ -198,42 +174,36 @@ private:
bool allow_il_changes;
};
-
-class hybrid_folder : public substitute_and_fold_engine
+class hybrid_ranger : public rvrp_ranger
{
public:
- hybrid_folder () : evrp_try_first (flag_evrp_mode == EVRP_MODE_EVRP_FIRST),
- m_range_analyzer (true), m_vr_values (m_range_analyzer.get_vr_values ()),
- simplifier (m_vr_values)
- {
- }
-
- ~hybrid_folder ()
- {
- if (dump_file)
- {
- fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
- m_range_analyzer.dump_all_value_ranges (dump_file);
- fprintf (dump_file, "\n");
- }
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- ranger.query.dump (dump_file);
- }
+ hybrid_ranger (vr_values *v) :
+ rvrp_ranger (/*allow_il_changes=*/true),
+ m_vr_values (v) { }
- tree get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED) OVERRIDE
+ bool value_of_expr (tree &t, tree op, gimple *stmt) OVERRIDE
{
tree e_ret = m_vr_values->op_with_constant_singleton_value_range (op);
- tree r_ret = ranger.singleton_p (op, stmt);
+ tree r_ret = singleton_p (op, stmt);
if (e_ret == r_ret)
- return e_ret;
+ {
+ if (e_ret)
+ {
+ t = e_ret;
+ return true;
+ }
+ return false;
+ }
// if the values are the same, return.
if (e_ret && r_ret && !compare_values (e_ret, r_ret))
- return e_ret;
+ {
+ t = e_ret;
+ return true;
+ }
- // Shouldnt get DIFFERENT singletons ever, so one should be NULL
+ // We should never get different singletons.
gcc_checking_assert (!e_ret || !r_ret);
if (e_ret)
{
@@ -243,7 +213,8 @@ public:
print_generic_expr (dump_file, e_ret);
fprintf (dump_file, "\n");
}
- return e_ret;
+ t = e_ret;
+ return true;
}
if (dump_file)
{
@@ -251,7 +222,47 @@ public:
print_generic_expr (dump_file, r_ret);
fprintf (dump_file, "\n");
}
- return r_ret;
+ return false;
+ }
+
+private:
+ tree singleton_p (tree op, gimple *stmt)
+ {
+ widest_irange r;
+ tree singleton;
+ if (range_of_expr (r, op, stmt) && r.singleton_p (&singleton))
+ return singleton;
+ return NULL_TREE;
+ }
+
+ vr_values *m_vr_values;
+};
+
+class hybrid_folder : public substitute_and_fold_engine
+{
+public:
+ hybrid_folder () :
+ substitute_and_fold_engine (),
+ evrp_try_first (flag_evrp_mode == EVRP_MODE_EVRP_FIRST),
+ m_range_analyzer (true),
+ m_vr_values (m_range_analyzer.get_vr_values ()),
+ ranger (m_vr_values),
+ simplifier (m_vr_values)
+ {
+ set_valuation_query (m_vr_values);
+ }
+
+ ~hybrid_folder ()
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
+ m_range_analyzer.dump_all_value_ranges (dump_file);
+ fprintf (dump_file, "\n");
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ ranger.dump (dump_file);
}
void pre_fold_bb (basic_block bb) OVERRIDE
@@ -276,11 +287,11 @@ public:
gcond *cond = dyn_cast <gcond *> (gsi_stmt (*gsi));
if (evrp_try_first)
{
- simplifier.set_range_query (m_vr_values);
+ simplifier.set_valuation_query (m_vr_values);
if (simplifier.simplify (gsi))
return true;
- simplifier.set_range_query (&ranger);
+ simplifier.set_valuation_query (&ranger);
if (cond && ranger.fold_cond (cond))
{
if (dump_file)
@@ -296,13 +307,13 @@ public:
return false;
}
- simplifier.set_range_query (&ranger);
+ simplifier.set_valuation_query (&ranger);
if (cond && ranger.fold_cond (cond))
return true;
if (simplifier.simplify (gsi))
return true;
- simplifier.set_range_query (m_vr_values);
+ simplifier.set_valuation_query (m_vr_values);
if (simplifier.simplify (gsi))
{
if (dump_file)
@@ -323,12 +334,11 @@ public:
}
private:
- bool evrp_try_first;
- rvrp_ranger ranger;
DISABLE_COPY_AND_ASSIGN (hybrid_folder);
+ bool evrp_try_first;
class evrp_range_analyzer m_range_analyzer;
class vr_values *m_vr_values;
-
+ hybrid_ranger ranger;
simplify_using_ranges simplifier;
};
@@ -354,6 +364,12 @@ execute_early_vrp ()
{
case EVRP_MODE_EVRP_ONLY:
{
+ /* ?? We could do:
+ evrp_range_analyzer range_analyzer;
+ evrp_folder folder (range_analyzer);
+ And then we wouldn't need we could instantiate
+ substitute_and_fold_engine with the correct vr_values
+ instead of calling set_valuation_query. */
evrp_folder folder;
folder.substitute_and_fold ();
break;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 65dffe06530..d3137596896 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -941,25 +941,42 @@ do_dbg_cnt (void)
}
}
+class ccp_valuation : public valuation_query
+{
+ /* This method just wraps GET_CONSTANT_VALUE for now. Over time
+ naked calls to GET_CONSTANT_VALUE should be eliminated in favor
+ of calling member functions. */
+ bool value_of_expr (tree &t, tree name, gimple *) OVERRIDE
+ {
+ t = get_constant_value (name);
+ return t != NULL;
+ }
+
+ virtual bool range_of_expr (irange &r, tree name, gimple *stmt) OVERRIDE
+ {
+ tree t;
+ if (value_of_expr (t, name, stmt))
+ {
+ if (TREE_CODE (t) == INTEGER_CST)
+ r.set (t, t);
+ else
+ r.set_varying (TREE_TYPE (name));
+ return true;
+ }
+ return false;
+ }
+};
/* We want to provide our own GET_VALUE and FOLD_STMT virtual methods. */
class ccp_folder : public substitute_and_fold_engine
{
- public:
- tree get_value (tree, gimple *) FINAL OVERRIDE;
+public:
+ ccp_folder () : substitute_and_fold_engine (&m_query) { }
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
+private:
+ ccp_valuation m_query;
};
-/* This method just wraps GET_CONSTANT_VALUE for now. Over time
- naked calls to GET_CONSTANT_VALUE should be eliminated in favor
- of calling member functions. */
-
-tree
-ccp_folder::get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED)
-{
- return get_constant_value (op);
-}
-
/* Do final substitution of propagated values, cleanup the flowgraph and
free allocated storage. If NONZERO_P, record nonzero bits.
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 9bcb708379e..8e4a6a03a9e 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -489,25 +489,24 @@ init_copy_prop (void)
}
}
-class copy_folder : public substitute_and_fold_engine
+class copy_valuation : public valuation_query
{
- public:
- tree get_value (tree, gimple *) FINAL OVERRIDE;
+ bool value_of_expr (tree &val, tree name, gimple *) FINAL OVERRIDE
+ {
+ if (SSA_NAME_VERSION (name) >= n_copy_of)
+ return false;
+ val = copy_of[SSA_NAME_VERSION (name)].value;
+ return val && val != name;
+ }
};
-/* Callback for substitute_and_fold to get at the final copy-of values. */
-
-tree
-copy_folder::get_value (tree name, gimple *stmt ATTRIBUTE_UNUSED)
+class copy_folder : public substitute_and_fold_engine
{
- tree val;
- if (SSA_NAME_VERSION (name) >= n_copy_of)
- return NULL_TREE;
- val = copy_of[SSA_NAME_VERSION (name)].value;
- if (val && val != name)
- return val;
- return NULL_TREE;
-}
+public:
+ copy_folder () : substitute_and_fold_engine (&m_query) { }
+private:
+ copy_valuation m_query;
+};
/* Deallocate memory used in copy propagation and do final
substitution. */
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 1e057284154..bbd66aab11e 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -868,9 +868,9 @@ substitute_and_fold_engine::replace_uses_in (gimple *stmt)
FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
tree tuse = USE_FROM_PTR (use);
- tree val = get_value (tuse, stmt);
+ tree val;
- if (val == tuse || val == NULL_TREE)
+ if (!query->value_of_expr (val, tuse, stmt) || val == tuse)
continue;
if (gimple_code (stmt) == GIMPLE_ASM
@@ -909,9 +909,9 @@ substitute_and_fold_engine::replace_phi_args_in (gphi *phi)
if (TREE_CODE (arg) == SSA_NAME)
{
- tree val = get_value (arg, phi);
-
- if (val && val != arg && may_propagate_copy (arg, val))
+ tree val;
+ if (query->value_of_expr (val, arg, phi)
+ && val != arg && may_propagate_copy (arg, val))
{
edge e = gimple_phi_arg_edge (phi, i);
@@ -1036,8 +1036,8 @@ substitute_and_fold_engine::propagate_into_phi_args (basic_block bb)
if (TREE_CODE (arg) != SSA_NAME
|| virtual_operand_p (arg))
continue;
- tree val = get_value (arg, phi);
- if (val
+ tree val;
+ if (query->value_of_expr (val, arg, phi)
&& is_gimple_min_invariant (val)
&& may_propagate_copy (arg, val))
{
@@ -1070,8 +1070,9 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
}
if (res && TREE_CODE (res) == SSA_NAME)
{
- tree sprime = substitute_and_fold_engine->get_value (res, phi);
- if (sprime
+ tree sprime;
+ if (substitute_and_fold_engine->query->value_of_expr (sprime,
+ res, phi)
&& sprime != res
&& may_propagate_copy (res, sprime))
{
@@ -1110,8 +1111,9 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
tree lhs = gimple_get_lhs (stmt);
if (lhs && TREE_CODE (lhs) == SSA_NAME)
{
- tree sprime = substitute_and_fold_engine->get_value (lhs, stmt);
- if (sprime
+ tree sprime;
+ if (substitute_and_fold_engine->query->value_of_expr (sprime,
+ lhs, stmt)
&& sprime != lhs
&& may_propagate_copy (lhs, sprime)
&& !stmt_could_throw_p (cfun, stmt)
diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
index 9406cdf8f51..fa6e971c409 100644
--- a/gcc/tree-ssa-propagate.h
+++ b/gcc/tree-ssa-propagate.h
@@ -100,11 +100,16 @@ class ssa_propagation_engine
class substitute_and_fold_engine
{
public:
+ /* If query is unset here, it must be initialized with
+ set_valuation_query instead. */
substitute_and_fold_engine (bool fold_all_stmts = false)
- : fold_all_stmts (fold_all_stmts) { }
+ : fold_all_stmts (fold_all_stmts), query (NULL) { }
+ substitute_and_fold_engine (class valuation_query *query,
+ bool fold_all_stmts = false)
+ : fold_all_stmts (fold_all_stmts), query (query) { }
+ void set_valuation_query (class valuation_query *q) { query = q; }
virtual ~substitute_and_fold_engine (void) { }
virtual bool fold_stmt (gimple_stmt_iterator *) { return false; }
- virtual tree get_value (tree, gimple *) { return NULL_TREE; }
bool substitute_and_fold (basic_block = NULL);
bool replace_uses_in (gimple *);
@@ -120,6 +125,8 @@ class substitute_and_fold_engine
/* Users like VRP can set this when they want to perform
folding for every propagation. */
bool fold_all_stmts;
+
+ class valuation_query *query;
};
#endif /* _TREE_SSA_PROPAGATE_H */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index de84c1d505d..4bcc8c5caa4 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3948,10 +3948,9 @@ class vrp_folder : public substitute_and_fold_engine
{
public:
vrp_folder (vr_values *v)
- : substitute_and_fold_engine (/* Fold all stmts. */ true),
+ : substitute_and_fold_engine (v, /* Fold all stmts. */ true),
m_vr_values (v), simplifier (v)
{ }
- tree get_value (tree, gimple *stmt) FINAL OVERRIDE;
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
class vr_values *m_vr_values;
@@ -3964,8 +3963,6 @@ private:
{ return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
{ return simplifier.simplify (gsi); }
- tree op_with_constant_singleton_value_range (tree op)
- { return m_vr_values->op_with_constant_singleton_value_range (op); }
simplify_using_ranges simplifier;
};
@@ -4043,18 +4040,6 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si)
return simplify_stmt_using_ranges (si);
}
-/* If OP has a value range with a single constant value return that,
- otherwise return NULL_TREE. This returns OP itself if OP is a
- constant.
-
- Implemented as a pure wrapper right now, but this will change. */
-
-tree
-vrp_folder::get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED)
-{
- return op_with_constant_singleton_value_range (op);
-}
-
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
BB. If no such ASSERT_EXPR is found, return OP. */
diff --git a/gcc/value-range-equiv.cc b/gcc/value-range-equiv.cc
index 7dc10b876e0..86177082dff 100644
--- a/gcc/value-range-equiv.cc
+++ b/gcc/value-range-equiv.cc
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "ssa.h"
#include "tree-pretty-print.h"
#include "value-range-equiv.h"
+#include "alloc-pool.h"
value_range_equiv::value_range_equiv (tree min, tree max, bitmap equiv,
value_range_kind kind)
@@ -322,3 +323,31 @@ debug (const value_range_equiv &vr)
{
dump_value_range (stderr, &vr);
}
+
+// valuation_query support routines for value_range_equiv's.
+
+class equiv_allocator : public object_allocator<value_range_equiv>
+{
+public:
+ equiv_allocator ()
+ : object_allocator<value_range_equiv> ("equiv_allocator pool") { }
+};
+
+const class value_range_equiv *
+valuation_query::get_value_range (const_tree expr, gimple *stmt)
+{
+ widest_irange r;
+ if (range_of_expr (r, const_cast<tree> (expr), stmt))
+ return new (equiv_pool->allocate ()) value_range_equiv (r);
+ return new (equiv_pool->allocate ()) value_range_equiv (TREE_TYPE (expr));
+}
+
+valuation_query::valuation_query ()
+{
+ equiv_pool = new equiv_allocator;
+}
+
+valuation_query::~valuation_query ()
+{
+ equiv_pool->release ();
+}
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 93164b7e2e2..21fd30d53ed 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2048,6 +2048,50 @@ vrp_operand_equal_p (const_tree val1, const_tree val2)
return true;
}
+// Default definitions for valuation_query methods.
+
+bool
+valuation_query::range_of_expr (irange &, tree, gimple *)
+{
+ return false;
+}
+
+bool
+valuation_query::range_on_edge (irange &r, edge, tree name)
+{
+ return range_of_expr (r, name);
+}
+
+bool
+valuation_query::range_of_stmt (irange &r, gimple *, tree name)
+{
+ if (name)
+ return range_of_expr (r, name);
+ return false;
+}
+
+bool
+valuation_query::value_of_expr (tree &t, tree name, gimple *stmt)
+{
+ widest_irange r;
+ return range_of_expr (r, name, stmt) && r.singleton_p (&t);
+}
+
+bool
+valuation_query::value_on_edge (tree &t, edge e, tree name)
+{
+ widest_irange r;
+ return range_on_edge (r, e, name) && r.singleton_p (&t);
+}
+
+bool
+valuation_query::value_of_stmt (tree &t, gimple *stmt, tree name)
+{
+ widest_irange r;
+ return range_of_stmt (r, stmt, name) && r.singleton_p (&t);
+}
+
+
#define DEFINE_INT_RANGE_GC_STUBS(N) \
void \
gt_pch_nx (int_range<N> *&x) \
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 8ae6d9c10e3..54b8cb3c204 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -673,4 +673,36 @@ irange_pool::allocate (const irange &src)
return r;
}
+// The bare minimum that must be implemented for this class is
+// range_of_expr. However, the VRP twins also provide their own
+// value_of_expr because the substitute_and_fold_engine may use this
+// method and expect a non-constant (is_gimple_min_invariant may
+// return an ADDR_EXPR).
+//
+// It would be interesting to see if using the default value_of_expr
+// causes any regressions for users of the substitute_and_fold_engine.
+
+class valuation_query
+{
+public:
+ valuation_query ();
+ virtual ~valuation_query ();
+
+ virtual bool range_of_expr (irange &, tree name, gimple * = NULL);
+ virtual bool range_on_edge (irange &, edge, tree name);
+ virtual bool range_of_stmt (irange &, gimple *, tree name = NULL);
+
+ virtual bool value_of_expr (tree &, tree name, gimple * = NULL);
+ virtual bool value_on_edge (tree &, edge, tree name);
+ virtual bool value_of_stmt (tree &, gimple *, tree name = NULL);
+
+ // DEPRECATED: This method is used from vr-values. The plan is to
+ // rewrite all uses of it to the above API.
+ virtual const class value_range_equiv *get_value_range (const_tree,
+ gimple * = NULL);
+
+private:
+ class equiv_allocator *equiv_pool;
+};
+
#endif // GCC_VALUE_RANGE_H
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 6a2c0a51ce6..cf8243d8adc 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -173,6 +173,27 @@ vr_values::get_value_range (const_tree var,
return vr;
}
+bool
+vr_values::range_of_expr (irange &r, tree name, gimple *stmt)
+{
+ if (const value_range *vr = get_value_range (name, stmt))
+ {
+ if (vr->symbolic_p ())
+ r.set_varying (TREE_TYPE (name));
+ else
+ r = *vr;
+ return true;
+ }
+ return false;
+}
+
+bool
+vr_values::value_of_expr (tree &t, tree op, gimple *)
+{
+ t = op_with_constant_singleton_value_range (op);
+ return t != NULL;
+}
+
/* Set the lattice entry for DEF to VARYING. */
void
@@ -451,7 +472,7 @@ simplify_using_ranges::op_with_boolean_value_range_p (tree op)
/* ?? Errr, this should probably check for [0,0] and [1,1] as well
as [0,1]. */
- const value_range *vr = get_value_range (op);
+ const value_range *vr = query->get_value_range (op);
return *vr == value_range (build_zero_cst (TREE_TYPE (op)),
build_one_cst (TREE_TYPE (op)));
}
@@ -1006,20 +1027,20 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
overflow. */
static bool
-check_for_binary_op_overflow (range_query *store,
+check_for_binary_op_overflow (valuation_query *query,
enum tree_code subcode, tree type,
tree op0, tree op1, bool *ovf)
{
value_range vr0, vr1;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *store->get_value_range (op0);
+ vr0 = *query->get_value_range (op0);
else if (TREE_CODE (op0) == INTEGER_CST)
vr0.set (op0);
else
vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
- vr1 = *store->get_value_range (op1);
+ vr1 = *query->get_value_range (op1);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
@@ -1742,7 +1763,7 @@ compare_range_with_value (enum tree_code comp, const value_range *vr,
could be determined, return FALSE. */
bool
-bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
+bounds_of_var_in_loop (tree *min, tree *max, valuation_query *query,
class loop *loop, gimple *stmt, tree var)
{
tree init, step, chrec, tmin, tmax, type = TREE_TYPE (var);
@@ -2092,7 +2113,7 @@ const value_range_equiv *
simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem)
{
/* Shallow-copy equiv bitmap. */
- const value_range_equiv *vr = get_value_range (ssa_name (i));
+ const value_range_equiv *vr = query->get_value_range (ssa_name (i));
/* If name N_i does not have a valid range, use N_i as its own
range. This allows us to compare against names that may
@@ -2117,7 +2138,7 @@ simplify_using_ranges::compare_name_with_value
bool *strict_overflow_p, bool use_equiv_p)
{
/* Get the set of equivalences for VAR. */
- bitmap e = get_value_range (var)->equiv ();
+ bitmap e = query->get_value_range (var)->equiv ();
/* Start at -1. Set it to 0 if we do a comparison without relying
on overflow, or 1 if all comparisons rely on overflow. */
@@ -2197,8 +2218,8 @@ simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
{
/* Compare the ranges of every name equivalent to N1 against the
ranges of every name equivalent to N2. */
- bitmap e1 = get_value_range (n1)->equiv ();
- bitmap e2 = get_value_range (n2)->equiv ();
+ bitmap e1 = query->get_value_range (n1)->equiv ();
+ bitmap e2 = query->get_value_range (n2)->equiv ();
/* Use the fake bitmaps if e1 or e2 are not available. */
static bitmap s_e1 = NULL, s_e2 = NULL;
@@ -2310,8 +2331,8 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges
(enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
{
const value_range_equiv *vr0, *vr1;
- vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
- vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
+ vr0 = (TREE_CODE (op0) == SSA_NAME) ? query->get_value_range (op0) : NULL;
+ vr1 = (TREE_CODE (op1) == SSA_NAME) ? query->get_value_range (op1) : NULL;
tree res = NULL_TREE;
if (vr0 && vr1)
@@ -2390,7 +2411,7 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
}
else
gcc_unreachable ();
- const value_range_equiv *vr0 = get_value_range (op0, stmt);
+ const value_range_equiv *vr0 = query->get_value_range (op0, stmt);
/* If vro, the range for OP0 to pass the overflow test, has
no intersection with *vr0, OP0's known range, then the
overflow test can't pass, so return the node for false.
@@ -2496,7 +2517,7 @@ simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0,
always fold regardless of the value of OP0. If -Wtype-limits
was specified, emit a warning. */
tree type = TREE_TYPE (op0);
- const value_range_equiv *vr0 = get_value_range (op0, stmt);
+ const value_range_equiv *vr0 = query->get_value_range (op0, stmt);
if (vr0->varying_p ()
&& INTEGRAL_TYPE_P (type)
@@ -2547,7 +2568,7 @@ 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, get_value_range (use, stmt));
+ dump_value_range (dump_file, query->get_value_range (use, stmt));
}
fprintf (dump_file, "\n");
@@ -3123,7 +3144,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges
}
else
{
- vr = get_value_range (op0, stmt);
+ vr = query->get_value_range (op0, stmt);
if (range_int_cst_p (vr))
{
op0min = vr->min ();
@@ -3134,7 +3155,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges
if (rhs_code == TRUNC_MOD_EXPR
&& TREE_CODE (op1) == SSA_NAME)
{
- const value_range_equiv *vr1 = get_value_range (op1, stmt);
+ const value_range_equiv *vr1 = query->get_value_range (op1, stmt);
if (range_int_cst_p (vr1))
op1min = vr1->min ();
}
@@ -3283,7 +3304,7 @@ simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{
tree op = gimple_assign_rhs1 (stmt);
- const value_range *vr = get_value_range (op, stmt);
+ const value_range *vr = query->get_value_range (op, stmt);
if (vr)
{
@@ -3373,14 +3394,14 @@ simplify_using_ranges::simplify_bit_ops_using_ranges
wide_int mask;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *(get_value_range (op0, stmt));
+ vr0 = *(query->get_value_range (op0, stmt));
else if (is_gimple_min_invariant (op0))
vr0.set (op0);
else
return false;
if (TREE_CODE (op1) == SSA_NAME)
- vr1 = *(get_value_range (op1, stmt));
+ vr1 = *(query->get_value_range (op1, stmt));
else if (is_gimple_min_invariant (op1))
vr1.set (op1);
else
@@ -3599,7 +3620,7 @@ simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
&& INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& is_gimple_min_invariant (op1))
{
- const value_range *vr = get_value_range (op0, stmt);
+ const value_range *vr = query->get_value_range (op0, stmt);
/* If we have range information for OP0, then we might be
able to simplify this conditional. */
@@ -3672,7 +3693,7 @@ simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
subsequent passes. */
void
-simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
+simplify_cond_using_ranges_2 (vr_values *query, gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -3702,7 +3723,7 @@ simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
&& desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
{
- const value_range *vr = store->get_value_range (innerop);
+ const value_range *vr = query->get_value_range (innerop);
if (range_int_cst_p (vr)
&& range_fits_type_p (vr,
@@ -3743,7 +3764,7 @@ simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
if (TREE_CODE (op) == SSA_NAME)
{
- vr = get_value_range (op, stmt);
+ vr = query->get_value_range (op, stmt);
/* We can only handle integer ranges. */
if (vr->varying_p ()
@@ -4036,7 +4057,7 @@ simplify_using_ranges::simplify_float_conversion_using_ranges
gimple *stmt)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- const value_range *vr = get_value_range (rhs1, stmt);
+ const value_range *vr = query->get_value_range (rhs1, stmt);
scalar_float_mode fltmode
= SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
scalar_int_mode mode;
@@ -4141,7 +4162,7 @@ simplify_using_ranges::simplify_internal_call_using_ranges
return false;
else
type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
- if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf)
+ if (!check_for_binary_op_overflow (query, subcode, type, op0, op1, &ovf)
|| (is_ubsan && ovf))
return false;
@@ -4200,7 +4221,7 @@ simplify_using_ranges::simplify_internal_call_using_ranges
bool
simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
{
- value_range vr = *get_value_range (var);
+ value_range vr = *query->get_value_range (var);
vr.normalize_symbolics ();
if (vr.varying_p () || vr.undefined_p ())
return false;
@@ -4217,8 +4238,8 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
return false;
}
-simplify_using_ranges::simplify_using_ranges (range_query *store)
- : store (store)
+simplify_using_ranges::simplify_using_ranges (valuation_query *query)
+ : query (query)
{
to_remove_edges = vNULL;
to_update_switch_stmts = vNULL;
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 4357f75fb88..579f3a62847 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -24,26 +24,14 @@ along with GCC; see the file COPYING3. If not see
// Abstract class to return a range for a given SSA.
-class range_query
-{
-public:
- virtual const value_range_equiv *get_value_range (const_tree,
- gimple * = NULL) = 0;
- virtual ~range_query () { }
-};
-
// Class to simplify a statement using range information.
-//
-// The constructor takes a full vr_values, but all it needs is
-// get_value_range() from it. This class could be made to work with
-// any range repository.
-class simplify_using_ranges
+class simplify_using_ranges
{
public:
- simplify_using_ranges (class range_query *);
+ simplify_using_ranges (class valuation_query *);
~simplify_using_ranges ();
- void set_range_query (class range_query *);
+ void set_valuation_query (class valuation_query *);
bool simplify (gimple_stmt_iterator *);
@@ -55,7 +43,6 @@ public:
bool *, bool *);
private:
- const value_range_equiv *get_value_range (const_tree op, gimple *stmt = NULL);
bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *);
bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *);
@@ -90,7 +77,7 @@ private:
vec<edge> to_remove_edges;
vec<switch_update> to_update_switch_stmts;
- class range_query *store;
+ class valuation_query *query;
};
/* The VR_VALUES class holds the current view of range information
@@ -107,13 +94,16 @@ private:
gets attached to an SSA_NAME. It's unclear how useful that global
information will be in a world where we can compute context sensitive
range information fast or perform on-demand queries. */
-class vr_values : public range_query
+class vr_values : public valuation_query
{
public:
vr_values (void);
~vr_values (void);
- const value_range_equiv *get_value_range (const_tree, gimple * = NULL);
+ virtual bool value_of_expr (tree &, tree, gimple *) OVERRIDE;
+ bool range_of_expr (irange &r, tree name, gimple *stmt) OVERRIDE;
+ virtual const value_range_equiv *get_value_range (const_tree,
+ gimple * = NULL) OVERRIDE;
void set_vr_value (tree, value_range_equiv *);
value_range_equiv *swap_vr_value (tree, value_range_equiv *);
@@ -178,15 +168,9 @@ class vr_values : public range_query
};
inline void
-simplify_using_ranges::set_range_query (class range_query *query)
-{
- store = query;
-}
-
-inline const value_range_equiv *
-simplify_using_ranges::get_value_range (const_tree op, gimple *stmt)
+simplify_using_ranges::set_valuation_query (class valuation_query *q)
{
- return store->get_value_range (op, stmt);
+ query = q;
}
extern tree get_output_for_vrp (gimple *);
@@ -194,7 +178,7 @@ extern tree get_output_for_vrp (gimple *);
// FIXME: Move this to tree-vrp.c.
void simplify_cond_using_ranges_2 (class vr_values *, gcond *);
-extern bool bounds_of_var_in_loop (tree *min, tree *max, range_query *,
+extern bool bounds_of_var_in_loop (tree *min, tree *max, valuation_query *,
class loop *loop, gimple *stmt, tree var);
#endif /* GCC_VR_VALUES_H */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-08-21 18:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-21 18:11 [gcc(refs/users/aldyh/heads/ranger-staging)] One valuation class to rule them all Aldy Hernandez
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).