From 185c1f3ab939d251923386674195994baa6fa20f Mon Sep 17 00:00:00 2001 From: hubicka Date: Sat, 31 Aug 2013 12:26:32 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202126 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 16 +++++++ gcc/ipa-prop.c | 145 ++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 114 insertions(+), 47 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e78ba1..030fa85 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2013-08-30 Jan Hubicka + + * 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 Steven Bosscher diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index ca13313..fee5d18 100644 --- a/gcc/ipa-prop.c +++ b/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); -- 2.7.4