ipa-prop.c (ipa_set_jf_known_type): Check that we add only records.
* ipa-prop.c (ipa_set_jf_known_type): Check that we add only records. (detect_type_change_1): Rename to ... (detect_type_change): ... this one; early return on non-polymorphic types. (detect_type_change_ssa): Add comp_type parameter; update use of detect_type_change. (compute_complex_assign_jump_func): Add param_type parameter; update use of detect_type_change_ssa. (compute_complex_ancestor_jump_func): Likewise. (ipa_get_callee_param_type): New function. (ipa_compute_jump_functions_for_edge): Compute parameter type; update calls to the jump function computation functions. From-SVN: r202126
This commit is contained in:
parent
600b5b1d5c
commit
06d6505030
2 changed files with 114 additions and 47 deletions
|
@ -1,3 +1,19 @@
|
|||
2013-08-30 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* ipa-prop.c (ipa_set_jf_known_type): Check that we add
|
||||
only records.
|
||||
(detect_type_change_1): Rename to ...
|
||||
(detect_type_change): ... this one; early return on non-polymorphic
|
||||
types.
|
||||
(detect_type_change_ssa): Add comp_type parameter; update
|
||||
use of detect_type_change.
|
||||
(compute_complex_assign_jump_func): Add param_type parameter;
|
||||
update use of detect_type_change_ssa.
|
||||
(compute_complex_ancestor_jump_func): Likewise.
|
||||
(ipa_get_callee_param_type): New function.
|
||||
(ipa_compute_jump_functions_for_edge): Compute parameter type;
|
||||
update calls to the jump function computation functions.
|
||||
|
||||
2013-08-30 Teresa Johnson <tejohnson@google.com>
|
||||
Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
|
|
145
gcc/ipa-prop.c
145
gcc/ipa-prop.c
|
@ -371,6 +371,8 @@ static void
|
|||
ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
|
||||
tree base_type, tree component_type)
|
||||
{
|
||||
gcc_assert (TREE_CODE (component_type) == RECORD_TYPE
|
||||
&& TYPE_BINFO (component_type));
|
||||
jfunc->type = IPA_JF_KNOWN_TYPE;
|
||||
jfunc->value.known_type.offset = offset,
|
||||
jfunc->value.known_type.base_type = base_type;
|
||||
|
@ -633,13 +635,16 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
|
|||
|
||||
|
||||
|
||||
/* Like detect_type_change but with extra argument COMP_TYPE which will become
|
||||
the component type part of new JFUNC of dynamic type change is detected and
|
||||
the new base type is identified. */
|
||||
/* Detect whether the dynamic type of ARG of COMP_TYPE has changed (before
|
||||
callsite CALL) by looking for assignments to its virtual table pointer. If
|
||||
it is, return true and fill in the jump function JFUNC with relevant type
|
||||
information or set it to unknown. ARG is the object itself (not a pointer
|
||||
to it, unless dereferenced). BASE is the base of the memory access as
|
||||
returned by get_ref_base_and_extent, as is the offset. */
|
||||
|
||||
static bool
|
||||
detect_type_change_1 (tree arg, tree base, tree comp_type, gimple call,
|
||||
struct ipa_jump_func *jfunc, HOST_WIDE_INT offset)
|
||||
detect_type_change (tree arg, tree base, tree comp_type, gimple call,
|
||||
struct ipa_jump_func *jfunc, HOST_WIDE_INT offset)
|
||||
{
|
||||
struct type_change_info tci;
|
||||
ao_ref ao;
|
||||
|
@ -649,7 +654,12 @@ detect_type_change_1 (tree arg, tree base, tree comp_type, gimple call,
|
|||
|| handled_component_p (arg));
|
||||
/* Const calls cannot call virtual methods through VMT and so type changes do
|
||||
not matter. */
|
||||
if (!flag_devirtualize || !gimple_vuse (call))
|
||||
if (!flag_devirtualize || !gimple_vuse (call)
|
||||
/* Be sure expected_type is polymorphic. */
|
||||
|| !comp_type
|
||||
|| TREE_CODE (comp_type) != RECORD_TYPE
|
||||
|| !TYPE_BINFO (comp_type)
|
||||
|| !BINFO_VTABLE (TYPE_BINFO (comp_type)))
|
||||
return false;
|
||||
|
||||
ao_ref_init (&ao, arg);
|
||||
|
@ -679,40 +689,23 @@ detect_type_change_1 (tree arg, tree base, tree comp_type, gimple call,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Detect whether the dynamic type of ARG has changed (before callsite CALL) by
|
||||
looking for assignments to its virtual table pointer. If it is, return true
|
||||
and fill in the jump function JFUNC with relevant type information or set it
|
||||
to unknown. ARG is the object itself (not a pointer to it, unless
|
||||
dereferenced). BASE is the base of the memory access as returned by
|
||||
get_ref_base_and_extent, as is the offset. */
|
||||
|
||||
static bool
|
||||
detect_type_change (tree arg, tree base, gimple call,
|
||||
struct ipa_jump_func *jfunc, HOST_WIDE_INT offset)
|
||||
{
|
||||
return detect_type_change_1 (arg, base, TREE_TYPE (arg), call, jfunc, offset);
|
||||
}
|
||||
|
||||
/* Like detect_type_change but ARG is supposed to be a non-dereferenced pointer
|
||||
SSA name (its dereference will become the base and the offset is assumed to
|
||||
be zero). */
|
||||
|
||||
static bool
|
||||
detect_type_change_ssa (tree arg, gimple call, struct ipa_jump_func *jfunc)
|
||||
detect_type_change_ssa (tree arg, tree comp_type,
|
||||
gimple call, struct ipa_jump_func *jfunc)
|
||||
{
|
||||
tree comp_type;
|
||||
|
||||
gcc_checking_assert (TREE_CODE (arg) == SSA_NAME);
|
||||
if (!flag_devirtualize
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (arg))
|
||||
|| TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != RECORD_TYPE)
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (arg)))
|
||||
return false;
|
||||
|
||||
comp_type = TREE_TYPE (TREE_TYPE (arg));
|
||||
arg = build2 (MEM_REF, ptr_type_node, arg,
|
||||
build_int_cst (ptr_type_node, 0));
|
||||
|
||||
return detect_type_change_1 (arg, arg, comp_type, call, jfunc, 0);
|
||||
return detect_type_change (arg, arg, comp_type, call, jfunc, 0);
|
||||
}
|
||||
|
||||
/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
|
||||
|
@ -988,7 +981,8 @@ static void
|
|||
compute_complex_assign_jump_func (struct ipa_node_params *info,
|
||||
struct param_analysis_info *parms_ainfo,
|
||||
struct ipa_jump_func *jfunc,
|
||||
gimple call, gimple stmt, tree name)
|
||||
gimple call, gimple stmt, tree name,
|
||||
tree param_type)
|
||||
{
|
||||
HOST_WIDE_INT offset, size, max_size;
|
||||
tree op1, tc_ssa, base, ssa;
|
||||
|
@ -1030,7 +1024,11 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
|
|||
{
|
||||
bool agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
|
||||
call, tc_ssa);
|
||||
bool type_p = !detect_type_change_ssa (tc_ssa, call, jfunc);
|
||||
bool type_p = false;
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1057,9 +1055,10 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
|
|||
|
||||
/* Dynamic types are changed in constructors and destructors. */
|
||||
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
|
||||
if (index >= 0)
|
||||
if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
|
||||
{
|
||||
bool type_p = !detect_type_change (op1, base, call, jfunc, offset);
|
||||
bool type_p = !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, TREE_TYPE (op1), index,
|
||||
parm_ref_data_pass_through_p (&parms_ainfo[index],
|
||||
|
@ -1137,7 +1136,7 @@ static void
|
|||
compute_complex_ancestor_jump_func (struct ipa_node_params *info,
|
||||
struct param_analysis_info *parms_ainfo,
|
||||
struct ipa_jump_func *jfunc,
|
||||
gimple call, gimple phi)
|
||||
gimple call, gimple phi, tree param_type)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
gimple assign, cond;
|
||||
|
@ -1188,7 +1187,10 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
|
|||
return;
|
||||
}
|
||||
|
||||
bool type_p = !detect_type_change (obj, expr, call, jfunc, offset);
|
||||
bool type_p = false;
|
||||
if (param_type && POINTER_TYPE_P (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, TREE_TYPE (obj), index,
|
||||
parm_ref_data_pass_through_p (&parms_ainfo[index],
|
||||
|
@ -1197,18 +1199,24 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
|
|||
|
||||
/* 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. */
|
||||
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)
|
||||
gimple call, tree expected_type)
|
||||
{
|
||||
HOST_WIDE_INT offset, size, max_size;
|
||||
tree base;
|
||||
|
||||
if (!flag_devirtualize
|
||||
|| TREE_CODE (op) != ADDR_EXPR
|
||||
|| TREE_CODE (TREE_TYPE (TREE_TYPE (op))) != RECORD_TYPE)
|
||||
|| TREE_CODE (TREE_TYPE (TREE_TYPE (op))) != RECORD_TYPE
|
||||
/* Be sure expected_type is polymorphic. */
|
||||
|| !expected_type
|
||||
|| TREE_CODE (expected_type) != RECORD_TYPE
|
||||
|| !TYPE_BINFO (expected_type)
|
||||
|| !BINFO_VTABLE (TYPE_BINFO (expected_type)))
|
||||
return;
|
||||
|
||||
op = TREE_OPERAND (op, 0);
|
||||
|
@ -1220,11 +1228,11 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
|
|||
|| is_global_var (base))
|
||||
return;
|
||||
|
||||
if (!TYPE_BINFO (TREE_TYPE (base))
|
||||
|| detect_type_change (op, base, call, jfunc, offset))
|
||||
if (detect_type_change (op, base, expected_type, call, jfunc, offset))
|
||||
return;
|
||||
|
||||
ipa_set_jf_known_type (jfunc, offset, TREE_TYPE (base), TREE_TYPE (op));
|
||||
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
|
||||
|
@ -1495,6 +1503,37 @@ determine_known_aggregate_parts (gimple call, tree arg,
|
|||
}
|
||||
}
|
||||
|
||||
static tree
|
||||
ipa_get_callee_param_type (struct cgraph_edge *e, int i)
|
||||
{
|
||||
int n;
|
||||
tree type = (e->callee
|
||||
? TREE_TYPE (e->callee->symbol.decl)
|
||||
: gimple_call_fntype (e->call_stmt));
|
||||
tree t = TYPE_ARG_TYPES (type);
|
||||
|
||||
for (n = 0; n < i; n++)
|
||||
{
|
||||
if (!t)
|
||||
break;
|
||||
t = TREE_CHAIN (t);
|
||||
}
|
||||
if (t)
|
||||
return TREE_VALUE (t);
|
||||
if (!e->callee)
|
||||
return NULL;
|
||||
t = DECL_ARGUMENTS (e->callee->symbol.decl);
|
||||
for (n = 0; n < i; n++)
|
||||
{
|
||||
if (!t)
|
||||
return NULL;
|
||||
t = TREE_CHAIN (t);
|
||||
}
|
||||
if (t)
|
||||
return TREE_TYPE (t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Compute jump function for all arguments of callsite CS and insert the
|
||||
information in the jump_functions array in the ipa_edge_args corresponding
|
||||
to this callsite. */
|
||||
|
@ -1519,6 +1558,7 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
|
|||
{
|
||||
struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, n);
|
||||
tree arg = gimple_call_arg (call, n);
|
||||
tree param_type = ipa_get_callee_param_type (cs, n);
|
||||
|
||||
if (is_gimple_ip_invariant (arg))
|
||||
ipa_set_jf_constant (jfunc, arg, cs);
|
||||
|
@ -1547,9 +1587,14 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
|
|||
bool agg_p, type_p;
|
||||
agg_p = parm_ref_data_pass_through_p (&parms_ainfo[index],
|
||||
call, arg);
|
||||
type_p = !detect_type_change_ssa (arg, call, jfunc);
|
||||
if (param_type && POINTER_TYPE_P (param_type))
|
||||
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);
|
||||
ipa_set_jf_simple_pass_through (jfunc, index, agg_p,
|
||||
type_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1557,14 +1602,18 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
|
|||
gimple stmt = SSA_NAME_DEF_STMT (arg);
|
||||
if (is_gimple_assign (stmt))
|
||||
compute_complex_assign_jump_func (info, parms_ainfo, jfunc,
|
||||
call, stmt, arg);
|
||||
call, stmt, arg, param_type);
|
||||
else if (gimple_code (stmt) == GIMPLE_PHI)
|
||||
compute_complex_ancestor_jump_func (info, parms_ainfo, jfunc,
|
||||
call, stmt);
|
||||
call, stmt, param_type);
|
||||
}
|
||||
}
|
||||
else
|
||||
compute_known_type_jump_func (arg, jfunc, call);
|
||||
compute_known_type_jump_func (arg, jfunc, call,
|
||||
param_type
|
||||
&& POINTER_TYPE_P (param_type)
|
||||
? TREE_TYPE (param_type)
|
||||
: NULL);
|
||||
|
||||
if ((jfunc->type != IPA_JF_PASS_THROUGH
|
||||
|| !ipa_get_jf_pass_through_agg_preserved (jfunc))
|
||||
|
@ -1908,7 +1957,8 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
|
|||
anc_offset = 0;
|
||||
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (obj));
|
||||
gcc_assert (index >= 0);
|
||||
if (detect_type_change_ssa (obj, call, &jfunc))
|
||||
if (detect_type_change_ssa (obj, obj_type_ref_class (target),
|
||||
call, &jfunc))
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -1922,7 +1972,8 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
|
|||
index = ipa_get_param_decl_index (info,
|
||||
SSA_NAME_VAR (TREE_OPERAND (expr, 0)));
|
||||
gcc_assert (index >= 0);
|
||||
if (detect_type_change (obj, expr, call, &jfunc, anc_offset))
|
||||
if (detect_type_change (obj, expr, obj_type_ref_class (target),
|
||||
call, &jfunc, anc_offset))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2134,7 +2185,7 @@ ipa_intraprocedural_devirtualization (gimple call)
|
|||
|
||||
jfunc.type = IPA_JF_UNKNOWN;
|
||||
compute_known_type_jump_func (OBJ_TYPE_REF_OBJECT (otr), &jfunc,
|
||||
call);
|
||||
call, obj_type_ref_class (otr));
|
||||
if (jfunc.type != IPA_JF_KNOWN_TYPE)
|
||||
return NULL_TREE;
|
||||
binfo = ipa_binfo_from_known_type_jfunc (&jfunc);
|
||||
|
|
Loading…
Add table
Reference in a new issue