summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2017-11-01 04:37:57 -0400
committerAldy Hernandez <aldyh@redhat.com>2017-11-01 04:37:57 -0400
commite563467101bba6b7961acef576473c785f40bb41 (patch)
tree27706d6cb422b86e9938eb06ae9700bf9469112f
parentfc8146536f5bd9ffcdaf3924fbe57a4951d5fcdd (diff)
parent599e206848457d4ec9d6fc867ed6e62f0c66f563 (diff)
downloadgcc-e563467101bba6b7961acef576473c785f40bb41.tar.gz
Merge remote-tracking branch 'range-gen3' of git://gcc.gnu.org/git/gcc into threader
-rw-r--r--gcc/ssa-range-gen.c229
-rw-r--r--gcc/ssa-range-gen.h39
2 files changed, 164 insertions, 104 deletions
diff --git a/gcc/ssa-range-gen.c b/gcc/ssa-range-gen.c
index 0e779ea755a..da314542c49 100644
--- a/gcc/ssa-range-gen.c
+++ b/gcc/ssa-range-gen.c
@@ -541,101 +541,158 @@ gori::range_of_def (irange& r, gimple *g, tree name,
}
// -------------------------------------------------------------------------
-range_cache::range_cache ()
+ssa_range_cache::ssa_range_cache (tree t)
{
+ irange tr;
+ gcc_assert (TYPE_P (t));
+ type = t;
+
tab.create (0);
tab.safe_grow_cleared (last_basic_block_for_fn (cfun));
+
+ tr.set_range_for_type (t);
+ type_range = irange_storage::ggc_alloc_init (tr);
+
+ tab[ENTRY_BLOCK_PTR_FOR_FN (cfun)->index] = type_range;
}
-range_cache::~range_cache ()
+ssa_range_cache::~ssa_range_cache ()
{
tab.release ();
}
void
-range_cache::reset ()
+ssa_range_cache::set_range (const basic_block bb, const irange& r)
{
- memset (tab.address () , 0, tab.length () * sizeof (irange *));
- unsigned x;
- for (x = 0; x < tab.length (); x++)
- gcc_assert (tab[x] == NULL);
+ irange_storage *m = tab[bb->index];
+
+ if (m)
+ m->set_irange (r);
+ else
+ m = irange_storage::ggc_alloc_init (r);
+
+ tab[bb->index] = m;
}
void
-range_cache::set_range (basic_block bb, irange_storage *r)
+ssa_range_cache::set_range_for_type (const basic_block bb)
{
- tab[bb->index] = r;
+ tab[bb->index] = type_range;
}
-irange_storage *
-range_cache::operator[] (const basic_block bb)
+
+bool
+ssa_range_cache::get_range (irange& r, const basic_block bb)
{
- return tab[bb->index];
+ irange_storage *m = tab[bb->index];
+ if (m)
+ {
+ r.set_range (m, type);
+ return true;
+ }
+ return false;
+}
+
+
+// Returns true if a range is present
+bool
+ssa_range_cache::range_p (const basic_block bb)
+{
+ return tab[bb->index] != NULL;
}
void
-range_cache::dump (FILE *f, tree type)
+ssa_range_cache::dump (FILE *f)
{
- basic_block bb;
+ basic_block bb;
+ irange r;
- FOR_EACH_BB_FN (bb, cfun)
- if (tab[bb->index] != NULL)
+ FOR_EACH_BB_FN (bb, cfun)
+ if (get_range (r, bb))
{
- irange r(tab[bb->index], type);
fprintf (f, "BB%d -> ", bb->index);
r.dump (f);
}
}
-
// -------------------------------------------------------------------------
-path_ranger::path_ranger ()
+range_cache::range_cache ()
{
- // Just a marker.
- processing = irange_storage::ggc_alloc (1);
- type_range = NULL;
+ ssa_ranges.create (0);
+ ssa_ranges.safe_grow_cleared (num_ssa_names);
}
-bool
-path_ranger::init (tree name)
+range_cache::~range_cache ()
{
- if (!irange_ssa (name))
- return false;
-
- def_stmt = SSA_NAME_DEF_STMT (name);
- if (!def_stmt)
- return false;
+ unsigned x;
+ for (x = 0; x < num_ssa_names; ++x)
+ {
+ if (ssa_ranges[x])
+ delete ssa_ranges[x];
+ }
+ ssa_ranges.release ();
+}
- ssa_name = name;
- def_bb = gimple_bb (def_stmt);
- if (!def_bb)
- def_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+ssa_range_cache&
+range_cache::operator[] (tree name)
+{
+ unsigned v = SSA_NAME_VERSION (name);
+ if (!ssa_ranges[v])
+ ssa_ranges[v] = new ssa_range_cache (TREE_TYPE (name));
- irange tr;
- tr.set_range_for_type (TREE_TYPE (name));
- type_range = irange_storage::ggc_alloc_init (tr);
+ return *(ssa_ranges[v]);
+}
- block_cache.reset ();
- block_cache.set_range (ENTRY_BLOCK_PTR_FOR_FN (cfun), type_range);
- return true;
+void
+range_cache::dump (FILE *f)
+{
+ unsigned x;
+ for (x = 0; x < num_ssa_names; ++x)
+ {
+ if (ssa_ranges[x])
+ {
+ fprintf (f, " Ranges for ");
+ print_generic_expr (f, ssa_name (x), 0);
+ fprintf (f, ":\n");
+ ssa_ranges[x]->dump (f);
+ }
+ }
+
+}
+// -------------------------------------------------------------------------
+path_ranger::path_ranger ()
+{
}
void
-path_ranger::range_for_bb (irange &r, basic_block bb)
+path_ranger::range_for_bb (irange &r, tree name, basic_block bb,
+ basic_block def_bb)
{
- determine_block (bb);
- irange tmp (block_cache[bb], TREE_TYPE (ssa_name));
- r = tmp;
+ bool res;
+ determine_block (name, bb, def_bb);
+ res = block_cache[name].get_range (r, bb);
+ gcc_assert (res);
}
bool
path_ranger::path_range_entry (irange& r, tree name, basic_block bb)
{
- if (!init (name))
+ gimple *def_stmt;
+ basic_block def_bb;
+
+ if (!irange_ssa (name))
+ return false;
+
+ def_stmt = SSA_NAME_DEF_STMT (name);
+ if (!def_stmt)
return false;
+ def_bb = gimple_bb (def_stmt);;
+ if (!def_bb)
+ def_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+
if (trace_path)
{
fprintf (dump_file, "path_range_entry BB%d on path for ", bb->index);
@@ -651,7 +708,7 @@ path_ranger::path_range_entry (irange& r, tree name, basic_block bb)
if (def_bb != bb)
{
irange block_range;
- range_for_bb (block_range, bb);
+ range_for_bb (block_range, name, bb, def_bb);
r.intersect (block_range);
}
@@ -661,7 +718,7 @@ path_ranger::path_range_entry (irange& r, tree name, basic_block bb)
print_generic_expr (dump_file, name, 0);
fprintf (dump_file, " in BB%d : returns ",bb->index);
r.dump (dump_file);
- block_cache.dump (dump_file, TREE_TYPE (name));
+ block_cache.dump (dump_file);
fprintf(dump_file, "\n");
}
@@ -688,7 +745,7 @@ path_ranger::path_range_edge (irange& r, tree name, edge e)
}
void
-path_ranger::determine_block (basic_block bb)
+path_ranger::determine_block (tree name, basic_block bb, basic_block def_bb)
{
edge_iterator ei;
edge e;
@@ -696,18 +753,19 @@ path_ranger::determine_block (basic_block bb)
irange block_result;
if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)
- || bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ || bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+ || bb == def_bb)
return;
if (trace_path)
fprintf (dump_file, "determine_block for BB%d\n", bb->index);
/* If the block cache is set, then we've already visited this block. */
- if (block_cache[bb] != NULL)
+ if (block_cache[name].range_p (bb))
return;
- /* Avoid infinite recursion by marking this block. */
- block_cache.set_range (bb, processing);
+ /* Avoid infinite recursion by marking this block as calculated. */
+ block_cache[name].set_range_for_type (bb);
if (trace_path)
fprintf (dump_file, "Visiting preds of BB%d\n", bb->index);
@@ -715,62 +773,58 @@ path_ranger::determine_block (basic_block bb)
/* Visit each predecessor to reseolve them. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
- determine_block (e->src);
+ determine_block (name, e->src, def_bb);
}
if (trace_path)
fprintf (dump_file, "Re-Visiting preds of BB%d\n", bb->index);
- block_result.clear (TREE_TYPE (ssa_name));
+ block_result.clear (TREE_TYPE (name));
/* Now Union all the ranges on the incoming edges. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
+ irange pred_range;
basic_block src = e->src;
if (trace_path)
fprintf (dump_file, " processing pred BB%d ", src->index);
- /* If a block is still unprocessed, we know nothing. */
- if (block_cache[src] == processing)
+
+ // Should be using range_on_def
+ if (src == def_bb)
+ pred_range.set_range (name);
+ else
{
- if (trace_path)
- fprintf (dump_file, " Cycle visit. range_for_type.\n");
- block_cache.set_range (bb, type_range);
- return;
+ bool res = block_cache[name].get_range (pred_range, src);
+ gcc_assert (res);
+ }
+
+ if (trace_path)
+ {
+ fprintf (dump_file, " No range on edge pred block range is: ");
+ pred_range.dump (dump_file);
}
- if (range_on_edge (er, ssa_name, e))
+ if (range_on_edge (er, name, e))
{
- irange pred_bb_range (block_cache[src], TREE_TYPE (ssa_name));
if (trace_path)
{
fprintf (dump_file, " edge has range : ");
er.dump (dump_file);
- fprintf (dump_file, " Pred has range : ");
- pred_bb_range.dump (dump_file);
-
}
- er.intersect (pred_bb_range);
- block_result.union_ (er);
+ pred_range.intersect (er);
+ er.intersect (pred_range);
if (trace_path)
{
- fprintf (dump_file, " result union range : ");
- block_result.dump (dump_file);
- }
- }
- else
- {
- /* If there is no range on the edge, it is the predecessor range. */
- irange pred_range (block_cache[src], TREE_TYPE (ssa_name));
- if (trace_path)
- {
- fprintf (dump_file, " No range on edge pred block range is: ");
+ fprintf (dump_file, " Edge intersect pred : ");
pred_range.dump (dump_file);
}
- block_result.union_ (pred_range);
- if (trace_path)
- {
- fprintf (dump_file, " result union range : ");
- block_result.dump (dump_file);
- }
+ }
+
+ block_result.union_ (pred_range);
+
+ if (trace_path)
+ {
+ fprintf (dump_file, " result union range : ");
+ block_result.dump (dump_file);
}
if (block_result.range_for_type_p ())
break;
@@ -782,12 +836,9 @@ path_ranger::determine_block (basic_block bb)
block_result.dump (dump_file);
}
if (block_result.range_for_type_p ())
- block_cache.set_range (bb, type_range);
+ block_cache[name].set_range_for_type (bb);
else
- {
- irange_storage *mem = irange_storage::ggc_alloc_init (block_result);
- block_cache.set_range (bb, mem);
- }
+ block_cache[name].set_range (bb, block_result);
}
bool
diff --git a/gcc/ssa-range-gen.h b/gcc/ssa-range-gen.h
index 98d69e73c5f..3f34acc8765 100644
--- a/gcc/ssa-range-gen.h
+++ b/gcc/ssa-range-gen.h
@@ -66,37 +66,46 @@ public:
-class range_cache
+class ssa_range_cache
{
private:
vec<irange_storage *> tab;
+ irange_storage *type_range;
+ const_tree type;
public:
- range_cache ();
- ~range_cache ();
+ ssa_range_cache (tree t);
+ ~ssa_range_cache ();
- void reset ();
- void set_range (basic_block bb, irange_storage *r);
- irange_storage *operator[] (const basic_block bb);
+ void set_range (const basic_block bb, const irange &r);
+ void set_range_for_type (const basic_block bb);
+ bool get_range (irange& r, const basic_block bb);
+ bool range_p (const basic_block bb);
- void dump(FILE *f, tree type);
+ void dump(FILE *f);
};
+class range_cache
+{
+private:
+ vec<ssa_range_cache *> ssa_ranges;
+public:
+ range_cache ();
+ ~range_cache ();
+ ssa_range_cache& operator[] (tree name);
+
+ void dump (FILE *f);
+};
+
/* This class utilizes the basic block GORI map and is used to query the range
of SSA_NAMEs across multiple basic blocks and edges. */
class path_ranger : public gori
{
private:
range_cache block_cache;
- tree ssa_name;
- basic_block def_bb;
- gimple *def_stmt;
- irange_storage *processing;
- irange_storage *type_range;
- bool init (tree name);
- void range_for_bb (irange &r, basic_block bb);
- void determine_block (basic_block bb);
+ void range_for_bb (irange &r, tree name, basic_block bb, basic_block def_bb);
+ void determine_block (tree name, basic_block bb, basic_block def_bb);
bool path_range_reverse (irange &r, tree name, const vec<basic_block> &);
public:
path_ranger ();