/* Vector where the parameter infos are actually stored. */
VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector;
-/* Bitmap with all UIDs of call graph edges that have been already processed
- by indirect inlining. */
-static bitmap iinlining_processed_edges;
-
/* Holders of ipa cgraph hooks: */
static struct cgraph_edge_hook_list *edge_removal_hook_holder;
static struct cgraph_node_hook_list *node_removal_hook_holder;
fprintf (f, "UNKNOWN\n");
else if (type == IPA_JF_KNOWN_TYPE)
{
- tree binfo_type = TREE_TYPE (jump_func->value.base_binfo);
- fprintf (f, "KNOWN TYPE, type in binfo is: ");
- print_generic_expr (f, binfo_type, 0);
- fprintf (f, " (%u)\n", TYPE_UID (binfo_type));
+ fprintf (f, "KNOWN TYPE: base ");
+ print_generic_expr (f, jump_func->value.known_type.base_type, 0);
+ fprintf (f, ", offset "HOST_WIDE_INT_PRINT_DEC", component ",
+ jump_func->value.known_type.offset);
+ print_generic_expr (f, jump_func->value.known_type.component_type, 0);
+ fprintf (f, "\n");
}
else if (type == IPA_JF_CONST)
{
tree_code_name[(int)
jump_func->value.pass_through.operation]);
if (jump_func->value.pass_through.operation != NOP_EXPR)
- print_generic_expr (dump_file,
+ print_generic_expr (f,
jump_func->value.pass_through.operand, 0);
- fprintf (dump_file, "\n");
+ fprintf (f, "\n");
}
else if (type == IPA_JF_ANCESTOR)
{
jump_func->value.ancestor.formal_id,
jump_func->value.ancestor.offset);
print_generic_expr (f, jump_func->value.ancestor.type, 0);
- fprintf (dump_file, "\n");
+ fprintf (f, "\n");
}
}
}
gimple call)
{
HOST_WIDE_INT offset, size, max_size;
- tree base, binfo;
+ tree base;
if (!flag_devirtualize
|| TREE_CODE (op) != ADDR_EXPR
|| is_global_var (base))
return;
- if (detect_type_change (op, base, call, jfunc, offset))
+ if (detect_type_change (op, base, call, jfunc, offset)
+ || !TYPE_BINFO (TREE_TYPE (base)))
return;
- binfo = TYPE_BINFO (TREE_TYPE (base));
- if (!binfo)
- return;
- binfo = get_binfo_at_offset (binfo, offset, TREE_TYPE (op));
- if (binfo)
- {
- jfunc->type = IPA_JF_KNOWN_TYPE;
- jfunc->value.base_binfo = binfo;
- }
+ jfunc->type = IPA_JF_KNOWN_TYPE;
+ jfunc->value.known_type.base_type = TREE_TYPE (base);
+ jfunc->value.known_type.offset = offset;
+ jfunc->value.known_type.component_type = TREE_TYPE (op);
}
combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src,
struct ipa_jump_func *dst)
{
- tree new_binfo;
+ HOST_WIDE_INT combined_offset;
+ tree combined_type;
- new_binfo = get_binfo_at_offset (src->value.base_binfo,
- dst->value.ancestor.offset,
- dst->value.ancestor.type);
- if (new_binfo)
- {
- dst->type = IPA_JF_KNOWN_TYPE;
- dst->value.base_binfo = new_binfo;
- }
- else
- dst->type = IPA_JF_UNKNOWN;
+ combined_offset = src->value.known_type.offset + dst->value.ancestor.offset;
+ combined_type = dst->value.ancestor.type;
+
+ dst->type = IPA_JF_KNOWN_TYPE;
+ dst->value.known_type.base_type = src->value.known_type.base_type;
+ dst->value.known_type.offset = combined_offset;
+ dst->value.known_type.component_type = combined_type;
}
/* Update the jump functions associated with call graph edge E when the call
try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
struct ipa_jump_func *jfunc)
{
- tree binfo, type, target;
- HOST_WIDE_INT token;
-
- if (jfunc->type == IPA_JF_KNOWN_TYPE)
- binfo = jfunc->value.base_binfo;
- else
- return NULL;
+ tree binfo, target;
- if (!binfo)
+ if (jfunc->type != IPA_JF_KNOWN_TYPE)
return NULL;
- token = ie->indirect_info->otr_token;
- type = ie->indirect_info->otr_type;
- binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type);
+ binfo = TYPE_BINFO (jfunc->value.known_type.base_type);
+ gcc_checking_assert (binfo);
+ binfo = get_binfo_at_offset (binfo, jfunc->value.known_type.offset
+ + ie->indirect_info->anc_offset,
+ ie->indirect_info->otr_type);
if (binfo)
- target = gimple_get_virt_method_for_binfo (token, binfo);
+ target = gimple_get_virt_method_for_binfo (ie->indirect_info->otr_token,
+ binfo);
else
return NULL;
struct ipa_jump_func *jfunc;
next_ie = ie->next_callee;
- if (bitmap_bit_p (iinlining_processed_edges, ie->uid))
- continue;
- /* If we ever use indirect edges for anything other than indirect
- inlining, we will need to skip those with negative param_indices. */
if (ici->param_index == -1)
continue;
/* We must check range due to calls with variable number of arguments: */
if (ici->param_index >= ipa_get_cs_argument_count (top))
{
- bitmap_set_bit (iinlining_processed_edges, ie->uid);
+ ici->param_index = -1;
continue;
}
}
else
/* Either we can find a destination for this edge now or never. */
- bitmap_set_bit (iinlining_processed_edges, ie->uid);
+ ici->param_index = -1;
+
+ if (!flag_indirect_inlining)
+ continue;
if (ici->polymorphic)
new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc);
res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges);
else
update_jump_functions_after_inlining (cs, e);
+ for (e = node->indirect_calls; e; e = e->next_callee)
+ update_jump_functions_after_inlining (cs, e);
return res;
}
ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges)
{
+ bool changed;
/* Do nothing if the preparation phase has not been carried out yet
(i.e. during early inlining). */
if (!ipa_node_params_vector)
return false;
gcc_assert (ipa_edge_args_vector);
- return propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
+ changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
+
+ /* We do not keep jump functions of inlined edges up to date. Better to free
+ them so we do not access them accidentally. */
+ ipa_free_edge_args_substructures (IPA_EDGE_REF (cs));
+ return changed;
}
/* Frees all dynamically allocated structures that the argument info points
new_args->jump_functions = VEC_copy (ipa_jump_func_t, gc,
old_args->jump_functions);
-
- if (iinlining_processed_edges
- && bitmap_bit_p (iinlining_processed_edges, src->uid))
- bitmap_set_bit (iinlining_processed_edges, dst->uid);
}
/* Hook that is called by cgraph.c when a node is duplicated. */
function_insertion_hook_holder = NULL;
}
-/* Allocate all necessary data structures necessary for indirect inlining. */
-
-void
-ipa_create_all_structures_for_iinln (void)
-{
- iinlining_processed_edges = BITMAP_ALLOC (NULL);
-}
-
/* Free all ipa_node_params and all ipa_edge_args structures if they are no
longer needed after ipa-cp. */
void
ipa_free_all_structures_after_ipa_cp (void)
{
- if (!flag_indirect_inlining)
+ if (!optimize)
{
ipa_free_all_edge_args ();
ipa_free_all_node_params ();
void
ipa_free_all_structures_after_iinln (void)
{
- BITMAP_FREE (iinlining_processed_edges);
-
ipa_free_all_edge_args ();
ipa_free_all_node_params ();
ipa_unregister_cgraph_hooks ();
case IPA_JF_UNKNOWN:
break;
case IPA_JF_KNOWN_TYPE:
- stream_write_tree (ob, jump_func->value.base_binfo, true);
+ streamer_write_uhwi (ob, jump_func->value.known_type.offset);
+ stream_write_tree (ob, jump_func->value.known_type.base_type, true);
+ stream_write_tree (ob, jump_func->value.known_type.component_type, true);
break;
case IPA_JF_CONST:
stream_write_tree (ob, jump_func->value.constant, true);
case IPA_JF_UNKNOWN:
break;
case IPA_JF_KNOWN_TYPE:
- jump_func->value.base_binfo = stream_read_tree (ib, data_in);
+ jump_func->value.known_type.offset = streamer_read_uhwi (ib);
+ jump_func->value.known_type.base_type = stream_read_tree (ib, data_in);
+ jump_func->value.known_type.component_type = stream_read_tree (ib,
+ data_in);
break;
case IPA_JF_CONST:
jump_func->value.constant = stream_read_tree (ib, data_in);