aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-relation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/value-relation.cc')
-rw-r--r--gcc/value-relation.cc260
1 files changed, 159 insertions, 101 deletions
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 08449b7..c96d438 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -202,12 +202,6 @@ adjust_equivalence_range (vrange &range)
}
}
-// This vector maps a relation to the equivalent tree code.
-
-static const tree_code relation_to_code [VREL_LAST] = {
- ERROR_MARK, ERROR_MARK, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR,
- NE_EXPR };
-
// Given an equivalence set EQUIV, set all the bits in B that are still valid
// members of EQUIV in basic block BB.
@@ -340,9 +334,10 @@ equiv_oracle::~equiv_oracle ()
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);
@@ -365,10 +360,10 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
// 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);
@@ -382,13 +377,13 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
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.
@@ -400,11 +395,11 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
{
// 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);
@@ -413,6 +408,7 @@ equiv_oracle::add_partial_equiv (relation_kind r, tree op1, tree op2)
pe1.members = pe2.members;
bitmap_set_bit (pe1.members, v1);
}
+ return true;
}
// Return the set of partial equivalences associated with NAME. The bitmap
@@ -627,19 +623,18 @@ equiv_oracle::register_initial_def (tree ssa)
// 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);
@@ -656,7 +651,7 @@ equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2)
// Check if they are the same set
if (equiv_1 && equiv_1 == equiv_2)
- return;
+ return false;
bitmap equiv_set;
@@ -680,9 +675,10 @@ equiv_oracle::record (basic_block bb, relation_kind k, tree ssa1, tree ssa2)
// 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.
@@ -780,15 +776,20 @@ equiv_oracle::dump (FILE *f) const
// --------------------------------------------------------------------------
-// Negate the current relation.
+
+// Adjust the relation by Swapping the operands and relation.
void
-value_relation::negate ()
+value_relation::swap ()
{
- related = relation_negate (related);
+ related = relation_swap (related);
+ tree tmp = name1;
+ name1 = name2;
+ name2 = tmp;
}
// Perform an intersection between 2 relations. *this &&= p.
+// Return false if the relations cannot be intersected.
bool
value_relation::intersect (value_relation &p)
@@ -951,6 +952,79 @@ public:
relation_chain *m_next;
};
+// Given relation record PTR in block BB, return the next relation in the
+// list. If PTR is NULL, retreive the first relation in BB.
+// If NAME is sprecified, return only relations which include NAME.
+// Return NULL when there are no relations left.
+
+relation_chain *
+dom_oracle::next_relation (basic_block bb, relation_chain *ptr,
+ tree name) const
+{
+ relation_chain *p;
+ // No value_relation pointer is used to intialize the iterator.
+ if (!ptr)
+ {
+ int bbi = bb->index;
+ if (bbi >= (int)m_relations.length())
+ return NULL;
+ else
+ p = m_relations[bbi].m_head;
+ }
+ else
+ p = ptr->m_next;
+
+ if (name)
+ for ( ; p; p = p->m_next)
+ if (p->op1 () == name || p->op2 () == name)
+ break;
+ return p;
+}
+
+// Instatiate a block relation iterator to iterate over the relations
+// on exit from block BB in ORACLE. Limit this to relations involving NAME
+// if specified. Return the first such relation in VR if there is one.
+
+block_relation_iterator::block_relation_iterator (const relation_oracle *oracle,
+ basic_block bb,
+ value_relation &vr,
+ tree name)
+{
+ m_oracle = oracle;
+ m_bb = bb;
+ m_name = name;
+ m_ptr = oracle->next_relation (bb, NULL, m_name);
+ if (m_ptr)
+ {
+ m_done = false;
+ vr = *m_ptr;
+ }
+ else
+ m_done = true;
+}
+
+// Retreive the next relation from the iterator and return it in VR.
+
+void
+block_relation_iterator::get_next_relation (value_relation &vr)
+{
+ m_ptr = m_oracle->next_relation (m_bb, m_ptr, m_name);
+ if (m_ptr)
+ {
+ vr = *m_ptr;
+ if (m_name)
+ {
+ if (vr.op1 () != m_name)
+ {
+ gcc_checking_assert (vr.op2 () == m_name);
+ vr.swap ();
+ }
+ }
+ }
+ else
+ m_done = true;
+}
+
// ------------------------------------------------------------------------
// Find the relation between any ssa_name in B1 and any name in B2 in LIST.
@@ -1001,8 +1075,9 @@ dom_oracle::~dom_oracle ()
}
// 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);
@@ -1011,16 +1086,7 @@ relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2)
// 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.
@@ -1034,22 +1100,26 @@ relation_oracle::record (gimple *stmt, relation_kind k, tree op1, tree op2)
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;
}
- record (gimple_bb (stmt), k, op1, op2);
+
+ 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);
+ }
+ 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);
@@ -1058,34 +1128,35 @@ relation_oracle::record (edge e, relation_kind k, tree op1, tree op2)
// 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,
@@ -1097,6 +1168,7 @@ dom_oracle::record (basic_block bb, relation_kind k, tree op1, tree op2)
&& (m_relations[bb->index].m_num_relations
< param_relation_block_limit))
register_transitives (bb, *ptr);
+ return ptr != NULL;
}
}
@@ -1129,33 +1201,16 @@ dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1,
// 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
@@ -1441,11 +1496,11 @@ dom_oracle::dump (FILE *f, basic_block bb) const
if (!m_relations[bb->index].m_names)
return;
- relation_chain *ptr = m_relations[bb->index].m_head;
- for (; ptr; ptr = ptr->m_next)
+ value_relation vr;
+ FOR_EACH_RELATION_BB (this, bb, vr)
{
fprintf (f, "Relational : ");
- ptr->dump (f);
+ vr.dump (f);
fprintf (f, "\n");
}
}
@@ -1513,9 +1568,9 @@ path_oracle::equiv_set (tree ssa, basic_block bb)
}
// 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);
@@ -1523,7 +1578,7 @@ path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
// 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);
@@ -1537,6 +1592,7 @@ path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2)
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.
@@ -1586,41 +1642,43 @@ path_oracle::killing_def (tree ssa)
}
// 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