aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2020-03-26 09:54:11 +0100
committerAldy Hernandez <aldyh@redhat.com>2020-03-30 14:00:14 +0200
commit5b6d81b17ebf860a9a3ca3945d99514437927c81 (patch)
tree6f6c812ba78d1baf1af9f7305192ea15bc90d4b3 /gcc
parentfde9e8acfb0eaf3e70569e22360f9167b48eb36f (diff)
downloadgcc-5b6d81b17ebf860a9a3ca3945d99514437927c81.zip
gcc-5b6d81b17ebf860a9a3ca3945d99514437927c81.tar.gz
gcc-5b6d81b17ebf860a9a3ca3945d99514437927c81.tar.bz2
New simplify_using_ranges and range_store classes.
simplify_using_ranges class contains the simplication with ranges code. range_store is a class which provides a generic mechanism to get a stored range for an SSA. All goris and vr_values inherit from it.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-gori.cc7
-rw-r--r--gcc/gimple-range-gori.h10
-rw-r--r--gcc/gimple-ssa-evrp-analyze.c170
-rw-r--r--gcc/gimple-ssa-evrp-analyze.h6
-rw-r--r--gcc/gimple-ssa-evrp.c22
-rw-r--r--gcc/tree-ssa-dom.c11
-rw-r--r--gcc/tree-vrp.c37
-rw-r--r--gcc/vr-values.c444
-rw-r--r--gcc/vr-values.h126
9 files changed, 460 insertions, 373 deletions
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 86e0970..f44a6b2 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -481,6 +481,13 @@ debug (gori_map &g)
g.dump (stderr);
}
+const value_range_equiv *
+range_store::get_value_range (const_tree expr ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+ return NULL;
+}
+
// Return the legacy global known value for NAME in R.
void
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 7560542..45aaa24 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -133,11 +133,19 @@ public:
bitmap exports (basic_block bb);
};
+// Generic object to return a range for an SSA.
+class range_store
+{
+public:
+ virtual bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL) = 0;
+ virtual const value_range_equiv *get_value_range (const_tree expr);
+};
+
// This class utilizes a GORI map to determine which SSA_NAMES can
// have ranges calculated for them on outgoing edges from basic
// blocks.
-class gori_compute
+class gori_compute : public range_store
{
public:
gori_compute ();
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 7d9289e..281170a 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -45,6 +45,32 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-range.h"
#include "ssa-range.h"
+class vr_gori_interface : public trace_gori_compute
+{
+public:
+ vr_gori_interface (range_store *store) : store (store) { }
+ virtual bool outgoing_edge_range_p (irange &, edge, tree name,
+ const irange *name_range = NULL);
+ bool gori_computable_p (tree name, basic_block);
+protected:
+ virtual bool refine_range_with_equivalences (irange &, edge, tree name);
+private:
+ virtual void range_of_ssa_name (irange &r, tree op, gimple * = NULL);
+ bool solve_name_at_statement (irange &, tree, gimple *stmt, const irange &);
+ bool solve_name_given_equivalence (irange &r, tree name, tree equiv,
+ const irange &equiv_range);
+ range_store *store;
+};
+
+class trace_vr_gori_interface : public vr_gori_interface
+{
+public:
+ trace_vr_gori_interface (range_store *store) : vr_gori_interface (store) { }
+private:
+ virtual bool refine_range_with_equivalences (irange &, edge, tree name);
+ typedef vr_gori_interface super;
+};
+
evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
: stack (10), m_update_global_ranges (update_global_ranges)
{
@@ -59,6 +85,7 @@ evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
}
vr_values = new class vr_values;
ranger = new global_ranger;
+ gori = new trace_vr_gori_interface (vr_values);
}
evrp_range_analyzer::~evrp_range_analyzer (void)
@@ -66,6 +93,7 @@ evrp_range_analyzer::~evrp_range_analyzer (void)
delete vr_values;
stack.release ();
delete ranger;
+ delete gori;
}
/* Push an unwinding marker onto the unwinding stack. */
@@ -163,6 +191,144 @@ all_uses_feed_or_dominated_by_stmt (tree name, gimple *stmt)
return true;
}
+void
+vr_gori_interface::range_of_ssa_name (irange &r, tree op,
+ gimple *stmt ATTRIBUTE_UNUSED)
+{
+ r = *store->get_value_range (op);
+ r.normalize_symbolics ();
+}
+
+// Return TRUE if NAME is computable by GORI in BB.
+
+bool
+vr_gori_interface::gori_computable_p (tree name, basic_block bb)
+{
+ return m_gori_map.is_export_p (name, bb);
+}
+
+// Calculate the range for NAME on edge E and return it in R.
+// Return FALSE if unable to compute a range.
+
+bool
+vr_gori_interface::outgoing_edge_range_p (irange &r, edge e, tree name,
+ const irange *known_range ATTRIBUTE_UNUSED)
+{
+ if (!gori_compute::outgoing_edge_range_p (r, e, name))
+ r.set_varying (TREE_TYPE (name));
+ if (!r.singleton_p ())
+ refine_range_with_equivalences (r, e, name);
+ widest_irange tmp;
+ range_of_ssa_name (tmp, name);
+ r.intersect (tmp);
+ return !r.varying_p ();
+}
+
+// R is a known range for NAME on edge E. Refine it with any
+// equivalences NAME may have.
+
+bool
+vr_gori_interface::refine_range_with_equivalences (irange &r,
+ edge e, tree name)
+{
+ widest_irange branch_range, tmp;
+ gimple *branch = gimple_outgoing_edge_range_p (branch_range, e);
+ if (!branch)
+ return false;
+
+ // Solve each equivalence and use them to refine the range.
+ bitmap_iterator bi;
+ unsigned i;
+ bitmap gori_exports = m_gori_map.exports (e->src);
+ EXECUTE_IF_SET_IN_BITMAP (gori_exports, 0, i, bi)
+ {
+ tree equiv = ssa_name (i);
+ if (equiv == name)
+ continue;
+ widest_irange equiv_range;
+ if (solve_name_at_statement (equiv_range, equiv, branch, branch_range))
+ {
+ gimple *equiv_def = SSA_NAME_DEF_STMT (equiv);
+ if (!equiv_def->bb
+ || !dominated_by_p (CDI_DOMINATORS, e->src, equiv_def->bb))
+ continue;
+
+ if (solve_name_given_equivalence (tmp, name, equiv, equiv_range))
+ r.intersect (tmp);
+ }
+ }
+ return !r.varying_p ();
+}
+
+// Compute a range for NAME as it would appear in STMT and return it
+// in R. LHS is the known range for STMT.
+
+bool
+vr_gori_interface::solve_name_at_statement (irange &r,
+ tree name, gimple *stmt,
+ const irange &lhs)
+{
+ widest_irange name_range;
+ range_of_ssa_name (name_range, name, stmt);
+ return compute_operand_range (r, stmt, lhs, name, &name_range);
+}
+
+bool
+vr_gori_interface::solve_name_given_equivalence (irange &r,
+ tree name,
+ tree equiv,
+ const irange &equiv_range)
+{
+ // Solve NAME in EQUIV = USE(NAME).
+ gimple *def = SSA_NAME_DEF_STMT (equiv);
+ if (gimple_range_handler (def) && gimple_range_operand1 (def) == name)
+ {
+ widest_irange op2_range;
+ if (tree op2 = gimple_range_operand2 (def))
+ range_of_expr (op2_range, op2, def);
+ else
+ {
+ tree type = TREE_TYPE (gimple_range_operand1 (def));
+ op2_range.set_varying (type);
+ }
+ return gimple_range_calc_op1 (def, r, equiv_range, op2_range);
+ }
+ // Solve NAME in NAME = USE(EQUIV).
+ def = SSA_NAME_DEF_STMT (name);
+ if (gimple_range_handler (def) && gimple_range_operand1 (def) == equiv)
+ {
+ widest_irange op2_range;
+ if (tree op2 = gimple_range_operand2 (def))
+ range_of_expr (op2_range, op2, def);
+ else
+ {
+ tree type = gimple_expr_type (def);
+ op2_range.set_varying (type);
+ }
+ return gimple_range_fold (def, r, equiv_range, op2_range);
+ }
+ return false;
+}
+
+bool
+trace_vr_gori_interface::refine_range_with_equivalences (irange &r,
+ edge e, tree name)
+{
+ unsigned idx = ++trace_count;
+ if (dumping (idx))
+ {
+ fprintf (dump_file, "refine_range_with_equivalences (");
+ print_generic_expr (dump_file, name, TDF_SLIM);
+ fprintf (dump_file, ") on edge %d->%d, with range ",
+ e->src->index, e->dest->index);
+ r.dump (dump_file);
+ fputc ('\n', dump_file);
+ indent += bump;
+ }
+ bool res = super::refine_range_with_equivalences (r, e, name);
+ return trailer (idx, "refine_range_with_equivalences", res, name, r);
+}
+
// Class to assert that gori/ranger provide ranges that are at least
// as good as evrp.
@@ -313,11 +479,11 @@ evrp_range_analyzer::try_find_new_range_for_assert (const assert_info &assert,
widest_irange tmp;
bitmap_iterator bi;
bool gori_can_calculate = (assert.gori_computable_p
- && vr_values->gori_computable_p (name, e->src));
+ && gori->gori_computable_p (name, e->src));
if (gori_can_calculate)
{
- if (!vr_values->outgoing_edge_range_p (vr_gori, e, name))
+ if (!gori->outgoing_edge_range_p (vr_gori, e, name))
vr_gori.set_varying (TREE_TYPE (name));
}
diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index f7cef41..d157191 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -46,7 +46,10 @@ class evrp_range_analyzer
/* A bit of a wart. This should ideally go away. */
void vrp_visit_cond_stmt (gcond *cond, edge *e)
- { return vr_values->vrp_visit_cond_stmt (cond, e); }
+ {
+ simplify_using_ranges simpl (vr_values);
+ simpl.vrp_visit_cond_stmt (cond, e);
+ }
/* Get the underlying vr_values class instance. If TRANSFER is
true, then we are transferring ownership. Else we keep ownership.
@@ -72,6 +75,7 @@ class evrp_range_analyzer
/* True if we are updating global ranges, false otherwise. */
bool m_update_global_ranges;
+ class trace_vr_gori_interface *gori;
class gimple_ranger *ranger;
};
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index af953cb..ffe83a6 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -46,13 +46,18 @@ class evrp_folder : public substitute_and_fold_engine
{
public:
tree get_value (tree) FINAL OVERRIDE;
- evrp_folder (class vr_values *vr_values_) : vr_values (vr_values_) { }
+ evrp_folder (class vr_values *vr_values_)
+ : vr_values (vr_values_),
+ simplifier (vr_values_) { }
bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
- { return vr_values->simplify_stmt_using_ranges (gsi); }
+ {
+ return simplifier.simplify (gsi);
+ }
class vr_values *vr_values;
private:
DISABLE_COPY_AND_ASSIGN (evrp_folder);
+ simplify_using_ranges simplifier;
};
tree
@@ -306,16 +311,15 @@ evrp_dom_walker::cleanup (void)
gimple *stmt = stmts_to_fixup.pop ();
fixup_noreturn_call (stmt);
}
-
- evrp_folder.vr_values->cleanup_edges_and_switches ();
}
class xevrp_folder : public substitute_and_fold_engine
{
public:
- xevrp_folder () : range_analyzer (true)
+ xevrp_folder () : range_analyzer (true),
+ vr_values (range_analyzer.get_vr_values ()),
+ simplifier (vr_values)
{
- vr_values = range_analyzer.get_vr_values ();
}
~xevrp_folder ()
@@ -326,7 +330,6 @@ public:
range_analyzer.dump_all_value_ranges (dump_file);
fprintf (dump_file, "\n");
}
- vr_values->cleanup_edges_and_switches ();
}
tree get_value (tree op)
@@ -353,7 +356,7 @@ public:
bool fold_stmt (gimple_stmt_iterator *gsi)
{
- return vr_values->simplify_stmt_using_ranges (gsi);
+ return simplifier.simplify (gsi);
}
void post_fold_bb (basic_block bb)
@@ -368,8 +371,9 @@ public:
private:
DISABLE_COPY_AND_ASSIGN (xevrp_folder);
- class vr_values *vr_values;
class evrp_range_analyzer range_analyzer;
+ class vr_values *vr_values;
+ simplify_using_ranges simplifier;
};
/* Main entry point for the early vrp pass which is a simplified non-iterative
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 1dbfb38..ab4cee6 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -886,12 +886,11 @@ simplify_stmt_for_jump_threading (gimple *stmt,
copy in tree-vrp is scheduled for removal in gcc-9. */
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
- cached_lhs
- = x_vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- within_stmt);
- return cached_lhs;
+ simplify_using_ranges simplifier (x_vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ gimple_cond_lhs (cond_stmt),
+ gimple_cond_rhs (cond_stmt),
+ within_stmt);
}
if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ead8552..fcc79c7 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3500,7 +3500,7 @@ class vrp_prop : public ssa_propagation_engine
enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
void vrp_initialize (void);
- void vrp_finalize (bool);
+ void vrp_finalize (class vrp_folder *, bool);
void check_all_array_refs (void);
bool check_array_ref (location_t, tree, bool);
bool check_mem_ref (location_t, tree, bool);
@@ -4850,21 +4850,26 @@ vrp_prop::visit_phi (gphi *phi)
class vrp_folder : public substitute_and_fold_engine
{
public:
- vrp_folder () : substitute_and_fold_engine (/* Fold all stmts. */ true) { }
+ vrp_folder (vr_values *v)
+ : substitute_and_fold_engine (/* Fold all stmts. */ true),
+ m_vr_values (v), simplifier (v)
+ { }
tree get_value (tree) FINAL OVERRIDE;
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
bool fold_predicate_in (gimple_stmt_iterator *);
- class vr_values *vr_values;
-
/* Delegators. */
tree vrp_evaluate_conditional (tree_code code, tree op0,
tree op1, gimple *stmt)
- { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
+ { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
- { return vr_values->simplify_stmt_using_ranges (gsi); }
+ { return simplifier.simplify (gsi); }
tree op_with_constant_singleton_value_range (tree op)
- { return vr_values->op_with_constant_singleton_value_range (op); }
+ { return m_vr_values->op_with_constant_singleton_value_range (op); }
+
+private:
+ vr_values *m_vr_values;
+ simplify_using_ranges simplifier;
};
/* If the statement pointed by SI has a predicate whose value can be
@@ -5006,7 +5011,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
tree op1 = gimple_cond_rhs (cond_stmt);
op1 = lhs_of_dominating_assert (op1, bb, stmt);
- return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ simplify_using_ranges simplifier (vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
op0, op1, within_stmt);
}
@@ -5242,7 +5248,7 @@ identify_jump_threads (class vr_values *vr_values)
/* Traverse all the blocks folding conditionals with known ranges. */
void
-vrp_prop::vrp_finalize (bool warn_array_bounds_p)
+vrp_prop::vrp_finalize (vrp_folder *folder, bool warn_array_bounds_p)
{
size_t i;
@@ -5286,9 +5292,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
if (warn_array_bounds && warn_array_bounds_p)
set_all_edges_as_executable (cfun);
- class vrp_folder vrp_folder;
- vrp_folder.vr_values = &vr_values;
- vrp_folder.substitute_and_fold ();
+ folder->substitute_and_fold ();
if (warn_array_bounds && warn_array_bounds_p)
check_all_array_refs ();
@@ -5359,7 +5363,10 @@ execute_vrp (bool warn_array_bounds_p)
class vrp_prop vrp_prop;
vrp_prop.vrp_initialize ();
vrp_prop.ssa_propagate ();
- vrp_prop.vrp_finalize (warn_array_bounds_p);
+ /* Instantiate the folder here, so that edge cleanups happen at the
+ end of this function. */
+ vrp_folder folder (&vrp_prop.vr_values);
+ vrp_prop.vrp_finalize (&folder, warn_array_bounds_p);
/* We must identify jump threading opportunities before we release
the datastructures built by VRP. */
@@ -5377,7 +5384,8 @@ execute_vrp (bool warn_array_bounds_p)
{
gimple *last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_COND)
- vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
+ simplify_cond_using_ranges_2 (&vrp_prop.vr_values,
+ as_a <gcond *> (last));
}
free_numbers_of_iterations_estimates (cfun);
@@ -5402,7 +5410,6 @@ execute_vrp (bool warn_array_bounds_p)
processing by the pass manager. */
thread_through_all_blocks (false);
- vrp_prop.vr_values.cleanup_edges_and_switches ();
threadedge_finalize_values ();
scev_finalize ();
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 1ea121f..d327f22 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -173,6 +173,25 @@ vr_values::get_value_range (const_tree var)
return vr;
}
+bool
+vr_values::range_of_expr (irange &r, tree expr, gimple *stmt ATTRIBUTE_UNUSED)
+{
+ tree type = TREE_TYPE (expr);
+ if (!irange::supports_type_p (type))
+ return false;
+
+ if (TREE_CODE (expr) == SSA_NAME)
+ {
+ const value_range_equiv *vr = get_value_range (expr);
+ r = *vr;
+ }
+ else if (TREE_CODE (expr) == INTEGER_CST)
+ r.set (expr, expr);
+ else
+ r.set_varying (type);
+ return true;
+}
+
/* Set the lattice entry for DEF to VARYING. */
void
@@ -437,10 +456,8 @@ vr_values::op_with_constant_singleton_value_range (tree op)
/* Return true if op is in a boolean [0, 1] value-range. */
bool
-vr_values::op_with_boolean_value_range_p (tree op)
+simplify_using_ranges::op_with_boolean_value_range_p (tree op, gimple *stmt)
{
- const value_range_equiv *vr;
-
if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
return true;
@@ -451,10 +468,11 @@ vr_values::op_with_boolean_value_range_p (tree op)
if (TREE_CODE (op) != SSA_NAME)
return false;
- vr = get_value_range (op);
- return (vr->kind () == VR_RANGE
- && integer_zerop (vr->min ())
- && integer_onep (vr->max ()));
+ widest_irange r;
+ gcc_checking_assert (store->range_of_expr (r, op, stmt));
+ return (r.kind () == VR_RANGE
+ && integer_zerop (r.min ())
+ && integer_onep (r.max ()));
}
/* Extract value range information for VAR when (OP COND_CODE LIMIT) is
@@ -980,8 +998,8 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
bool sop;
tree val;
- val = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, false, &sop,
- NULL);
+ val = simplifier.vrp_evaluate_conditional_warnv_with_ops (code, op0, op1,
+ false, &sop, NULL);
if (val)
{
/* Since this expression was found on the RHS of an assignment,
@@ -1004,20 +1022,21 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
always overflow. Set *OVF to true if it is known to always
overflow. */
-bool
-vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
- tree op0, tree op1, bool *ovf)
+static bool
+check_for_binary_op_overflow (range_store *store,
+ enum tree_code subcode, tree type,
+ tree op0, tree op1, bool *ovf)
{
value_range vr0, vr1;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *get_value_range (op0);
+ gcc_checking_assert (store->range_of_expr (vr0, 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 = *get_value_range (op1);
+ store->range_of_expr (vr1, op1);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
@@ -1397,7 +1416,8 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
if (code == IMAGPART_EXPR)
{
bool ovf = false;
- if (check_for_binary_op_overflow (subcode, type,
+ if (check_for_binary_op_overflow (this,
+ subcode, type,
op0, op1, &ovf))
vr->set (build_int_cst (type, ovf));
else if (TYPE_PRECISION (type) == 1
@@ -1638,7 +1658,7 @@ compare_ranges (enum tree_code comp, const value_range_equiv *vr0,
assumed signed overflow is undefined. */
static tree
-compare_range_with_value (enum tree_code comp, const value_range_equiv *vr,
+compare_range_with_value (enum tree_code comp, const irange *vr,
tree val, bool *strict_overflow_p)
{
if (vr->varying_p () || vr->undefined_p ())
@@ -1932,13 +1952,6 @@ vr_values::dump_all_value_ranges (FILE *file)
{
size_t i;
- if (dump_flags & TDF_GORI)
- {
- fprintf (file, "GORI map:\n");
- m_gori_map.dump (file);
- fprintf (file, "-----------------\n");
- }
-
for (i = 0; i < num_vr_values; i++)
{
if (vr_value[i])
@@ -1951,155 +1964,16 @@ vr_values::dump_all_value_ranges (FILE *file)
}
}
-void
-vr_values::range_of_ssa_name (irange &r, tree op,
- gimple *stmt ATTRIBUTE_UNUSED)
-{
- r = *(get_value_range (op));
- r.normalize_symbolics ();
-}
-
-// Return TRUE if NAME is computable by GORI in BB.
-
-bool
-vr_gori_interface::gori_computable_p (tree name, basic_block bb)
-{
- return m_gori_map.is_export_p (name, bb);
-}
-
-// Calculate the range for NAME on edge E and return it in R.
-// Return FALSE if unable to compute a range.
-
-bool
-vr_gori_interface::outgoing_edge_range_p (irange &r, edge e, tree name,
- const irange *known_range ATTRIBUTE_UNUSED)
-{
- if (!gori_compute::outgoing_edge_range_p (r, e, name))
- r.set_varying (TREE_TYPE (name));
- if (!r.singleton_p ())
- refine_range_with_equivalences (r, e, name);
- widest_irange tmp;
- range_of_ssa_name (tmp, name);
- r.intersect (tmp);
- return !r.varying_p ();
-}
-
-// R is a known range for NAME on edge E. Refine it with any
-// equivalences NAME may have.
-
-bool
-vr_gori_interface::refine_range_with_equivalences (irange &r,
- edge e, tree name)
-{
- widest_irange branch_range, tmp;
- gimple *branch = gimple_outgoing_edge_range_p (branch_range, e);
- if (!branch)
- return false;
-
- // Solve each equivalence and use them to refine the range.
- bitmap_iterator bi;
- unsigned i;
- bitmap gori_exports = m_gori_map.exports (e->src);
- EXECUTE_IF_SET_IN_BITMAP (gori_exports, 0, i, bi)
- {
- tree equiv = ssa_name (i);
- if (equiv == name)
- continue;
- widest_irange equiv_range;
- if (solve_name_at_statement (equiv_range, equiv, branch, branch_range))
- {
- gimple *equiv_def = SSA_NAME_DEF_STMT (equiv);
- if (!equiv_def->bb
- || !dominated_by_p (CDI_DOMINATORS, e->src, equiv_def->bb))
- continue;
-
- if (solve_name_given_equivalence (tmp, name, equiv, equiv_range))
- r.intersect (tmp);
- }
- }
- return !r.varying_p ();
-}
-
-// Compute a range for NAME as it would appear in STMT and return it
-// in R. LHS is the known range for STMT.
-
-bool
-vr_gori_interface::solve_name_at_statement (irange &r,
- tree name, gimple *stmt,
- const irange &lhs)
-{
- widest_irange name_range;
- range_of_ssa_name (name_range, name, stmt);
- return compute_operand_range (r, stmt, lhs, name, &name_range);
-}
-
-bool
-vr_gori_interface::solve_name_given_equivalence (irange &r,
- tree name,
- tree equiv,
- const irange &equiv_range)
-{
- // Solve NAME in EQUIV = USE(NAME).
- gimple *def = SSA_NAME_DEF_STMT (equiv);
- if (gimple_range_handler (def) && gimple_range_operand1 (def) == name)
- {
- widest_irange op2_range;
- if (tree op2 = gimple_range_operand2 (def))
- range_of_expr (op2_range, op2, def);
- else
- {
- tree type = TREE_TYPE (gimple_range_operand1 (def));
- op2_range.set_varying (type);
- }
- return gimple_range_calc_op1 (def, r, equiv_range, op2_range);
- }
- // Solve NAME in NAME = USE(EQUIV).
- def = SSA_NAME_DEF_STMT (name);
- if (gimple_range_handler (def) && gimple_range_operand1 (def) == equiv)
- {
- widest_irange op2_range;
- if (tree op2 = gimple_range_operand2 (def))
- range_of_expr (op2_range, op2, def);
- else
- {
- tree type = gimple_expr_type (def);
- op2_range.set_varying (type);
- }
- return gimple_range_fold (def, r, equiv_range, op2_range);
- }
- return false;
-}
-
-bool
-trace_vr_gori_interface::refine_range_with_equivalences (irange &r,
- edge e, tree name)
-{
- unsigned idx = ++trace_count;
- if (dumping (idx))
- {
- fprintf (dump_file, "refine_range_with_equivalences (");
- print_generic_expr (dump_file, name, TDF_SLIM);
- fprintf (dump_file, ") on edge %d->%d, with range ",
- e->src->index, e->dest->index);
- r.dump (dump_file);
- fputc ('\n', dump_file);
- indent += bump;
- }
- bool res = super::refine_range_with_equivalences (r, e, name);
- return trailer (idx, "refine_range_with_equivalences", res, name, r);
-}
-
/* Initialize VRP lattice. */
-vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
+vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges"),
+ simplifier (this)
{
values_propagated = false;
num_vr_values = num_ssa_names * 2;
vr_value = XCNEWVEC (value_range_equiv *, num_vr_values);
vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
bitmap_obstack_initialize (&vrp_equiv_obstack);
- to_remove_edges = vNULL;
- to_update_switch_stmts = vNULL;
}
/* Free VRP lattice. */
@@ -2116,12 +1990,6 @@ vr_values::~vr_values ()
and not available. */
vr_value = NULL;
vr_phi_edge_counts = NULL;
-
- /* If there are entries left in TO_REMOVE_EDGES or TO_UPDATE_SWITCH_STMTS
- then an EVRP client did not clean up properly. Catch it now rather
- than seeing something more obscure later. */
- gcc_assert (to_remove_edges.is_empty ()
- && to_update_switch_stmts.is_empty ());
}
@@ -2239,10 +2107,10 @@ vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
is varying or undefined. Uses TEM as storage for the alternate range. */
const value_range_equiv *
-vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
+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 = get_value_range_equiv (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
@@ -2262,11 +2130,12 @@ vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
*STRICT_OVERFLOW_P. */
tree
-vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
- bool *strict_overflow_p, bool use_equiv_p)
+simplify_using_ranges::compare_name_with_value
+ (enum tree_code comp, tree var, tree val,
+ bool *strict_overflow_p, bool use_equiv_p)
{
/* Get the set of equivalences for VAR. */
- bitmap e = get_value_range (var)->equiv ();
+ bitmap e = get_value_range_equiv (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. */
@@ -2341,13 +2210,13 @@ vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
tree
-vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
- bool *strict_overflow_p)
+simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
+ bool *strict_overflow_p)
{
/* 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 = get_value_range_equiv (n1)->equiv ();
+ bitmap e2 = get_value_range_equiv (n2)->equiv ();
/* Use the fake bitmaps if e1 or e2 are not available. */
static bitmap s_e1 = NULL, s_e2 = NULL;
@@ -2455,12 +2324,12 @@ vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
optimizers. */
tree
-vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
+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) ? get_value_range_equiv (op0) : NULL;
+ vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range_equiv (op1) : NULL;
tree res = NULL_TREE;
if (vr0 && vr1)
@@ -2476,11 +2345,12 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
/* Helper function for vrp_evaluate_conditional_warnv. */
tree
-vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
- tree op0, tree op1,
- bool use_equiv_p,
- bool *strict_overflow_p,
- bool *only_ranges)
+simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
+ (enum tree_code code,
+ tree op0, tree op1,
+ bool use_equiv_p,
+ bool *strict_overflow_p,
+ bool *only_ranges)
{
tree ret;
if (only_ranges)
@@ -2537,7 +2407,7 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
}
else
gcc_unreachable ();
- const value_range_equiv *vr0 = get_value_range (op0);
+ const value_range_equiv *vr0 = get_value_range_equiv (op0);
/* 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.
@@ -2583,8 +2453,8 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
appropriate. */
tree
-vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
- tree op1, gimple *stmt)
+simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0,
+ tree op1, gimple *stmt)
{
bool sop;
tree ret;
@@ -2643,7 +2513,7 @@ vr_values::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);
+ const value_range_equiv *vr0 = get_value_range_equiv (op0);
if (vr0->kind () == VR_RANGE
&& INTEGRAL_TYPE_P (type)
@@ -2676,7 +2546,7 @@ vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
*TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */
void
-vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
+simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
{
tree val;
@@ -2696,7 +2566,7 @@ vr_values::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, vr_value[SSA_NAME_VERSION (use)]);
+ dump_value_range (dump_file, store->get_value_range (use));
}
fprintf (dump_file, "\n");
@@ -2769,7 +2639,7 @@ vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
Returns true if the default label is not needed. */
static bool
-find_case_label_ranges (gswitch *stmt, const value_range_equiv *vr,
+find_case_label_ranges (gswitch *stmt, const irange *vr,
size_t *min_idx1, size_t *max_idx1,
size_t *min_idx2, size_t *max_idx2)
{
@@ -2953,7 +2823,7 @@ vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
vrp_visit_assignment_or_call (stmt, output_p, vr);
else if (gimple_code (stmt) == GIMPLE_COND)
- vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
+ simplifier.vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
vrp_visit_switch_stmt (as_a <gswitch *> (stmt), taken_edge_p);
}
@@ -3174,8 +3044,9 @@ update_range:
/* Simplify boolean operations if the source is known
to be already a boolean. */
bool
-vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_truth_ops_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs, op0, op1;
@@ -3185,11 +3056,11 @@ vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR);
op0 = gimple_assign_rhs1 (stmt);
- if (!op_with_boolean_value_range_p (op0))
+ if (!op_with_boolean_value_range_p (op0, stmt))
return false;
op1 = gimple_assign_rhs2 (stmt);
- if (!op_with_boolean_value_range_p (op1))
+ if (!op_with_boolean_value_range_p (op1, stmt))
return false;
/* Reduce number of cases to handle to NE_EXPR. As there is no
@@ -3251,8 +3122,9 @@ vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
modulo. */
bool
-vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_div_or_mod_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree val = NULL;
@@ -3260,7 +3132,11 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
tree op1 = gimple_assign_rhs2 (stmt);
tree op0min = NULL_TREE, op0max = NULL_TREE;
tree op1min = op1;
- const value_range_equiv *vr = NULL;
+ /* ?? All uses of value_range in the simplifier should be converted
+ to widest_irange. However, in order to do this, there must be no
+ VR_ANTI_RANGE uses downstream, as widest_irange has no concept of
+ them except for symbolics. */
+ value_range vr;
if (TREE_CODE (op0) == INTEGER_CST)
{
@@ -3269,20 +3145,21 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
}
else
{
- vr = get_value_range (op0);
- if (range_int_cst_p (vr))
+ gcc_checking_assert (store->range_of_expr (vr, op0, stmt));
+ if (range_int_cst_p (&vr))
{
- op0min = vr->min ();
- op0max = vr->max ();
+ op0min = vr.min ();
+ op0max = vr.max ();
}
}
if (rhs_code == TRUNC_MOD_EXPR
&& TREE_CODE (op1) == SSA_NAME)
{
- const value_range_equiv *vr1 = get_value_range (op1);
- if (range_int_cst_p (vr1))
- op1min = vr1->min ();
+ value_range vr1;
+ gcc_checking_assert (store->range_of_expr (vr1, op1, stmt));
+ if (range_int_cst_p (&vr1))
+ op1min = vr1.min ();
}
if (rhs_code == TRUNC_MOD_EXPR
&& TREE_CODE (op1min) == INTEGER_CST
@@ -3323,7 +3200,7 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
{
bool sop = false;
- val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+ val = compare_range_with_value (GE_EXPR, &vr, integer_zero_node, &sop);
if (val
&& sop
@@ -3376,8 +3253,9 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
disjoint. Return true if we do simplify. */
bool
-vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_min_or_max_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
if (!irange::supports_type_p (TREE_TYPE (op0)))
@@ -3385,13 +3263,13 @@ vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
tree op1 = gimple_assign_rhs2 (stmt);
value_range vr0, vr1;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *get_value_range (op0);
+ gcc_checking_assert (store->range_of_expr (vr0, op0, stmt));
else if (TREE_CODE (op0) == INTEGER_CST)
vr0.set (op0);
else
vr0.set_varying (TREE_TYPE (op0));
if (TREE_CODE (op1) == SSA_NAME)
- vr1 = *get_value_range (op1);
+ gcc_checking_assert (store->range_of_expr (vr1, op1, stmt));
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
@@ -3427,23 +3305,25 @@ vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
ABS_EXPR into a NEGATE_EXPR. */
bool
-vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op = gimple_assign_rhs1 (stmt);
- const value_range_equiv *vr = get_value_range (op);
+ value_range vr;
+ gcc_checking_assert (store->range_of_expr (vr, op, stmt));
- if (vr)
+ if (!vr.varying_p () && !vr.undefined_p ())
{
tree val = NULL;
bool sop = false;
- val = compare_range_with_value (LE_EXPR, vr, integer_zero_node, &sop);
+ val = compare_range_with_value (LE_EXPR, &vr, integer_zero_node, &sop);
if (!val)
{
/* The range is neither <= 0 nor > 0. Now see if it is
either < 0 or >= 0. */
sop = false;
- val = compare_range_with_value (LT_EXPR, vr, integer_zero_node,
+ val = compare_range_with_value (LT_EXPR, &vr, integer_zero_node,
&sop);
}
@@ -3507,8 +3387,9 @@ vr_set_zero_nonzero_bits (const tree expr_type,
operation is redundant. */
bool
-vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_bit_ops_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
@@ -3519,14 +3400,14 @@ vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
wide_int mask;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *(get_value_range (op0));
+ gcc_checking_assert (store->range_of_expr (vr0, 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));
+ gcc_checking_assert (store->range_of_expr (vr1, op1, stmt));
else if (is_gimple_min_invariant (op1))
vr1.set (op1);
else
@@ -3592,7 +3473,7 @@ vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
static tree
test_for_singularity (enum tree_code cond_code, tree op0,
- tree op1, const value_range_equiv *vr)
+ tree op1, const irange *vr)
{
tree min = NULL;
tree max = NULL;
@@ -3650,7 +3531,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
by PRECISION and UNSIGNED_P. */
static bool
-range_fits_type_p (const value_range_equiv *vr,
+range_fits_type_p (const value_range *vr,
unsigned dest_precision, signop dest_sgn)
{
tree src_type;
@@ -3699,7 +3580,8 @@ range_fits_type_p (const value_range_equiv *vr,
}
bool
-vr_values::simplify_cond_using_ranges_when_edge_is_known (gcond *cond)
+simplify_using_ranges::simplify_cond_using_ranges_when_edge_is_known
+ (gcond *cond)
{
/* ?? vrp_folder::fold_predicate_in() is a superset of this. At
some point we should merge all variants of this code. */
@@ -3724,7 +3606,7 @@ vr_values::simplify_cond_using_ranges_when_edge_is_known (gcond *cond)
the original conditional. */
bool
-vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
+simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -3739,13 +3621,14 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
&& INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& is_gimple_min_invariant (op1))
{
- const value_range_equiv *vr = get_value_range (op0);
+ value_range vr;
+ gcc_checking_assert (store->range_of_expr (vr, op0, stmt));
/* If we have range information for OP0, then we might be
able to simplify this conditional. */
- if (vr->kind () == VR_RANGE)
+ if (vr.kind () == VR_RANGE)
{
- tree new_tree = test_for_singularity (cond_code, op0, op1, vr);
+ tree new_tree = test_for_singularity (cond_code, op0, op1, &vr);
if (new_tree)
{
if (dump_file)
@@ -3775,7 +3658,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
issues with inverting FP comparisons. */
new_tree = test_for_singularity
(invert_tree_comparison (cond_code, false),
- op0, op1, vr);
+ op0, op1, &vr);
if (new_tree)
{
if (dump_file)
@@ -3812,7 +3695,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
subsequent passes. */
void
-vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
+simplify_cond_using_ranges_2 (range_store *store, gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -3842,10 +3725,11 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
&& desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
{
- const value_range_equiv *vr = get_value_range (innerop);
+ value_range vr;
+ gcc_checking_assert (store->range_of_expr (vr, innerop, stmt));
- if (range_int_cst_p (vr)
- && range_fits_type_p (vr,
+ if (range_int_cst_p (&vr)
+ && range_fits_type_p (&vr,
TYPE_PRECISION (TREE_TYPE (op0)),
TYPE_SIGN (TREE_TYPE (op0)))
&& int_fits_type_p (op1, TREE_TYPE (innerop)))
@@ -3869,10 +3753,10 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
argument. */
bool
-vr_values::simplify_switch_using_ranges (gswitch *stmt)
+simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
{
tree op = gimple_switch_index (stmt);
- const value_range_equiv *vr = NULL;
+ value_range vr;
bool take_default;
edge e;
edge_iterator ei;
@@ -3883,16 +3767,16 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
if (TREE_CODE (op) == SSA_NAME)
{
- vr = get_value_range (op);
+ gcc_checking_assert (store->range_of_expr (vr, op, stmt));
/* We can only handle integer ranges. */
- if (vr->varying_p ()
- || vr->undefined_p ()
- || vr->symbolic_p ())
+ if (vr.varying_p ()
+ || vr.undefined_p ()
+ || vr.symbolic_p ())
return false;
/* Find case label for min/max of the value range. */
- take_default = !find_case_label_ranges (stmt, vr, &i, &j, &k, &l);
+ take_default = !find_case_label_ranges (stmt, &vr, &i, &j, &k, &l);
}
else if (TREE_CODE (op) == INTEGER_CST)
{
@@ -3915,8 +3799,8 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
/* We can truncate the case label ranges that partially overlap with OP's
value range. */
size_t min_idx = 1, max_idx = 0;
- if (vr != NULL)
- find_case_label_range (stmt, vr->min (), vr->max (), &min_idx, &max_idx);
+ if (!vr.varying_p () && !vr.undefined_p ())
+ find_case_label_range (stmt, vr.min (), vr.max (), &min_idx, &max_idx);
if (min_idx <= max_idx)
{
tree min_label = gimple_switch_label (stmt, min_idx);
@@ -3924,10 +3808,10 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
/* Avoid changing the type of the case labels when truncating. */
tree case_label_type = TREE_TYPE (CASE_LOW (min_label));
- tree vr_min = fold_convert (case_label_type, vr->min ());
- tree vr_max = fold_convert (case_label_type, vr->max ());
+ tree vr_min = fold_convert (case_label_type, vr.min ());
+ tree vr_max = fold_convert (case_label_type, vr.max ());
- if (vr->kind () == VR_RANGE)
+ if (vr.kind () == VR_RANGE)
{
/* If OP's value range is [2,8] and the low label range is
0 ... 3, truncate the label's range to 2 .. 3. */
@@ -3943,7 +3827,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
&& tree_int_cst_compare (CASE_HIGH (max_label), vr_max) > 0)
CASE_HIGH (max_label) = vr_max;
}
- else if (vr->kind () == VR_ANTI_RANGE)
+ else if (vr.kind () == VR_ANTI_RANGE)
{
tree one_cst = build_one_cst (case_label_type);
@@ -4050,7 +3934,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
}
void
-vr_values::cleanup_edges_and_switches (void)
+simplify_using_ranges::cleanup_edges_and_switches (void)
{
int i;
edge e;
@@ -4168,11 +4052,13 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
/* Simplify a conversion from integral SSA name to float in STMT. */
bool
-vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_float_conversion_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- const value_range_equiv *vr = get_value_range (rhs1);
+ value_range vr;
+ gcc_checking_assert (store->range_of_expr (vr, rhs1, stmt));
scalar_float_mode fltmode
= SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
scalar_int_mode mode;
@@ -4180,14 +4066,14 @@ vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
gassign *conv;
/* We can only handle constant ranges. */
- if (!range_int_cst_p (vr))
+ if (!range_int_cst_p (&vr))
return false;
/* First check if we can use a signed type in place of an unsigned. */
scalar_int_mode rhs_mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs1));
if (TYPE_UNSIGNED (TREE_TYPE (rhs1))
&& can_float_p (fltmode, rhs_mode, 0) != CODE_FOR_nothing
- && range_fits_type_p (vr, TYPE_PRECISION (TREE_TYPE (rhs1)), SIGNED))
+ && range_fits_type_p (&vr, TYPE_PRECISION (TREE_TYPE (rhs1)), SIGNED))
mode = rhs_mode;
/* If we can do the conversion in the current input mode do nothing. */
else if (can_float_p (fltmode, rhs_mode,
@@ -4204,7 +4090,7 @@ vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
or if the value-range does not fit in the signed type
try with a wider mode. */
if (can_float_p (fltmode, mode, 0) != CODE_FOR_nothing
- && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED))
+ && range_fits_type_p (&vr, GET_MODE_PRECISION (mode), SIGNED))
break;
/* But do not widen the input. Instead leave that to the
@@ -4230,8 +4116,9 @@ vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
/* Simplify an internal fn call using ranges if possible. */
bool
-vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_internal_call_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code subcode;
bool is_ubsan = false;
@@ -4276,7 +4163,7 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
return false;
else
type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
- if (!check_for_binary_op_overflow (subcode, type, op0, op1, &ovf)
+ if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf)
|| (is_ubsan && ovf))
return false;
@@ -4333,29 +4220,30 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
two-values when it is true. Return false otherwise. */
bool
-vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
+simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
{
- const value_range_equiv *vr = get_value_range (var);
- if (vr->varying_p ()
- || vr->undefined_p ()
- || TREE_CODE (vr->min ()) != INTEGER_CST
- || TREE_CODE (vr->max ()) != INTEGER_CST)
+ value_range vr;
+ gcc_checking_assert (store->range_of_expr (vr, var));
+ if (vr.varying_p ()
+ || vr.undefined_p ()
+ || TREE_CODE (vr.min ()) != INTEGER_CST
+ || TREE_CODE (vr.max ()) != INTEGER_CST)
return false;
- if (vr->kind () == VR_RANGE
- && wi::to_wide (vr->max ()) - wi::to_wide (vr->min ()) == 1)
+ if (vr.kind () == VR_RANGE
+ && wi::to_wide (vr.max ()) - wi::to_wide (vr.min ()) == 1)
{
- *a = vr->min ();
- *b = vr->max ();
+ *a = vr.min ();
+ *b = vr.max ();
return true;
}
/* ~[TYPE_MIN + 1, TYPE_MAX - 1] */
- if (vr->kind () == VR_ANTI_RANGE
- && (wi::to_wide (vr->min ())
+ if (vr.kind () == VR_ANTI_RANGE
+ && (wi::to_wide (vr.min ())
- wi::to_wide (vrp_val_min (TREE_TYPE (var)))) == 1
&& (wi::to_wide (vrp_val_max (TREE_TYPE (var)))
- - wi::to_wide (vr->max ())) == 1)
+ - wi::to_wide (vr.max ())) == 1)
{
*a = vrp_val_min (TREE_TYPE (var));
*b = vrp_val_max (TREE_TYPE (var));
@@ -4365,10 +4253,22 @@ vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
return false;
}
+simplify_using_ranges::simplify_using_ranges (range_store *store)
+ : store (store)
+{
+ to_remove_edges = vNULL;
+ to_update_switch_stmts = vNULL;
+}
+
+simplify_using_ranges::~simplify_using_ranges ()
+{
+ cleanup_edges_and_switches ();
+}
+
/* Simplify STMT using ranges if possible. */
bool
-vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
if (is_gimple_assign (stmt))
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 2a6273c..bd121b7 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -22,28 +22,61 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-range-gori.h"
-class vr_gori_interface : public trace_gori_compute
+class simplify_using_ranges
{
public:
- virtual bool outgoing_edge_range_p (irange &, edge, tree name,
- const irange *name_range = NULL);
- bool gori_computable_p (tree name, basic_block);
-protected:
- virtual void range_of_ssa_name (irange &r ATTRIBUTE_UNUSED,
- tree op ATTRIBUTE_UNUSED,
- gimple *stmt ATTRIBUTE_UNUSED = NULL)
- { gcc_unreachable (); }
- virtual bool refine_range_with_equivalences (irange &, edge, tree name);
- bool solve_name_at_statement (irange &, tree, gimple *stmt, const irange &);
- bool solve_name_given_equivalence (irange &r, tree name, tree equiv,
- const irange &equiv_range);
-};
+ simplify_using_ranges (range_store *);
+ ~simplify_using_ranges ();
+ bool simplify (gimple_stmt_iterator *);
+
+ // ?? These should be cleaned, merged, and made private.
+ tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
+ void vrp_visit_cond_stmt (gcond *, edge *);
+ tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
+ tree, tree, bool,
+ bool *, bool *);
-class trace_vr_gori_interface : public vr_gori_interface
-{
private:
- virtual bool refine_range_with_equivalences (irange &, edge, tree name);
- typedef vr_gori_interface super;
+ // This is named differently than get_value_range to make it obvious
+ // that it returns an equivalence. Only use this for calculations
+ // that may take equivalences, otherwise use range_of_expr.
+ const value_range_equiv *get_value_range_equiv (const_tree op)
+ { return store->get_value_range (op); }
+ 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 *);
+ bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
+ bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
+ bool simplify_cond_using_ranges_1 (gcond *);
+ bool simplify_cond_using_ranges_when_edge_is_known (gcond *);
+ bool simplify_switch_using_ranges (gswitch *);
+ bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
+ gimple *);
+ bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
+
+ bool two_valued_val_range_p (tree, tree *, tree *);
+ bool op_with_boolean_value_range_p (tree, gimple *);
+ tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
+ tree compare_names (enum tree_code, tree, tree, bool *);
+ const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
+ tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
+ tree, tree,
+ bool *);
+ void cleanup_edges_and_switches (void);
+
+ /* Vectors of edges that need removing and switch statements that
+ need updating. It is expected that a pass using the simplification
+ routines will, at the end of the pass, clean up the edges and
+ switch statements. The class dtor will try to detect cases
+ that do not follow that expectation. */
+ struct switch_update {
+ gswitch *stmt;
+ tree vec;
+ };
+
+ vec<edge> to_remove_edges;
+ vec<switch_update> to_update_switch_stmts;
+ range_store *store;
};
/* The VR_VALUES class holds the current view of range information
@@ -60,15 +93,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 trace_vr_gori_interface
+class vr_values : public range_store
{
public:
vr_values (void);
- ~vr_values (void);
+ virtual ~vr_values (void);
const value_range_equiv *get_value_range (const_tree);
void set_vr_value (tree, value_range_equiv *);
value_range_equiv *swap_vr_value (tree, value_range_equiv *);
+ bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL);
void set_def_to_varying (const_tree);
void set_defs_to_varying (gimple *);
@@ -76,7 +110,6 @@ class vr_values : public trace_vr_gori_interface
tree op_with_constant_singleton_value_range (tree);
void adjust_range_with_scev (value_range_equiv *, class loop *,
gimple *, tree);
- tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
void dump_all_value_ranges (FILE *);
void extract_range_for_var_from_comparison_expr (tree, enum tree_code,
@@ -86,11 +119,6 @@ class vr_values : public trace_vr_gori_interface
void extract_range_basic (value_range_equiv *, gimple *);
void extract_range_from_stmt (gimple *, edge *, tree *, value_range_equiv *);
- void vrp_visit_cond_stmt (gcond *, edge *);
-
- void simplify_cond_using_ranges_2 (gcond *);
- bool simplify_stmt_using_ranges (gimple_stmt_iterator *);
-
/* Indicate that propagation through the lattice is complete. */
void set_lattice_propagation_complete (void) { values_propagated = true; }
@@ -100,26 +128,9 @@ class vr_values : public trace_vr_gori_interface
void free_value_range (value_range_equiv *vr)
{ vrp_value_range_pool.remove (vr); }
- /* */
- void cleanup_edges_and_switches (void);
-
private:
- virtual void range_of_ssa_name (irange &r, tree op, gimple * = NULL);
-
value_range_equiv *get_lattice_entry (const_tree);
bool vrp_stmt_computes_nonzero (gimple *);
- bool op_with_boolean_value_range_p (tree);
- bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
- const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
- tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
- tree compare_names (enum tree_code, tree, tree, bool *);
- bool two_valued_val_range_p (tree, tree *, tree *);
- tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
- tree, tree,
- bool *);
- tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
- tree, tree, bool,
- bool *, bool *);
void extract_range_from_assignment (value_range_equiv *, gassign *);
void extract_range_from_assert (value_range_equiv *, tree);
void extract_range_from_ssa_name (value_range_equiv *, tree);
@@ -132,17 +143,6 @@ class vr_values : public trace_vr_gori_interface
tree, tree, tree);
void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *);
void vrp_visit_switch_stmt (gswitch *, edge *);
- 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 *);
- bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
- bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
- bool simplify_cond_using_ranges_1 (gcond *);
- bool simplify_cond_using_ranges_when_edge_is_known (gcond *);
- bool simplify_switch_using_ranges (gswitch *);
- bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
- gimple *);
- bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
/* Allocation pools for value_range objects. */
object_allocator<value_range_equiv> vrp_value_range_pool;
@@ -162,20 +162,12 @@ class vr_values : public trace_vr_gori_interface
number of executable edges we saw the last time we visited the
node. */
int *vr_phi_edge_counts;
-
- /* Vectors of edges that need removing and switch statements that
- need updating. It is expected that a pass using the simplification
- routines will, at the end of the pass, clean up the edges and
- switch statements. The class dtor will try to detect cases
- that do not follow that expectation. */
- struct switch_update {
- gswitch *stmt;
- tree vec;
- };
-
- vec<edge> to_remove_edges;
- vec<switch_update> to_update_switch_stmts;
+ simplify_using_ranges simplifier;
};
extern tree get_output_for_vrp (gimple *);
+
+// FIXME: Move this to tree-vrp.c.
+void simplify_cond_using_ranges_2 (range_store *, gcond *);
+
#endif /* GCC_VR_VALUES_H */