Commit 3b97a5c7 by Martin Jambor Committed by Martin Jambor

ipa-prop.h (jump_func_type): Removed value IPA_JF_KNOWN_TYPE.

2014-11-14  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (jump_func_type): Removed value IPA_JF_KNOWN_TYPE.
	(ipa_pass_through_data): Removed field type_preserved.
	(ipa_ancestor_jf_data): removed fields type and type_preserved.
	(ipa_jump_func): Removed field known_type.
	(ipa_get_jf_known_type_offset): Removed.
	(ipa_get_jf_known_type_base_type): Likewise.
	(ipa_get_jf_known_type_component_type): Likewise.
	(ipa_get_jf_ancestor_type): Likewise.
	* ipa-cp.c (print_ipcp_constant_value): Removed BINFO handling.
	(ipa_get_jf_pass_through_result): Likewise.
	(ipa_get_jf_ancestor_result): Always build ptr_node_type accesses.
	(values_equal_for_ipcp_p): Removed BINFO handling.
	(ipa_get_indirect_edge_target_1): Updated comment.
	* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Removed handling
	of IPA_JF_KNOWN_TYPE jump functions.  Do not print removed fields.
	(ipa_set_jf_known_type): Removed.
	(ipa_set_jf_simple_pass_through): Do not set removed fields.  Update
	all callers.
	(ipa_set_jf_arith_pass_through): Likewise.
	(ipa_set_ancestor_jf): Likewise.
	(ipa_binfo_from_known_type_jfunc): Removed.
	(prop_type_change_info): Removed fields known_current_type and
	multiple_types_encountered.
	(extr_type_from_vtbl_ptr_store): Removed.
	(check_stmt_for_type_change): Do not attempt to identify changed type.
	(detect_type_change_from_memory_writes): Do not set the removed fields,
	always set jfunc to unknown.
	(compute_complex_assign_jump_func): Do not detect dynamic type change.
	(compute_complex_ancestor_jump_func): Likewise.
	(compute_known_type_jump_func): Removed.
	(ipa_compute_jump_functions_for_edge): Do not detect dynamic type
	change.  Do not comute known type jump functions.
	(combine_known_type_and_ancestor_jfs): Removed.
	(update_jump_functions_after_inlining): Removed handling of
	IPA_JF_KNOWN_TYPE jump functions.  Do not set removed fields.
	(ipa_write_jump_function): Do not stream removed fields or known type
	jump functions.
	(ipa_read_jump_function): Likewise.

From-SVN: r217589
parent 4ab74a01
2014-11-14 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (jump_func_type): Removed value IPA_JF_KNOWN_TYPE.
(ipa_pass_through_data): Removed field type_preserved.
(ipa_ancestor_jf_data): removed fields type and type_preserved.
(ipa_jump_func): Removed field known_type.
(ipa_get_jf_known_type_offset): Removed.
(ipa_get_jf_known_type_base_type): Likewise.
(ipa_get_jf_known_type_component_type): Likewise.
(ipa_get_jf_ancestor_type): Likewise.
* ipa-cp.c (print_ipcp_constant_value): Removed BINFO handling.
(ipa_get_jf_pass_through_result): Likewise.
(ipa_get_jf_ancestor_result): Always build ptr_node_type accesses.
(values_equal_for_ipcp_p): Removed BINFO handling.
(ipa_get_indirect_edge_target_1): Updated comment.
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Removed handling
of IPA_JF_KNOWN_TYPE jump functions. Do not print removed fields.
(ipa_set_jf_known_type): Removed.
(ipa_set_jf_simple_pass_through): Do not set removed fields. Update
all callers.
(ipa_set_jf_arith_pass_through): Likewise.
(ipa_set_ancestor_jf): Likewise.
(ipa_binfo_from_known_type_jfunc): Removed.
(prop_type_change_info): Removed fields known_current_type and
multiple_types_encountered.
(extr_type_from_vtbl_ptr_store): Removed.
(check_stmt_for_type_change): Do not attempt to identify changed type.
(detect_type_change_from_memory_writes): Do not set the removed fields,
always set jfunc to unknown.
(compute_complex_assign_jump_func): Do not detect dynamic type change.
(compute_complex_ancestor_jump_func): Likewise.
(compute_known_type_jump_func): Removed.
(ipa_compute_jump_functions_for_edge): Do not detect dynamic type
change. Do not comute known type jump functions.
(combine_known_type_and_ancestor_jfs): Removed.
(update_jump_functions_after_inlining): Removed handling of
IPA_JF_KNOWN_TYPE jump functions. Do not set removed fields.
(ipa_write_jump_function): Do not stream removed fields or known type
jump functions.
(ipa_read_jump_function): Likewise.
2014-11-14 Vladimir Makarov <vmakarov@redhat.com> 2014-11-14 Vladimir Makarov <vmakarov@redhat.com>
* lra-int.h (lra_create_live_ranges): Add parameter. * lra-int.h (lra_create_live_ranges): Add parameter.
...@@ -340,12 +340,7 @@ ipcp_lattice<valtype>::is_single_const () ...@@ -340,12 +340,7 @@ ipcp_lattice<valtype>::is_single_const ()
static void static void
print_ipcp_constant_value (FILE * f, tree v) print_ipcp_constant_value (FILE * f, tree v)
{ {
if (TREE_CODE (v) == TREE_BINFO) if (TREE_CODE (v) == ADDR_EXPR
{
fprintf (f, "BINFO ");
print_generic_expr (f, BINFO_TYPE (v), 0);
}
else if (TREE_CODE (v) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL) && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL)
{ {
fprintf (f, "& "); fprintf (f, "& ");
...@@ -842,21 +837,10 @@ ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input) ...@@ -842,21 +837,10 @@ ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
{ {
tree restype, res; tree restype, res;
if (TREE_CODE (input) == TREE_BINFO) gcc_checking_assert (is_gimple_ip_invariant (input));
{
if (ipa_get_jf_pass_through_type_preserved (jfunc))
{
gcc_checking_assert (ipa_get_jf_pass_through_operation (jfunc)
== NOP_EXPR);
return input;
}
return NULL_TREE;
}
if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
return input; return input;
gcc_checking_assert (is_gimple_ip_invariant (input));
if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
== tcc_comparison) == tcc_comparison)
restype = boolean_type_node; restype = boolean_type_node;
...@@ -883,9 +867,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) ...@@ -883,9 +867,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
tree t = TREE_OPERAND (input, 0); tree t = TREE_OPERAND (input, 0);
t = build_ref_for_offset (EXPR_LOCATION (t), t, t = build_ref_for_offset (EXPR_LOCATION (t), t,
ipa_get_jf_ancestor_offset (jfunc), ipa_get_jf_ancestor_offset (jfunc),
ipa_get_jf_ancestor_type (jfunc) ptr_type_node, NULL, false);
? ipa_get_jf_ancestor_type (jfunc)
: ptr_type_node, NULL, false);
return build_fold_addr_expr (t); return build_fold_addr_expr (t);
} }
else else
...@@ -1051,9 +1033,6 @@ values_equal_for_ipcp_p (tree x, tree y) ...@@ -1051,9 +1033,6 @@ values_equal_for_ipcp_p (tree x, tree y)
if (x == y) if (x == y)
return true; return true;
if (TREE_CODE (x) == TREE_BINFO || TREE_CODE (y) == TREE_BINFO)
return false;
if (TREE_CODE (x) == ADDR_EXPR if (TREE_CODE (x) == ADDR_EXPR
&& TREE_CODE (y) == ADDR_EXPR && TREE_CODE (y) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
...@@ -1740,9 +1719,8 @@ propagate_constants_accross_call (struct cgraph_edge *cs) ...@@ -1740,9 +1719,8 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
} }
/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
(which can contain both constants and binfos), KNOWN_CONTEXTS, KNOWN_AGGS or KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter
AGG_REPS return the destination. The latter three can be NULL. If AGG_REPS three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */
is not NULL, KNOWN_AGGS is ignored. */
static tree static tree
ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
......
...@@ -303,15 +303,6 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) ...@@ -303,15 +303,6 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
fprintf (f, " param %d: ", i); fprintf (f, " param %d: ", i);
if (type == IPA_JF_UNKNOWN) if (type == IPA_JF_UNKNOWN)
fprintf (f, "UNKNOWN\n"); fprintf (f, "UNKNOWN\n");
else if (type == IPA_JF_KNOWN_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) else if (type == IPA_JF_CONST)
{ {
tree val = jump_func->value.constant.value; tree val = jump_func->value.constant.value;
...@@ -340,21 +331,16 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs) ...@@ -340,21 +331,16 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
} }
if (jump_func->value.pass_through.agg_preserved) if (jump_func->value.pass_through.agg_preserved)
fprintf (f, ", agg_preserved"); fprintf (f, ", agg_preserved");
if (jump_func->value.pass_through.type_preserved)
fprintf (f, ", type_preserved");
fprintf (f, "\n"); fprintf (f, "\n");
} }
else if (type == IPA_JF_ANCESTOR) else if (type == IPA_JF_ANCESTOR)
{ {
fprintf (f, "ANCESTOR: "); fprintf (f, "ANCESTOR: ");
fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC", ", fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC,
jump_func->value.ancestor.formal_id, jump_func->value.ancestor.formal_id,
jump_func->value.ancestor.offset); jump_func->value.ancestor.offset);
print_generic_expr (f, jump_func->value.ancestor.type, 0);
if (jump_func->value.ancestor.agg_preserved) if (jump_func->value.ancestor.agg_preserved)
fprintf (f, ", agg_preserved"); fprintf (f, ", agg_preserved");
if (jump_func->value.ancestor.type_preserved)
fprintf (f, ", type_preserved");
fprintf (f, "\n"); fprintf (f, "\n");
} }
...@@ -460,28 +446,6 @@ ipa_print_all_jump_functions (FILE *f) ...@@ -460,28 +446,6 @@ ipa_print_all_jump_functions (FILE *f)
} }
} }
/* Set JFUNC to be a known type jump function. */
static void
ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
tree base_type, tree component_type)
{
/* Recording and propagating main variants increases change that types
will match. */
base_type = TYPE_MAIN_VARIANT (base_type);
component_type = TYPE_MAIN_VARIANT (component_type);
gcc_assert (contains_polymorphic_type_p (base_type)
&& contains_polymorphic_type_p (component_type));
if (!flag_devirtualize)
return;
jfunc->type = IPA_JF_KNOWN_TYPE;
jfunc->value.known_type.offset = offset,
jfunc->value.known_type.base_type = base_type;
jfunc->value.known_type.component_type = component_type;
gcc_assert (component_type);
}
/* Set JFUNC to be a copy of another jmp (to be used by jump function /* Set JFUNC to be a copy of another jmp (to be used by jump function
combination code). The two functions will share their rdesc. */ combination code). The two functions will share their rdesc. */
...@@ -528,14 +492,13 @@ ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant, ...@@ -528,14 +492,13 @@ ipa_set_jf_constant (struct ipa_jump_func *jfunc, tree constant,
/* Set JFUNC to be a simple pass-through jump function. */ /* Set JFUNC to be a simple pass-through jump function. */
static void static void
ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id, ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id,
bool agg_preserved, bool type_preserved) bool agg_preserved)
{ {
jfunc->type = IPA_JF_PASS_THROUGH; jfunc->type = IPA_JF_PASS_THROUGH;
jfunc->value.pass_through.operand = NULL_TREE; jfunc->value.pass_through.operand = NULL_TREE;
jfunc->value.pass_through.formal_id = formal_id; jfunc->value.pass_through.formal_id = formal_id;
jfunc->value.pass_through.operation = NOP_EXPR; jfunc->value.pass_through.operation = NOP_EXPR;
jfunc->value.pass_through.agg_preserved = agg_preserved; jfunc->value.pass_through.agg_preserved = agg_preserved;
jfunc->value.pass_through.type_preserved = type_preserved;
} }
/* Set JFUNC to be an arithmetic pass through jump function. */ /* Set JFUNC to be an arithmetic pass through jump function. */
...@@ -549,61 +512,18 @@ ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id, ...@@ -549,61 +512,18 @@ ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id,
jfunc->value.pass_through.formal_id = formal_id; jfunc->value.pass_through.formal_id = formal_id;
jfunc->value.pass_through.operation = operation; jfunc->value.pass_through.operation = operation;
jfunc->value.pass_through.agg_preserved = false; jfunc->value.pass_through.agg_preserved = false;
jfunc->value.pass_through.type_preserved = false;
} }
/* Set JFUNC to be an ancestor jump function. */ /* Set JFUNC to be an ancestor jump function. */
static void static void
ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset, ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
tree type, int formal_id, bool agg_preserved, int formal_id, bool agg_preserved)
bool type_preserved)
{ {
if (!flag_devirtualize)
type_preserved = false;
if (!type_preserved)
type = NULL_TREE;
if (type)
type = TYPE_MAIN_VARIANT (type);
if (!type || !contains_polymorphic_type_p (type))
type_preserved = false;
jfunc->type = IPA_JF_ANCESTOR; jfunc->type = IPA_JF_ANCESTOR;
jfunc->value.ancestor.formal_id = formal_id; jfunc->value.ancestor.formal_id = formal_id;
jfunc->value.ancestor.offset = offset; jfunc->value.ancestor.offset = offset;
jfunc->value.ancestor.type = type_preserved ? type : NULL;
jfunc->value.ancestor.agg_preserved = agg_preserved; jfunc->value.ancestor.agg_preserved = agg_preserved;
jfunc->value.ancestor.type_preserved = type_preserved;
}
/* Extract the acual BINFO being described by JFUNC which must be a known type
jump function. */
tree
ipa_binfo_from_known_type_jfunc (struct ipa_jump_func *jfunc)
{
if (!RECORD_OR_UNION_TYPE_P (jfunc->value.known_type.base_type))
return NULL_TREE;
tree base_binfo = TYPE_BINFO (jfunc->value.known_type.base_type);
if (!base_binfo)
return NULL_TREE;
/* FIXME: At LTO we can't propagate to non-polymorphic type, because
we have no ODR equivalency on those. This should be fixed by
propagating on types rather than binfos that would make type
matching here unnecesary. */
if (in_lto_p
&& (TREE_CODE (jfunc->value.known_type.component_type) != RECORD_TYPE
|| !TYPE_BINFO (jfunc->value.known_type.component_type)
|| !BINFO_VTABLE (TYPE_BINFO (jfunc->value.known_type.component_type))))
{
if (!jfunc->value.known_type.offset)
return base_binfo;
return NULL;
}
return get_binfo_at_offset (base_binfo,
jfunc->value.known_type.offset,
jfunc->value.known_type.component_type);
} }
/* Get IPA BB information about the given BB. FBI is the context of analyzis /* Get IPA BB information about the given BB. FBI is the context of analyzis
...@@ -627,14 +547,8 @@ struct prop_type_change_info ...@@ -627,14 +547,8 @@ struct prop_type_change_info
/* The declaration or SSA_NAME pointer of the base that we are checking for /* The declaration or SSA_NAME pointer of the base that we are checking for
type change. */ type change. */
tree object; tree object;
/* If we actually can tell the type that the object has changed to, it is
stored in this field. Otherwise it remains NULL_TREE. */
tree known_current_type;
/* Set to true if dynamic type change has been detected. */ /* Set to true if dynamic type change has been detected. */
bool type_maybe_changed; bool type_maybe_changed;
/* Set to true if multiple types have been encountered. known_current_type
must be disregarded in that case. */
bool multiple_types_encountered;
}; };
/* Return true if STMT can modify a virtual method table pointer. /* Return true if STMT can modify a virtual method table pointer.
...@@ -702,57 +616,9 @@ stmt_may_be_vtbl_ptr_store (gimple stmt) ...@@ -702,57 +616,9 @@ stmt_may_be_vtbl_ptr_store (gimple stmt)
return true; return true;
} }
/* If STMT can be proved to be an assignment to the virtual method table /* Callback of walk_aliased_vdefs and a helper function for detect_type_change
pointer of ANALYZED_OBJ and the type associated with the new table to check whether a particular statement may modify the virtual table
identified, return the type. Otherwise return NULL_TREE. */ pointerIt stores its result into DATA, which points to a
static tree
extr_type_from_vtbl_ptr_store (gimple stmt, struct prop_type_change_info *tci)
{
HOST_WIDE_INT offset, size, max_size;
tree lhs, rhs, base, binfo;
if (!gimple_assign_single_p (stmt))
return NULL_TREE;
lhs = gimple_assign_lhs (stmt);
rhs = gimple_assign_rhs1 (stmt);
if (TREE_CODE (lhs) != COMPONENT_REF
|| !DECL_VIRTUAL_P (TREE_OPERAND (lhs, 1)))
return NULL_TREE;
base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
if (offset != tci->offset
|| size != POINTER_SIZE
|| max_size != POINTER_SIZE)
return NULL_TREE;
if (TREE_CODE (base) == MEM_REF)
{
if (TREE_CODE (tci->object) != MEM_REF
|| TREE_OPERAND (tci->object, 0) != TREE_OPERAND (base, 0)
|| !tree_int_cst_equal (TREE_OPERAND (tci->object, 1),
TREE_OPERAND (base, 1)))
return NULL_TREE;
}
else if (tci->object != base)
return NULL_TREE;
binfo = vtable_pointer_value_to_binfo (rhs);
/* FIXME: vtable_pointer_value_to_binfo may return BINFO of a
base of outer type. In this case we would need to either
work on binfos or translate it back to outer type and offset.
KNOWN_TYPE jump functions are not ready for that, yet. */
if (!binfo || TYPE_BINFO (BINFO_TYPE (binfo)) != binfo)
return NULL;
return BINFO_TYPE (binfo);
}
/* Callback of walk_aliased_vdefs and a helper function for
detect_type_change to check whether a particular statement may modify
the virtual table pointer, and if possible also determine the new type of
the (sub-)object. It stores its result into DATA, which points to a
prop_type_change_info structure. */ prop_type_change_info structure. */
static bool static bool
...@@ -763,14 +629,6 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) ...@@ -763,14 +629,6 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
if (stmt_may_be_vtbl_ptr_store (stmt)) if (stmt_may_be_vtbl_ptr_store (stmt))
{ {
tree type;
type = extr_type_from_vtbl_ptr_store (stmt, tci);
gcc_assert (!type || TYPE_MAIN_VARIANT (type) == type);
if (tci->type_maybe_changed
&& type != tci->known_current_type)
tci->multiple_types_encountered = true;
tci->known_current_type = type;
tci->type_maybe_changed = true; tci->type_maybe_changed = true;
return true; return true;
} }
...@@ -885,25 +743,14 @@ detect_type_change_from_memory_writes (tree arg, tree base, tree comp_type, ...@@ -885,25 +743,14 @@ detect_type_change_from_memory_writes (tree arg, tree base, tree comp_type,
tci.offset = offset; tci.offset = offset;
tci.object = get_base_address (arg); tci.object = get_base_address (arg);
tci.known_current_type = NULL_TREE;
tci.type_maybe_changed = false; tci.type_maybe_changed = false;
tci.multiple_types_encountered = false;
walk_aliased_vdefs (&ao, gimple_vuse (call), check_stmt_for_type_change, walk_aliased_vdefs (&ao, gimple_vuse (call), check_stmt_for_type_change,
&tci, NULL, &entry_reached); &tci, NULL, &entry_reached);
if (!tci.type_maybe_changed) if (!tci.type_maybe_changed)
return false; return false;
if (!tci.known_current_type jfunc->type = IPA_JF_UNKNOWN;
|| tci.multiple_types_encountered
|| offset != 0
/* When the walk reached function entry, it means that type
is set along some paths but not along others. */
|| entry_reached)
jfunc->type = IPA_JF_UNKNOWN;
else
ipa_set_jf_known_type (jfunc, 0, tci.known_current_type, comp_type);
return true; return true;
} }
...@@ -1354,13 +1201,7 @@ compute_complex_assign_jump_func (struct func_body_info *fbi, ...@@ -1354,13 +1201,7 @@ compute_complex_assign_jump_func (struct func_body_info *fbi,
else if (gimple_assign_single_p (stmt)) else if (gimple_assign_single_p (stmt))
{ {
bool agg_p = parm_ref_data_pass_through_p (fbi, index, call, tc_ssa); bool agg_p = parm_ref_data_pass_through_p (fbi, index, call, tc_ssa);
bool type_p = false; ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
if (param_type && POINTER_TYPE_P (param_type))
type_p = !detect_type_change_ssa (tc_ssa, TREE_TYPE (param_type),
call, jfunc);
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_jf_simple_pass_through (jfunc, index, agg_p, type_p);
} }
return; return;
} }
...@@ -1386,16 +1227,8 @@ compute_complex_assign_jump_func (struct func_body_info *fbi, ...@@ -1386,16 +1227,8 @@ compute_complex_assign_jump_func (struct func_body_info *fbi,
/* Dynamic types are changed in constructors and destructors. */ /* Dynamic types are changed in constructors and destructors. */
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa)); index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
if (index >= 0 && param_type && POINTER_TYPE_P (param_type)) if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
{ ipa_set_ancestor_jf (jfunc, offset, index,
bool type_p = (contains_polymorphic_type_p (TREE_TYPE (param_type)) parm_ref_data_pass_through_p (fbi, index, call, ssa));
&& !detect_type_change (op1, base, TREE_TYPE (param_type),
call, jfunc, offset));
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_ancestor_jf (jfunc, offset,
type_p ? TREE_TYPE (param_type) : NULL, index,
parm_ref_data_pass_through_p (fbi, index,
call, ssa), type_p);
}
} }
/* Extract the base, offset and MEM_REF expression from a statement ASSIGN if /* Extract the base, offset and MEM_REF expression from a statement ASSIGN if
...@@ -1468,7 +1301,7 @@ static void ...@@ -1468,7 +1301,7 @@ static void
compute_complex_ancestor_jump_func (struct func_body_info *fbi, compute_complex_ancestor_jump_func (struct func_body_info *fbi,
struct ipa_node_params *info, struct ipa_node_params *info,
struct ipa_jump_func *jfunc, struct ipa_jump_func *jfunc,
gimple call, gimple phi, tree param_type) gimple call, gimple phi)
{ {
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
gimple assign, cond; gimple assign, cond;
...@@ -1520,56 +1353,8 @@ compute_complex_ancestor_jump_func (struct func_body_info *fbi, ...@@ -1520,56 +1353,8 @@ compute_complex_ancestor_jump_func (struct func_body_info *fbi,
return; return;
} }
bool type_p = false; ipa_set_ancestor_jf (jfunc, offset, index,
if (param_type && POINTER_TYPE_P (param_type) parm_ref_data_pass_through_p (fbi, index, call, parm));
&& contains_polymorphic_type_p (TREE_TYPE (param_type)))
type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type),
call, jfunc, offset);
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_ancestor_jf (jfunc, offset, type_p ? TREE_TYPE (param_type) : NULL,
index,
parm_ref_data_pass_through_p (fbi, index, call, parm),
type_p);
}
/* Given OP which is passed as an actual argument to a called function,
determine if it is possible to construct a KNOWN_TYPE jump function for it
and if so, create one and store it to JFUNC.
EXPECTED_TYPE represents a type the argument should be in */
static void
compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
gimple call, tree expected_type)
{
HOST_WIDE_INT offset, size, max_size;
tree base;
if (!flag_devirtualize
|| TREE_CODE (op) != ADDR_EXPR
|| !contains_polymorphic_type_p (TREE_TYPE (TREE_TYPE (op)))
/* Be sure expected_type is polymorphic. */
|| !expected_type
|| !contains_polymorphic_type_p (expected_type))
return;
op = TREE_OPERAND (op, 0);
base = get_ref_base_and_extent (op, &offset, &size, &max_size);
if (!DECL_P (base)
|| max_size == -1
|| max_size != size
|| !contains_polymorphic_type_p (TREE_TYPE (base)))
return;
if (decl_maybe_in_construction_p (base, TREE_TYPE (base),
call, current_function_decl)
/* Even if the var seems to be in construction by inline call stack,
we may work out the actual type by walking memory writes. */
&& (is_global_var (base)
|| detect_type_change (op, base, expected_type, call, jfunc, offset)))
return;
ipa_set_jf_known_type (jfunc, offset, TREE_TYPE (base),
expected_type);
} }
/* Inspect the given TYPE and return true iff it has the same structure (the /* Inspect the given TYPE and return true iff it has the same structure (the
...@@ -1944,7 +1729,7 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi, ...@@ -1944,7 +1729,7 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
for cycle. */ for cycle. */
if (parm_preserved_before_stmt_p (fbi, index, call, arg)) if (parm_preserved_before_stmt_p (fbi, index, call, arg))
{ {
ipa_set_jf_simple_pass_through (jfunc, index, false, false); ipa_set_jf_simple_pass_through (jfunc, index, false);
continue; continue;
} }
} }
...@@ -1955,16 +1740,9 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi, ...@@ -1955,16 +1740,9 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg)); int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
if (index >= 0) if (index >= 0)
{ {
bool agg_p, type_p; bool agg_p;
agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg); agg_p = parm_ref_data_pass_through_p (fbi, index, call, arg);
if (param_type && POINTER_TYPE_P (param_type)) ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
type_p = !detect_type_change_ssa (arg, TREE_TYPE (param_type),
call, jfunc);
else
type_p = false;
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_jf_simple_pass_through (jfunc, index, agg_p,
type_p);
} }
} }
else else
...@@ -1975,15 +1753,9 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi, ...@@ -1975,15 +1753,9 @@ ipa_compute_jump_functions_for_edge (struct func_body_info *fbi,
call, stmt, arg, param_type); call, stmt, arg, param_type);
else if (gimple_code (stmt) == GIMPLE_PHI) else if (gimple_code (stmt) == GIMPLE_PHI)
compute_complex_ancestor_jump_func (fbi, info, jfunc, compute_complex_ancestor_jump_func (fbi, info, jfunc,
call, stmt, param_type); call, stmt);
} }
} }
else
compute_known_type_jump_func (arg, jfunc, call,
param_type
&& POINTER_TYPE_P (param_type)
? TREE_TYPE (param_type)
: NULL);
/* If ARG is pointer, we can not use its type to determine the type of aggregate /* If ARG is pointer, we can not use its type to determine the type of aggregate
passed (because type conversions are ignored in gimple). Usually we can passed (because type conversions are ignored in gimple). Usually we can
...@@ -2608,35 +2380,6 @@ ipa_analyze_node (struct cgraph_node *node) ...@@ -2608,35 +2380,6 @@ ipa_analyze_node (struct cgraph_node *node)
pop_cfun (); pop_cfun ();
} }
/* Update the jump function DST when the call graph edge corresponding to SRC is
is being inlined, knowing that DST is of type ancestor and src of known
type. */
static void
combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src,
struct ipa_jump_func *dst)
{
HOST_WIDE_INT combined_offset;
tree combined_type;
if (!ipa_get_jf_ancestor_type_preserved (dst))
{
dst->type = IPA_JF_UNKNOWN;
return;
}
combined_offset = ipa_get_jf_known_type_offset (src)
+ ipa_get_jf_ancestor_offset (dst);
combined_type = ipa_get_jf_ancestor_type (dst);
if (combined_type)
ipa_set_jf_known_type (dst, combined_offset,
ipa_get_jf_known_type_base_type (src),
combined_type);
else
dst->type = IPA_JF_UNKNOWN;
}
/* Update the jump functions associated with call graph edge E when the call /* Update the jump functions associated with call graph edge E when the call
graph edge CS is being inlined, assuming that E->caller is already (possibly graph edge CS is being inlined, assuming that E->caller is already (possibly
indirectly) inlined into CS->callee and that E has not been inlined. */ indirectly) inlined into CS->callee and that E has not been inlined. */
...@@ -2707,16 +2450,12 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -2707,16 +2450,12 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
item->offset -= dst->value.ancestor.offset; item->offset -= dst->value.ancestor.offset;
} }
if (src->type == IPA_JF_KNOWN_TYPE) if (src->type == IPA_JF_PASS_THROUGH
combine_known_type_and_ancestor_jfs (src, dst); && src->value.pass_through.operation == NOP_EXPR)
else if (src->type == IPA_JF_PASS_THROUGH
&& src->value.pass_through.operation == NOP_EXPR)
{ {
dst->value.ancestor.formal_id = src->value.pass_through.formal_id; dst->value.ancestor.formal_id = src->value.pass_through.formal_id;
dst->value.ancestor.agg_preserved &= dst->value.ancestor.agg_preserved &=
src->value.pass_through.agg_preserved; src->value.pass_through.agg_preserved;
dst->value.ancestor.type_preserved &=
src->value.pass_through.type_preserved;
} }
else if (src->type == IPA_JF_ANCESTOR) else if (src->type == IPA_JF_ANCESTOR)
{ {
...@@ -2724,8 +2463,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -2724,8 +2463,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
dst->value.ancestor.offset += src->value.ancestor.offset; dst->value.ancestor.offset += src->value.ancestor.offset;
dst->value.ancestor.agg_preserved &= dst->value.ancestor.agg_preserved &=
src->value.ancestor.agg_preserved; src->value.ancestor.agg_preserved;
dst->value.ancestor.type_preserved &=
src->value.ancestor.type_preserved;
} }
else else
dst->type = IPA_JF_UNKNOWN; dst->type = IPA_JF_UNKNOWN;
...@@ -2768,15 +2505,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -2768,15 +2505,6 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
case IPA_JF_UNKNOWN: case IPA_JF_UNKNOWN:
dst->type = IPA_JF_UNKNOWN; dst->type = IPA_JF_UNKNOWN;
break; break;
case IPA_JF_KNOWN_TYPE:
if (ipa_get_jf_pass_through_type_preserved (dst))
ipa_set_jf_known_type (dst,
ipa_get_jf_known_type_offset (src),
ipa_get_jf_known_type_base_type (src),
ipa_get_jf_known_type_component_type (src));
else
dst->type = IPA_JF_UNKNOWN;
break;
case IPA_JF_CONST: case IPA_JF_CONST:
ipa_set_jf_cst_copy (dst, src); ipa_set_jf_cst_copy (dst, src);
break; break;
...@@ -2789,13 +2517,10 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -2789,13 +2517,10 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
if (operation == NOP_EXPR) if (operation == NOP_EXPR)
{ {
bool agg_p, type_p; bool agg_p;
agg_p = dst_agg_p agg_p = dst_agg_p
&& ipa_get_jf_pass_through_agg_preserved (src); && ipa_get_jf_pass_through_agg_preserved (src);
type_p = ipa_get_jf_pass_through_type_preserved (src) ipa_set_jf_simple_pass_through (dst, formal_id, agg_p);
&& ipa_get_jf_pass_through_type_preserved (dst);
ipa_set_jf_simple_pass_through (dst, formal_id,
agg_p, type_p);
} }
else else
{ {
...@@ -2807,16 +2532,13 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -2807,16 +2532,13 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
} }
case IPA_JF_ANCESTOR: case IPA_JF_ANCESTOR:
{ {
bool agg_p, type_p; bool agg_p;
agg_p = dst_agg_p agg_p = dst_agg_p
&& ipa_get_jf_ancestor_agg_preserved (src); && ipa_get_jf_ancestor_agg_preserved (src);
type_p = ipa_get_jf_ancestor_type_preserved (src)
&& ipa_get_jf_pass_through_type_preserved (dst);
ipa_set_ancestor_jf (dst, ipa_set_ancestor_jf (dst,
ipa_get_jf_ancestor_offset (src), ipa_get_jf_ancestor_offset (src),
ipa_get_jf_ancestor_type (src),
ipa_get_jf_ancestor_formal_id (src), ipa_get_jf_ancestor_formal_id (src),
agg_p, type_p); agg_p);
break; break;
} }
default: default:
...@@ -4685,11 +4407,6 @@ ipa_write_jump_function (struct output_block *ob, ...@@ -4685,11 +4407,6 @@ ipa_write_jump_function (struct output_block *ob,
{ {
case IPA_JF_UNKNOWN: case IPA_JF_UNKNOWN:
break; break;
case IPA_JF_KNOWN_TYPE:
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: case IPA_JF_CONST:
gcc_assert ( gcc_assert (
EXPR_LOCATION (jump_func->value.constant.value) == UNKNOWN_LOCATION); EXPR_LOCATION (jump_func->value.constant.value) == UNKNOWN_LOCATION);
...@@ -4702,7 +4419,6 @@ ipa_write_jump_function (struct output_block *ob, ...@@ -4702,7 +4419,6 @@ ipa_write_jump_function (struct output_block *ob,
streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id); streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
bp = bitpack_create (ob->main_stream); bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, jump_func->value.pass_through.agg_preserved, 1); bp_pack_value (&bp, jump_func->value.pass_through.agg_preserved, 1);
bp_pack_value (&bp, jump_func->value.pass_through.type_preserved, 1);
streamer_write_bitpack (&bp); streamer_write_bitpack (&bp);
} }
else else
...@@ -4713,11 +4429,9 @@ ipa_write_jump_function (struct output_block *ob, ...@@ -4713,11 +4429,9 @@ ipa_write_jump_function (struct output_block *ob,
break; break;
case IPA_JF_ANCESTOR: case IPA_JF_ANCESTOR:
streamer_write_uhwi (ob, jump_func->value.ancestor.offset); streamer_write_uhwi (ob, jump_func->value.ancestor.offset);
stream_write_tree (ob, jump_func->value.ancestor.type, true);
streamer_write_uhwi (ob, jump_func->value.ancestor.formal_id); streamer_write_uhwi (ob, jump_func->value.ancestor.formal_id);
bp = bitpack_create (ob->main_stream); bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, jump_func->value.ancestor.agg_preserved, 1); bp_pack_value (&bp, jump_func->value.ancestor.agg_preserved, 1);
bp_pack_value (&bp, jump_func->value.ancestor.type_preserved, 1);
streamer_write_bitpack (&bp); streamer_write_bitpack (&bp);
break; break;
} }
...@@ -4756,15 +4470,6 @@ ipa_read_jump_function (struct lto_input_block *ib, ...@@ -4756,15 +4470,6 @@ ipa_read_jump_function (struct lto_input_block *ib,
case IPA_JF_UNKNOWN: case IPA_JF_UNKNOWN:
jump_func->type = IPA_JF_UNKNOWN; jump_func->type = IPA_JF_UNKNOWN;
break; break;
case IPA_JF_KNOWN_TYPE:
{
HOST_WIDE_INT offset = streamer_read_uhwi (ib);
tree base_type = stream_read_tree (ib, data_in);
tree component_type = stream_read_tree (ib, data_in);
ipa_set_jf_known_type (jump_func, offset, base_type, component_type);
break;
}
case IPA_JF_CONST: case IPA_JF_CONST:
ipa_set_jf_constant (jump_func, stream_read_tree (ib, data_in), cs); ipa_set_jf_constant (jump_func, stream_read_tree (ib, data_in), cs);
break; break;
...@@ -4775,9 +4480,7 @@ ipa_read_jump_function (struct lto_input_block *ib, ...@@ -4775,9 +4480,7 @@ ipa_read_jump_function (struct lto_input_block *ib,
int formal_id = streamer_read_uhwi (ib); int formal_id = streamer_read_uhwi (ib);
struct bitpack_d bp = streamer_read_bitpack (ib); struct bitpack_d bp = streamer_read_bitpack (ib);
bool agg_preserved = bp_unpack_value (&bp, 1); bool agg_preserved = bp_unpack_value (&bp, 1);
bool type_preserved = bp_unpack_value (&bp, 1); ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved);
ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved,
type_preserved);
} }
else else
{ {
...@@ -4790,14 +4493,10 @@ ipa_read_jump_function (struct lto_input_block *ib, ...@@ -4790,14 +4493,10 @@ ipa_read_jump_function (struct lto_input_block *ib,
case IPA_JF_ANCESTOR: case IPA_JF_ANCESTOR:
{ {
HOST_WIDE_INT offset = streamer_read_uhwi (ib); HOST_WIDE_INT offset = streamer_read_uhwi (ib);
tree type = stream_read_tree (ib, data_in);
int formal_id = streamer_read_uhwi (ib); int formal_id = streamer_read_uhwi (ib);
struct bitpack_d bp = streamer_read_bitpack (ib); struct bitpack_d bp = streamer_read_bitpack (ib);
bool agg_preserved = bp_unpack_value (&bp, 1); bool agg_preserved = bp_unpack_value (&bp, 1);
bool type_preserved = bp_unpack_value (&bp, 1); ipa_set_ancestor_jf (jump_func, offset, formal_id, agg_preserved);
ipa_set_ancestor_jf (jump_func, offset, type, formal_id, agg_preserved,
type_preserved);
break; break;
} }
} }
......
...@@ -51,11 +51,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -51,11 +51,6 @@ along with GCC; see the file COPYING3. If not see
parameter or can apply one simple binary operation to it (such jump parameter or can apply one simple binary operation to it (such jump
functions are called polynomial). functions are called polynomial).
IPA_JF_KNOWN_TYPE is a special type of an "unknown" function that applies
only to pointer parameters. It means that even though we cannot prove that
the passed value is an interprocedural constant, we still know the exact
type of the containing object which may be valuable for devirtualization.
Jump functions are computed in ipa-prop.c by function Jump functions are computed in ipa-prop.c by function
update_call_notes_after_inlining. Some information can be lost and jump update_call_notes_after_inlining. Some information can be lost and jump
functions degraded accordingly when inlining, see functions degraded accordingly when inlining, see
...@@ -64,7 +59,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -64,7 +59,6 @@ along with GCC; see the file COPYING3. If not see
enum jump_func_type enum jump_func_type
{ {
IPA_JF_UNKNOWN = 0, /* newly allocated and zeroed jump functions default */ IPA_JF_UNKNOWN = 0, /* newly allocated and zeroed jump functions default */
IPA_JF_KNOWN_TYPE, /* represented by field known_type */
IPA_JF_CONST, /* represented by field costant */ IPA_JF_CONST, /* represented by field costant */
IPA_JF_PASS_THROUGH, /* represented by field pass_through */ IPA_JF_PASS_THROUGH, /* represented by field pass_through */
IPA_JF_ANCESTOR /* represented by field ancestor */ IPA_JF_ANCESTOR /* represented by field ancestor */
...@@ -113,11 +107,6 @@ struct GTY(()) ipa_pass_through_data ...@@ -113,11 +107,6 @@ struct GTY(()) ipa_pass_through_data
ipa_agg_jump_function). The flag is used only when the operation is ipa_agg_jump_function). The flag is used only when the operation is
NOP_EXPR. */ NOP_EXPR. */
unsigned agg_preserved : 1; unsigned agg_preserved : 1;
/* When set to true, we guarantee that, if there is a C++ object pointed to
by this object, it does not undergo dynamic type change in the course of
functions decribed by this jump function. */
unsigned type_preserved : 1;
}; };
/* Structure holding data required to describe an ancestor pass-through /* Structure holding data required to describe an ancestor pass-through
...@@ -127,18 +116,10 @@ struct GTY(()) ipa_ancestor_jf_data ...@@ -127,18 +116,10 @@ struct GTY(()) ipa_ancestor_jf_data
{ {
/* Offset of the field representing the ancestor. */ /* Offset of the field representing the ancestor. */
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
/* Type of the result.
When TYPE_PRESERVED is false, TYPE is NULL, since it is only
relevant for the devirtualization machinery. */
tree type;
/* Number of the caller's formal parameter being passed. */ /* Number of the caller's formal parameter being passed. */
int formal_id; int formal_id;
/* Flag with the same meaning like agg_preserve in ipa_pass_through_data. */ /* Flag with the same meaning like agg_preserve in ipa_pass_through_data. */
unsigned agg_preserved : 1; unsigned agg_preserved : 1;
/* When set to true, we guarantee that, if there is a C++ object pointed to
by this object, it does not undergo dynamic type change in the course of
functions decribed by this jump function. */
unsigned type_preserved : 1;
}; };
/* An element in an aggegate part of a jump function describing a known value /* An element in an aggegate part of a jump function describing a known value
...@@ -189,7 +170,6 @@ struct GTY (()) ipa_jump_func ...@@ -189,7 +170,6 @@ struct GTY (()) ipa_jump_func
functions and member_cst holds constant c++ member functions. */ functions and member_cst holds constant c++ member functions. */
union jump_func_value union jump_func_value
{ {
struct ipa_known_type_data GTY ((tag ("IPA_JF_KNOWN_TYPE"))) known_type;
struct ipa_constant_data GTY ((tag ("IPA_JF_CONST"))) constant; struct ipa_constant_data GTY ((tag ("IPA_JF_CONST"))) constant;
struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through; struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;
struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR"))) ancestor; struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR"))) ancestor;
...@@ -197,34 +177,6 @@ struct GTY (()) ipa_jump_func ...@@ -197,34 +177,6 @@ struct GTY (()) ipa_jump_func
}; };
/* Return the offset of the component that is described by a known type jump
function JFUNC. */
static inline HOST_WIDE_INT
ipa_get_jf_known_type_offset (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_KNOWN_TYPE);
return jfunc->value.known_type.offset;
}
/* Return the base type of a known type jump function JFUNC. */
static inline tree
ipa_get_jf_known_type_base_type (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_KNOWN_TYPE);
return jfunc->value.known_type.base_type;
}
/* Return the component type of a known type jump function JFUNC. */
static inline tree
ipa_get_jf_known_type_component_type (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_KNOWN_TYPE);
return jfunc->value.known_type.component_type;
}
/* Return the constant stored in a constant jump functin JFUNC. */ /* Return the constant stored in a constant jump functin JFUNC. */
static inline tree static inline tree
...@@ -297,15 +249,6 @@ ipa_get_jf_ancestor_offset (struct ipa_jump_func *jfunc) ...@@ -297,15 +249,6 @@ ipa_get_jf_ancestor_offset (struct ipa_jump_func *jfunc)
return jfunc->value.ancestor.offset; return jfunc->value.ancestor.offset;
} }
/* Return the result type of an ancestor jump function JFUNC. */
static inline tree
ipa_get_jf_ancestor_type (struct ipa_jump_func *jfunc)
{
gcc_checking_assert (jfunc->type == IPA_JF_ANCESTOR);
return jfunc->value.ancestor.type;
}
/* Return the number of the caller's formal parameter that an ancestor jump /* Return the number of the caller's formal parameter that an ancestor jump
function JFUNC refers to. */ function JFUNC refers to. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment