Support ofsetted parameters in local modref
Jan Hubicka
hubicka@ucw.cz
Tue Oct 13 09:55:26 GMT 2020
> Hi,
> this patch makes local modref to track parameters that are passed through with
> and adjustment (via pointer_plus or addr_expr of mem_ref). I intended to re-use
> logic in ipa-prop, but it turns out that it is weird:
> if (TREE_CODE (op1) != ADDR_EXPR)
> return;
> op1 = TREE_OPERAND (op1, 0);
> if (TREE_CODE (TREE_TYPE (op1)) != RECORD_TYPE)
> return;
> base = get_ref_base_and_extent_hwi (op1, &offset, &size, &reverse);
> offset_int mem_offset;
> if (!base
> || TREE_CODE (base) != MEM_REF
> || !mem_ref_offset (base).is_constant (&mem_offset))
> return;
> offset += mem_offset.to_short_addr () * BITS_PER_UNIT;
> ssa = TREE_OPERAND (base, 0);
> if (TREE_CODE (ssa) != SSA_NAME
> || !SSA_NAME_IS_DEFAULT_DEF (ssa)
> || offset < 0)
> return;
>
> /* Dynamic types are changed in constructors and destructors. */
> index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
> if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
> ipa_set_ancestor_jf (jfunc, offset, index,
> parm_ref_data_pass_through_p (fbi, index, call, ssa));
>
> First it does not handle POINTER_PLUS that is quite common i.e. for
>
> test (int *a)
> {
> test2 (a+1);
> }
>
> and also it restrict to access paths that starts by RECORD_TYPE. This seems
> not to make sense since all ADDR_EXPRs of refs are just pointer adjustements.
> I think it is leftover from time when ancestor was meant to track C++ type
> hiearchy.
>
> Next it also does refuse negative offset for not very apparent reason (this
> happens in multiple inheritance in C++).
>
> On tramp3d it is also common that the parameter ADDR_EXPR happens in
> separate statement rather than call itself (i.e. no forward propagation
> is done)
>
> Finally it works on bits witout overflow check and uses HOST_WIDE_INT
> instead of poly_int64 that I think would be right datatype to accumulate
> offsets these days.
>
> So I implemented my own pattern matching and I think we should switch ipa-prop
> on it incrementally. It is based on similar logic in
> ao_ref_init_from_ptr_and_size. I support chained statements since they happen
> in tramp3d after early opts.
>
> Bootstrapped/regtested x86_64-linux. Also ltobootstrapped and I am waiting
> for cc1plus stats to finish. OK?
So stats finished, for record:
Alias oracle query stats:
refs_may_alias_p: 64156070 disambiguations, 74373175 queries
ref_maybe_used_by_call_p: 142785 disambiguations, 65060092 queries
call_may_clobber_ref_p: 22991 disambiguations, 28817 queries
nonoverlapping_component_refs_p: 0 disambiguations, 37222 queries
nonoverlapping_refs_since_match_p: 19427 disambiguations, 55940 must overlaps, 76158 queries
aliasing_component_refs_p: 54747 disambiguations, 760197 queries
TBAA oracle: 23613733 disambiguations 55949704 queries
16074768 are in alias set 0
10619115 queries asked about the same object
125 queries asked about the same alias set
0 access volatile
3995285 are dependent in the DAG
1646678 are aritificially in conflict with void *
Modref stats:
modref use: 11758 disambiguations, 40510 queries
modref clobber: 1505226 disambiguations, 1825004 queries
3894419 tbaa queries (2.133924 per modref query)
621924 base compares (0.340780 per modref query)
So about 8% increase in clobber disambiguation rate. Use disambiguation
seems unchanged.
Honza
>
> gcc/ChangeLog:
>
> 2020-10-13 Jan Hubicka <hubicka@ucw.cz>
>
> * ipa-modref.c (merge_call_side_effects): Use
> unadjusted_ptr_and_unit_offset.
> * ipa-prop.c (unadjusted_ptr_and_unit_offset): Declare.
> * ipa-prop.h (unadjusted_ptr_and_unit_offset): New function.
>
> diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
> index 4f86b9ccea1..92119eb6fe3 100644
> --- a/gcc/ipa-modref.c
> +++ b/gcc/ipa-modref.c
> @@ -531,6 +532,10 @@ merge_call_side_effects (modref_summary *cur_summary,
> for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
> {
> tree op = gimple_call_arg (stmt, i);
> + bool offset_known;
> + poly_int64 offset;
> +
> + offset_known = unadjusted_ptr_and_unit_offset (op, &op, &offset);
> if (TREE_CODE (op) == SSA_NAME
> && SSA_NAME_IS_DEFAULT_DEF (op)
> && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
> @@ -547,15 +552,23 @@ merge_call_side_effects (modref_summary *cur_summary,
> index++;
> }
> parm_map[i].parm_index = index;
> - parm_map[i].parm_offset_known = true;
> - parm_map[i].parm_offset = 0;
> + parm_map[i].parm_offset_known = offset_known;
> + parm_map[i].parm_offset = offset;
> }
> else if (points_to_local_or_readonly_memory_p (op))
> parm_map[i].parm_index = -2;
> else
> parm_map[i].parm_index = -1;
> if (dump_file)
> - fprintf (dump_file, " %i", parm_map[i].parm_index);
> + {
> + fprintf (dump_file, " %i", parm_map[i].parm_index);
> + if (parm_map[i].parm_offset_known)
> + {
> + fprintf (dump_file, " offset:");
> + print_dec ((poly_int64_pod)parm_map[i].parm_offset,
> + dump_file, SIGNED);
> + }
> + }
> }
> if (dump_file)
> fprintf (dump_file, "\n");
> diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
> index 2d09d913051..fe317f56e02 100644
> --- a/gcc/ipa-prop.c
> +++ b/gcc/ipa-prop.c
> @@ -1222,6 +1222,72 @@ load_from_unmodified_param_or_agg (struct ipa_func_body_info *fbi,
> return index;
> }
>
> +/* Walk pointer adjustemnts from OP (such as POINTER_PLUS and ADDR_EXPR)
> + to find original pointer. Initialize RET to the pointer which results from
> + the walk.
> + If offset is known return true and initialize OFFSET_RET. */
> +
> +bool
> +unadjusted_ptr_and_unit_offset (tree op, tree *ret, poly_int64 *offset_ret)
> +{
> + poly_int64 offset = 0;
> + bool offset_known = true;
> +
> + while (true)
> + {
> + if (TREE_CODE (op) == ADDR_EXPR)
> + {
> + poly_int64 extra_offset = 0;
> + tree base = get_addr_base_and_unit_offset (TREE_OPERAND (op, 0),
> + &offset);
> + if (!base)
> + {
> + base = get_base_address (TREE_OPERAND (op, 0));
> + if (TREE_CODE (base) != MEM_REF)
> + break;
> + offset_known = false;
> + }
> + else
> + {
> + if (TREE_CODE (base) != MEM_REF)
> + break;
> + offset += extra_offset;
> + }
> + op = TREE_OPERAND (base, 0);
> + if (mem_ref_offset (base).to_shwi (&extra_offset))
> + offset += extra_offset;
> + else
> + offset_known = false;
> + }
> + else if (TREE_CODE (op) == SSA_NAME
> + && !SSA_NAME_IS_DEFAULT_DEF (op))
> + {
> + gimple *pstmt = SSA_NAME_DEF_STMT (op);
> +
> + if (gimple_assign_single_p (pstmt))
> + op = gimple_assign_rhs1 (pstmt);
> + else if (is_gimple_assign (pstmt)
> + && gimple_assign_rhs_code (pstmt) == POINTER_PLUS_EXPR)
> + {
> + poly_int64 extra_offset = 0;
> + if (ptrdiff_tree_p (gimple_assign_rhs2 (pstmt),
> + &extra_offset))
> + offset += extra_offset;
> + else
> + offset_known = false;
> + op = gimple_assign_rhs1 (pstmt);
> + }
> + else
> + break;
> + }
> + else
> + break;
> + }
> + *ret = op;
> + *offset_ret = offset;
> + return offset_known;
> +}
> +
> /* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
> of an assignment statement STMT, try to determine whether we are actually
> handling any of the following cases and construct an appropriate jump
> diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
> index 8b2edf6300c..0bbbbf9bd9f 100644
> --- a/gcc/ipa-prop.h
> +++ b/gcc/ipa-prop.h
> @@ -1144,6 +1144,8 @@ void ipa_dump_param (FILE *, class ipa_node_params *info, int i);
> void ipa_release_body_info (struct ipa_func_body_info *);
> tree ipa_get_callee_param_type (struct cgraph_edge *e, int i);
> bool ipcp_get_parm_bits (tree, tree *, widest_int *);
> +bool unadjusted_ptr_and_unit_offset (tree op, tree *ret,
> + poly_int64 *offset_ret);
>
> /* From tree-sra.c: */
> tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree,
More information about the Gcc-patches
mailing list