tem1.type = TREE_TYPE (tem1.op0);
tem1.opcode = TREE_CODE (tem1.op0);
vro1 = &tem1;
+ deref1 = false;
}
if (deref2 && vro2->opcode == ADDR_EXPR)
{
tem2.type = TREE_TYPE (tem2.op0);
tem2.opcode = TREE_CODE (tem2.op0);
vro2 = &tem2;
+ deref2 = false;
}
+ if (deref1 != deref2)
+ return false;
if (!vn_reference_op_eq (vro1, vro2))
return false;
++j;
switch (temp.opcode)
{
+ case WITH_SIZE_EXPR:
+ temp.op0 = TREE_OPERAND (ref, 1);
+ temp.off = 0;
+ break;
case MEM_REF:
/* The base address gets its own vn_reference_op_s structure. */
temp.op0 = TREE_OPERAND (ref, 1);
VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
if (REFERENCE_CLASS_P (ref)
+ || TREE_CODE (ref) == WITH_SIZE_EXPR
|| (TREE_CODE (ref) == ADDR_EXPR
&& !is_gimple_min_invariant (ref)))
ref = TREE_OPERAND (ref, 0);
ref->base_alias_set = base_alias_set;
else
ref->base_alias_set = get_alias_set (base);
+ /* We discount volatiles from value-numbering elsewhere. */
+ ref->volatile_p = false;
return true;
}
return NULL;
}
+/* Lookup an existing or insert a new vn_reference entry into the
+ value table for the VUSE, SET, TYPE, OPERANDS reference which
+ has the value VALUE which is either a constant or an SSA name. */
+
+static vn_reference_t
+vn_reference_lookup_or_insert_for_pieces (tree vuse,
+ alias_set_type set,
+ tree type,
+ VEC (vn_reference_op_s,
+ heap) *operands,
+ tree value)
+{
+ struct vn_reference_s vr1;
+ vn_reference_t result;
+ unsigned value_id;
+ vr1.vuse = vuse;
+ vr1.operands = operands;
+ vr1.type = type;
+ vr1.set = set;
+ vr1.hashcode = vn_reference_compute_hash (&vr1);
+ if (vn_reference_lookup_1 (&vr1, &result))
+ return result;
+ if (TREE_CODE (value) == SSA_NAME)
+ value_id = VN_INFO (value)->value_id;
+ else
+ value_id = get_or_alloc_constant_value_id (value);
+ return vn_reference_insert_pieces (vuse, set, type,
+ VEC_copy (vn_reference_op_s, heap,
+ operands), value, value_id);
+}
+
/* Callback for walk_non_aliased_vuses. Tries to perform a lookup
from the statement defining VUSE and if not successful tries to
translate *REFP and VR_ through an aggregate copy at the defintion
if (maxsize == -1)
return (void *)-1;
+ /* We can't deduce anything useful from clobbers. */
+ if (gimple_clobber_p (def_stmt))
+ return (void *)-1;
+
/* def_stmt may-defs *ref. See if we can derive a value for *ref
- from that defintion.
+ from that definition.
1) Memset. */
if (is_gimple_reg_type (vr->type)
&& gimple_call_builtin_p (def_stmt, BUILT_IN_MEMSET)
&& offset2 + size2 >= offset + maxsize)
{
tree val = build_zero_cst (vr->type);
- unsigned int value_id = get_or_alloc_constant_value_id (val);
- return vn_reference_insert_pieces (vuse, vr->set, vr->type,
- VEC_copy (vn_reference_op_s,
- heap, vr->operands),
- val, value_id);
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
}
}
&& offset2 + size2 >= offset + maxsize)
{
tree val = build_zero_cst (vr->type);
- unsigned int value_id = get_or_alloc_constant_value_id (val);
- return vn_reference_insert_pieces (vuse, vr->set, vr->type,
- VEC_copy (vn_reference_op_s,
- heap, vr->operands),
- val, value_id);
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
}
}
/ BITS_PER_UNIT),
ref->size / BITS_PER_UNIT);
if (val)
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
+ }
+ }
+ }
+
+ /* 4) Assignment from an SSA name which definition we may be able
+ to access pieces from. */
+ else if (ref->size == maxsize
+ && is_gimple_reg_type (vr->type)
+ && gimple_assign_single_p (def_stmt)
+ && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
+ {
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs1);
+ if (is_gimple_assign (def_stmt2)
+ && (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR
+ || gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR)
+ && types_compatible_p (vr->type, TREE_TYPE (TREE_TYPE (rhs1))))
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2, off;
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2);
+ off = offset - offset2;
+ if (maxsize2 != -1
+ && maxsize2 == size2
+ && operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ tree val = NULL_TREE;
+ HOST_WIDE_INT elsz
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1))));
+ if (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR)
{
- unsigned int value_id = get_or_alloc_constant_value_id (val);
- return vn_reference_insert_pieces
- (vuse, vr->set, vr->type,
- VEC_copy (vn_reference_op_s, heap, vr->operands),
- val, value_id);
+ if (off == 0)
+ val = gimple_assign_rhs1 (def_stmt2);
+ else if (off == elsz)
+ val = gimple_assign_rhs2 (def_stmt2);
}
+ else if (gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR
+ && off % elsz == 0)
+ {
+ tree ctor = gimple_assign_rhs1 (def_stmt2);
+ unsigned i = off / elsz;
+ if (i < CONSTRUCTOR_NELTS (ctor))
+ {
+ constructor_elt *elt = CONSTRUCTOR_ELT (ctor, i);
+ if (compare_tree_int (elt->index, i) == 0)
+ val = elt->value;
+ }
+ }
+ if (val)
+ return vn_reference_lookup_or_insert_for_pieces
+ (vuse, vr->set, vr->type, vr->operands, val);
}
}
}
- /* 4) For aggregate copies translate the reference through them if
+ /* 5) For aggregate copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& gimple_assign_single_p (def_stmt)
FOR_EACH_VEC_ELT (vn_reference_op_s, rhs, j, vro)
VEC_replace (vn_reference_op_s, vr->operands, i + 1 + j, vro);
VEC_free (vn_reference_op_s, heap, rhs);
+ vr->operands = valueize_refs (vr->operands);
vr->hashcode = vn_reference_compute_hash (vr);
/* Adjust *ref from the new operands. */
return NULL;
}
- /* 5) For memcpy copies translate the reference through them if
+ /* 6) For memcpy copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& is_gimple_reg_type (vr->type)
tree var;
unsigned int i;
- fprintf (out, "SCC consists of: ");
+ fprintf (out, "SCC consists of:");
FOR_EACH_VEC_ELT (tree, scc, i, var)
{
- print_generic_expr (out, var, 0);
fprintf (out, " ");
+ print_generic_expr (out, var, 0);
}
fprintf (out, "\n");
}
if (gimple_code (stmt) == GIMPLE_PHI)
changed = visit_phi (stmt);
else if (!gimple_has_lhs (stmt)
- || gimple_has_volatile_ops (stmt)
- || stmt_could_throw_p (stmt))
+ || gimple_has_volatile_ops (stmt))
changed = defs_to_varying (stmt);
else if (is_gimple_assign (stmt))
{