/* Try to find a destination for indirect edge IE that corresponds to a simple
call or a call of a member function pointer and where the destination is a
pointer formal parameter described by jump function JFUNC. If it can be
- determined, return the newly direct edge, otherwise return NULL. */
+ determined, return the newly direct edge, otherwise return NULL.
+ NEW_ROOT_INFO is the node info that JFUNC lattices are relative to. */
static struct cgraph_edge *
try_make_edge_direct_simple_call (struct cgraph_edge *ie,
- struct ipa_jump_func *jfunc)
+ struct ipa_jump_func *jfunc,
+ struct ipa_node_params *new_root_info)
{
tree target;
if (ie->indirect_info->agg_contents)
- {
- target = ipa_find_agg_cst_for_param (&jfunc->agg,
- ie->indirect_info->offset,
- ie->indirect_info->by_ref);
- if (!target)
- return NULL;
- }
+ target = ipa_find_agg_cst_for_param (&jfunc->agg,
+ ie->indirect_info->offset,
+ ie->indirect_info->by_ref);
else
- {
- if (jfunc->type != IPA_JF_CONST)
- return NULL;
- target = ipa_get_jf_constant (jfunc);
- }
+ target = ipa_value_from_jfunc (new_root_info, jfunc);
+ if (!target)
+ return NULL;
return ipa_make_edge_direct_to_target (ie, target);
}
-/* Try to find a destination for indirect edge IE that corresponds to a
- virtual call based on a formal parameter which is described by jump
- function JFUNC and if it can be determined, make it direct and return the
- direct edge. Otherwise, return NULL. */
+/* Try to find a destination for indirect edge IE that corresponds to a virtual
+ call based on a formal parameter which is described by jump function JFUNC
+ and if it can be determined, make it direct and return the direct edge.
+ Otherwise, return NULL. NEW_ROOT_INFO is the node info that JFUNC lattices
+ are relative to. */
static struct cgraph_edge *
try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
- struct ipa_jump_func *jfunc)
+ struct ipa_jump_func *jfunc,
+ struct ipa_node_params *new_root_info)
{
tree binfo, target;
- if (jfunc->type != IPA_JF_KNOWN_TYPE)
+ binfo = ipa_value_from_jfunc (new_root_info, jfunc);
+
+ if (!binfo || TREE_CODE (binfo) != TREE_BINFO)
return NULL;
- binfo = TYPE_BINFO (ipa_get_jf_known_type_base_type (jfunc));
- gcc_checking_assert (binfo);
- binfo = get_binfo_at_offset (binfo, ipa_get_jf_known_type_offset (jfunc)
- + ie->indirect_info->offset,
+ binfo = get_binfo_at_offset (binfo, ie->indirect_info->offset,
ie->indirect_info->otr_type);
if (binfo)
target = gimple_get_virt_method_for_binfo (ie->indirect_info->otr_token,
{
struct ipa_edge_args *top;
struct cgraph_edge *ie, *next_ie, *new_direct_edge;
+ struct ipa_node_params *new_root_info;
bool res = false;
ipa_check_create_edge_args ();
top = IPA_EDGE_REF (cs);
+ new_root_info = IPA_NODE_REF (cs->caller->global.inlined_to
+ ? cs->caller->global.inlined_to
+ : cs->caller);
for (ie = node->indirect_calls; ie; ie = next_ie)
{
continue;
if (ici->polymorphic)
- new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc);
+ new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc,
+ new_root_info);
else
- new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc);
+ new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc,
+ new_root_info);
if (new_direct_edge)
{
{
tree expr, base, off;
location_t loc;
+ unsigned int deref_align;
+ bool deref_base = false;
/* We create a new parameter out of the value of the old one, we can
do the following kind of transformations:
{
HOST_WIDE_INT base_offset;
tree prev_base;
+ bool addrof;
if (TREE_CODE (base) == ADDR_EXPR)
- base = TREE_OPERAND (base, 0);
+ {
+ base = TREE_OPERAND (base, 0);
+ addrof = true;
+ }
+ else
+ addrof = false;
prev_base = base;
base = get_addr_base_and_unit_offset (base, &base_offset);
/* Aggregate arguments can have non-invariant addresses. */
}
else if (TREE_CODE (base) == MEM_REF)
{
+ if (!addrof)
+ {
+ deref_base = true;
+ deref_align = TYPE_ALIGN (TREE_TYPE (base));
+ }
off = build_int_cst (adj->alias_ptr_type,
base_offset
+ adj->offset / BITS_PER_UNIT);
unsigned int align;
unsigned HOST_WIDE_INT misalign;
- get_pointer_alignment_1 (base, &align, &misalign);
+ if (deref_base)
+ {
+ align = deref_align;
+ misalign = 0;
+ }
+ else
+ {
+ get_pointer_alignment_1 (base, &align, &misalign);
+ if (TYPE_ALIGN (type) > align)
+ align = TYPE_ALIGN (type);
+ }
misalign += (tree_to_double_int (off)
.sext (TYPE_PRECISION (TREE_TYPE (off))).low
* BITS_PER_UNIT);