add_graph_edge (graph, newe);
olde.src = from;
olde.dest = c->dest;
+ olde.weights = NULL;
temp = get_graph_weights (graph, olde);
weights = get_graph_weights (graph, newe);
bitmap_ior_into (weights, temp);
add_graph_edge (graph, newe);
olde.src = c->dest;
olde.dest = from;
+ olde.weights = NULL;
temp = get_graph_weights (graph, olde);
weights = get_graph_weights (graph, newe);
bitmap_ior_into (weights, temp);
struct constraint_edge edge;
edge.src = to;
edge.dest = from;
+ edge.weights = NULL;
r = add_graph_edge (graph, edge);
r |= !bitmap_bit_p (get_graph_weights (graph, edge), weight);
bitmap_set_bit (get_graph_weights (graph, edge), weight);
merge_graph_nodes (graph, to, from);
edge.src = to;
edge.dest = to;
+ edge.weights = NULL;
if (valid_graph_edge (graph, edge))
{
bitmap weights = get_graph_weights (graph, edge);
bitmap_clear (tmp);
edge.src = n;
edge.dest = n;
+ edge.weights = NULL;
if (valid_graph_edge (graph, edge))
{
bitmap weights = get_graph_weights (graph, edge);
tree op, var;
var_ann_t v_ann;
struct ptr_info_def *pi;
- bool is_store;
+ bool is_store, is_potential_deref;
unsigned num_uses, num_derefs;
op = USE_FROM_PTR (use_p);
is an escape point, whether OP escapes. */
count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
- if (num_derefs > 0)
+ /* Handle a corner case involving address expressions of the
+ form '&PTR->FLD'. The problem with these expressions is that
+ they do not represent a dereference of PTR. However, if some
+ other transformation propagates them into an INDIRECT_REF
+ expression, we end up with '*(&PTR->FLD)' which is folded
+ into 'PTR->FLD'.
+
+ So, if the original code had no other dereferences of PTR,
+ the aliaser will not create memory tags for it, and when
+ &PTR->FLD gets propagated to INDIRECT_REF expressions, the
+ memory operations will receive no V_MAY_DEF/VUSE operands.
+
+ One solution would be to have count_uses_and_derefs consider
+ &PTR->FLD a dereference of PTR. But that is wrong, since it
+ is not really a dereference but an offset calculation.
+
+ What we do here is to recognize these special ADDR_EXPR
+ nodes. Since these expressions are never GIMPLE values (they
+ are not GIMPLE invariants), they can only appear on the RHS
+ of an assignment and their base address is always an
+ INDIRECT_REF expression. */
+ is_potential_deref = false;
+ if (TREE_CODE (stmt) == MODIFY_EXPR
+ && TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
+ && !is_gimple_val (TREE_OPERAND (stmt, 1)))
+ {
+ /* If the RHS if of the form &PTR->FLD and PTR == OP, then
+ this represents a potential dereference of PTR. */
+ tree rhs = TREE_OPERAND (stmt, 1);
+ tree base = get_base_address (TREE_OPERAND (rhs, 0));
+ if (TREE_CODE (base) == INDIRECT_REF
+ && TREE_OPERAND (base, 0) == op)
+ is_potential_deref = true;
+ }
+
+ if (num_derefs > 0 || is_potential_deref)
{
/* Mark OP as dereferenced. In a subsequent pass,
dereferenced pointers that point to a set of
/* Return true if we actually need to solve the constraint graph in order to
get our points-to sets. This is false when, for example, no addresses are
taken other than special vars, or all points-to sets with members already
- contain the anything variable. */
+ contain the anything variable and there are no predecessors for other
+ sets. */
static bool
need_to_solve (void)
&& !bitmap_empty_p (v->solution)
&& !bitmap_bit_p (v->solution, anything_id))
found_non_anything = true;
+ else if (bitmap_empty_p (v->solution)
+ && VEC_length (constraint_edge_t, graph->preds[v->id]) != 0)
+ found_non_anything = true;
if (found_address_taken && found_non_anything)
return true;