return VREL_VARYING;
}
-// Default registers nothing.
+// Default registers nothing and returns false meaning nothing changed.
-void
+bool
fur_source::register_relation (gimple *s ATTRIBUTE_UNUSED,
relation_kind k ATTRIBUTE_UNUSED,
tree op1 ATTRIBUTE_UNUSED,
tree op2 ATTRIBUTE_UNUSED)
{
+ return false;
}
-// Default registers nothing.
+// Default registers nothing and returns false meaning nothing changed.
-void
+bool
fur_source::register_relation (edge e ATTRIBUTE_UNUSED,
relation_kind k ATTRIBUTE_UNUSED,
tree op1 ATTRIBUTE_UNUSED,
tree op2 ATTRIBUTE_UNUSED)
{
+ return false;
}
// Get the value of EXPR on edge m_edge.
m_depend_p = true;
}
-// Register a relation on a stmt if there is an oracle.
+// Register a relation on a stmt if there is an oracle. Return false if
+// no new relation is registered.
-void
+bool
fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2)
{
- m_query->relation ().record (s, k, op1, op2);
+ if (!m_query->relation ().record (s, k, op1, op2))
+ return false;
+
// This new relation could cause different calculations, so mark the operands
// with a new timestamp, forcing recalculations.
if (m_cache)
m_cache->update_consumers (op1);
m_cache->update_consumers (op2);
}
+ return true;
}
-// Register a relation on an edge if there is an oracle.
+// Register a relation on an edge if there is an oracle. Return false if
+// no new relation is registered.
-void
+bool
fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
{
- m_query->relation ().record (e, k, op1, op2);
+ if (!m_query->relation ().record (e, k, op1, op2))
+ return false;
+
// This new relation could cause different calculations, so mark the operands
// with a new timestamp, forcing recalculations.
if (m_cache)
m_cache->update_consumers (op1);
m_cache->update_consumers (op2);
}
+ return true;
}
// This version of fur_source will pick a range up from a list of ranges
{
public:
fur_relation (gimple *s, range_query *q = NULL);
- virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
+ virtual bool register_relation (gimple *stmt, relation_kind k, tree op1,
tree op2);
- virtual void register_relation (edge e, relation_kind k, tree op1,
+ virtual bool register_relation (edge e, relation_kind k, tree op1,
tree op2);
relation_trio trio() const;
private:
}
// Don't support edges, but avoid a compiler warning by providing the routine.
+// Return false indicating nothing has changed.
-void
+bool
fur_relation::register_relation (edge, relation_kind, tree, tree)
{
+ return false;
}
-// Register relation K between OP1 and OP2 on STMT.
+// Register relation K between OP1 and OP2 on STMT. Return false if there
+// is no relation.
-void
+bool
fur_relation::register_relation (gimple *stmt, relation_kind k, tree op1,
tree op2)
{
else if (op2 == a1 && op1 == a2)
op1_op2 = relation_swap (k);
}
+ return def_op1 == VREL_VARYING && def_op2 == VREL_VARYING
+ && op1_op2 == VREL_VARYING;
}
// Return the relation trio for stmt S using query Q.
bitmap_obstack_release (&m_bitmaps);
}
-// Add a partial equivalence R between OP1 and OP2.
+// Add a partial equivalence R between OP1 and OP2. Return false if no
+// new relation is added.
-void
+bool
equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
{
int v1 = SSA_NAME_VERSION (op1);
// being re-evaluated, or the def was used before being registered.
// In either case, if PE2 has an entry, we simply do nothing.
if (pe2.members)
- return;
+ return false;
// If there are no uses of op2, do not register.
if (has_zero_uses (op2))
- return;
+ return false;
// PE1 is the LHS and already has members, so everything in the set
// should be a slice of PE2 rather than PE1.
pe2.code = pe_min (r, pe1.code);
m_partial[x].code = pe_min (m_partial[x].code, pe2.code);
}
bitmap_set_bit (pe1.members, v2);
- return;
+ return true;
}
if (pe2.members)
{
// If there are no uses of op1, do not register.
if (has_zero_uses (op1))
- return;
+ return false;
pe1.ssa_base = pe2.ssa_base;
// If pe2 is a 16 bit value, but only an 8 bit copy, we can't be any
// more than an 8 bit equivalence here, so choose MIN value.
{
// If there are no uses of either operand, do not register.
if (has_zero_uses (op1) || has_zero_uses (op2))
- return;
+ return false;
// Neither name has an entry, simply create op1 as slice of op2.
pe2.code = bits_to_pe (TYPE_PRECISION (TREE_TYPE (op2)));
if (pe2.code == VREL_VARYING)
- return;
+ return false;
pe2.ssa_base = op2;
pe2.members = BITMAP_ALLOC (&m_bitmaps);
bitmap_set_bit (pe2.members, v2);
pe1.members = pe2.members;
bitmap_set_bit (pe1.members, v1);
}
+ return true;
}
// Return the set of partial equivalences associated with NAME. The bitmap
// a query is made as to what equivalences both names have already, and
// any preexisting equivalences are merged to create a single equivalence
// containing all the ssa_names in this basic block.
+// Return false if no new relation is added.
-void
+bool
equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2)
{
// Process partial equivalencies.
if (relation_partial_equiv_p (k))
- {
- add_partial_equiv (k, ssa1, ssa2);
- return;
- }
+ return add_partial_equiv (k, ssa1, ssa2);
+
// Only handle equality relations.
if (k != VREL_EQ)
- return;
+ return false;
unsigned v1 = SSA_NAME_VERSION (ssa1);
unsigned v2 = SSA_NAME_VERSION (ssa2);
// Check if they are the same set
if (equiv_1 && equiv_1 == equiv_2)
- return;
+ return false;
bitmap equiv_set;
// A non-null return is a bitmap that is to be added to the current
// block as a new equivalence.
if (!equiv_set)
- return;
+ return false;
add_equiv_to_block (bb, equiv_set);
+ return true;
}
// Add an equivalency record in block BB containing bitmap EQUIV_SET.
}
// Register relation K between ssa_name OP1 and OP2 on STMT.
+// Return false if no new relation is added.
-void
+bool
relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2)
{
gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
// Don't register lack of a relation.
if (k == VREL_VARYING)
- return;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- value_relation vr (k, op1, op2);
- fprintf (dump_file, " Registering value_relation ");
- vr.dump (dump_file);
- fprintf (dump_file, " (bb%d) at ", gimple_bb (stmt)->index);
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- }
+ return false;
// If an equivalence is being added between a PHI and one of its arguments
// make sure that that argument is not defined in the same block.
if (phi_def == op2)
arg = op1;
if (gimple_bb (stmt) == gimple_bb (SSA_NAME_DEF_STMT (arg)))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, " Not registered due to ");
- print_generic_expr (dump_file, arg, TDF_SLIM);
- fprintf (dump_file, " being defined in the same block.\n");
- }
- return;
- }
+ return false;
+ }
+
+ bool ret = record (gimple_bb (stmt), k, op1, op2);
+
+ if (ret && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ value_relation vr (k, op1, op2);
+ fprintf (dump_file, " Registering value_relation ");
+ vr.dump (dump_file);
+ fprintf (dump_file, " (bb%d) at ", gimple_bb (stmt)->index);
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
- record (gimple_bb (stmt), k, op1, op2);
+ return ret;
}
// Register relation K between ssa_name OP1 and OP2 on edge E.
+// Return false if no new relation is added.
-void
+bool
relation_oracle::record (edge e, relation_kind k, tree op1, tree op2)
{
gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
// Do not register lack of relation, or blocks which have more than
// edge E for a predecessor.
if (k == VREL_VARYING || !single_pred_p (e->dest))
- return;
+ return false;
- if (dump_file && (dump_flags & TDF_DETAILS))
+ bool ret = record (e->dest, k, op1, op2);
+
+ if (ret && dump_file && (dump_flags & TDF_DETAILS))
{
value_relation vr (k, op1, op2);
fprintf (dump_file, " Registering value_relation ");
vr.dump (dump_file);
fprintf (dump_file, " on (%d->%d)\n", e->src->index, e->dest->index);
}
-
- record (e->dest, k, op1, op2);
+ return ret;
}
// Register relation K between OP! and OP2 in block BB.
// This creates the record and searches for existing records in the dominator
-// tree to merge with.
+// tree to merge with. Return false if no new relation is added.
-void
+bool
dom_oracle::record (basic_block bb, relation_kind k, tree op1, tree op2)
{
// If the 2 ssa_names are the same, do nothing. An equivalence is implied,
// and no other relation makes sense.
if (op1 == op2)
- return;
+ return false;
// Equivalencies are handled by the equivalence oracle.
if (relation_equiv_p (k))
- equiv_oracle::record (bb, k, op1, op2);
+ return equiv_oracle::record (bb, k, op1, op2);
else
{
// if neither op1 nor op2 are in a relation before this is registered,
&& (m_relations[bb->index].m_num_relations
< param_relation_block_limit))
register_transitives (bb, *ptr);
+ return ptr != NULL;
}
}
// There is an existing relation in this block, just intersect with it.
if (curr != VREL_VARYING)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, " Intersecting with existing ");
- ptr->dump (dump_file);
- }
// Check into whether we can simply replace the relation rather than
// intersecting it. This may help with some optimistic iterative
- // updating algorithms.
- bool new_rel = ptr->intersect (vr);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, " to produce ");
- ptr->dump (dump_file);
- fprintf (dump_file, " %s.\n", new_rel ? "Updated" : "No Change");
- }
- // If there was no change, return no record..
- if (!new_rel)
+ // updating algorithms. If there was no change, return no record..
+ if (!ptr->intersect (vr))
return NULL;
}
else
{
if (m_relations[bbi].m_num_relations >= param_relation_block_limit)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Not registered due to bb being full\n");
- return NULL;
- }
+ return NULL;
m_relations[bbi].m_num_relations++;
// Check for an existing relation further up the DOM chain.
// By including dominating relations, The first one found in any search
}
// Register an equivalence between SSA1 and SSA2 resolving unknowns from
-// block BB.
+// block BB. Return false if no new equivalence was added.
-void
+bool
path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
{
const_bitmap equiv_1 = equiv_set (ssa1, bb);
// Check if they are the same set, if so, we're done.
if (bitmap_equal_p (equiv_1, equiv_2))
- return;
+ return false;
// Don't mess around, simply create a new record and insert it first.
bitmap b = BITMAP_ALLOC (&m_bitmaps);
ptr->m_next = m_equiv.m_next;
m_equiv.m_next = ptr;
bitmap_ior_into (m_equiv.m_names, b);
+ return true;
}
// Register killing definition of an SSA_NAME.
}
// Register relation K between SSA1 and SSA2, resolving unknowns by
-// querying from BB.
+// querying from BB. Return false if no new relation is registered.
-void
+bool
path_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2)
{
// If the 2 ssa_names are the same, do nothing. An equivalence is implied,
// and no other relation makes sense.
if (ssa1 == ssa2)
- return;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- value_relation vr (k, ssa1, ssa2);
- fprintf (dump_file, " Registering value_relation (path_oracle) ");
- vr.dump (dump_file);
- fprintf (dump_file, " (root: bb%d)\n", bb->index);
- }
+ return false;
relation_kind curr = query (bb, ssa1, ssa2);
if (curr != VREL_VARYING)
k = relation_intersect (curr, k);
+ bool ret;
if (k == VREL_EQ)
+ ret = register_equiv (bb, ssa1, ssa2);
+ else
{
- register_equiv (bb, ssa1, ssa2);
- return;
+ bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1));
+ bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa2));
+ relation_chain *ptr = (relation_chain *) obstack_alloc (&m_chain_obstack,
+ sizeof (relation_chain));
+ ptr->set_relation (k, ssa1, ssa2);
+ ptr->m_next = m_relations.m_head;
+ m_relations.m_head = ptr;
+ ret = true;
}
- bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa1));
- bitmap_set_bit (m_relations.m_names, SSA_NAME_VERSION (ssa2));
- relation_chain *ptr = (relation_chain *) obstack_alloc (&m_chain_obstack,
- sizeof (relation_chain));
- ptr->set_relation (k, ssa1, ssa2);
- ptr->m_next = m_relations.m_head;
- m_relations.m_head = ptr;
+ if (ret && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ value_relation vr (k, ssa1, ssa2);
+ fprintf (dump_file, " Registering value_relation (path_oracle) ");
+ vr.dump (dump_file);
+ fprintf (dump_file, " (root: bb%d)\n", bb->index);
+ }
+ return ret;
}
// Query for a relationship between equiv set B1 and B2, resolving unknowns
virtual ~relation_oracle () { }
// register a relation between 2 ssa names.
- void record (gimple *, relation_kind, tree, tree);
- void record (edge, relation_kind, tree, tree);
- virtual void record (basic_block, relation_kind, tree, tree) { }
+ bool record (gimple *, relation_kind, tree, tree);
+ bool record (edge, relation_kind, tree, tree);
+ virtual bool record (basic_block, relation_kind, tree, tree) { return false; }
// Query if there is any relation between SSA1 and SSA2.
relation_kind query (gimple *s, tree ssa1, tree ssa2);
~equiv_oracle ();
const_bitmap equiv_set (tree ssa, basic_block bb) final override;
- void record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) override;
+ bool record (basic_block bb, relation_kind k, tree ssa1, tree ssa2) override;
relation_kind partial_equiv (tree ssa1, tree ssa2, tree *base = NULL) const;
relation_kind query (basic_block, tree, tree) override;
void dump (FILE *f) const override;
protected:
- void add_partial_equiv (relation_kind, tree, tree);
+ bool add_partial_equiv (relation_kind, tree, tree);
const pe_slice *partial_equiv_set (tree name) final override;
inline bool has_equiv_p (unsigned v) { return bitmap_bit_p (m_equiv_set, v); }
bitmap_obstack m_bitmaps;
dom_oracle (bool do_trans_p = true);
~dom_oracle ();
- void record (basic_block bb, relation_kind k, tree op1, tree op2)
+ bool record (basic_block bb, relation_kind k, tree op1, tree op2)
final override;
relation_kind query (basic_block bb, tree ssa1, tree ssa2) final override;
path_oracle (relation_oracle *oracle = NULL);
~path_oracle ();
const_bitmap equiv_set (tree, basic_block) final override;
- void record (basic_block, relation_kind, tree, tree) final override;
+ bool record (basic_block, relation_kind, tree, tree) final override;
void killing_def (tree);
relation_kind query (basic_block, tree, tree) final override;
relation_kind query (basic_block, const_bitmap, const_bitmap) final override;
void dump (FILE *, basic_block) const final override;
void dump (FILE *) const final override;
private:
- void register_equiv (basic_block bb, tree ssa1, tree ssa2);
+ bool register_equiv (basic_block bb, tree ssa1, tree ssa2);
equiv_chain m_equiv;
relation_chain_head m_relations;
relation_oracle *m_root;