Hi, the main purpose of this patch is to break up function determine_known_aggregate_parts so that the next patch can use the standalone bits and to make the changes slightly easier for review.
However, this patch also removes some of the offset checks which Honza correctly thought superfluous and even possibly filtering out useful information. Bootstrapped and tested and LTO-bootstrapped on x86_64-linux. OK for trunk after the preceeding patches get in? Thanks, Martin 2014-02-19 Martin Jambor <mjam...@suse.cz> * ipa-prop.c (get_place_in_agg_contents_list): New function. (build_agg_jump_func_from_list): Likewise. (determine_known_aggregate_parts): Renamed to determine_locally_known_aggregate_parts. Moved some functionality to the two functions above, removed bound checks. Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -1679,14 +1679,72 @@ struct ipa_known_agg_contents_list struct ipa_known_agg_contents_list *next; }; +/* Find the proper place in linked list of ipa_known_agg_contents_list + structures where to put a new one with the given LHS_OFFSET and LHS_SIZE, + unless there is a partial overlap, in which case return NULL, or such + element is already there, in which case set *ALREADY_THERE to true. */ + +static struct ipa_known_agg_contents_list ** +get_place_in_agg_contents_list (struct ipa_known_agg_contents_list **list, + HOST_WIDE_INT lhs_offset, + HOST_WIDE_INT lhs_size, + bool *already_there) +{ + struct ipa_known_agg_contents_list **p = list; + while (*p && (*p)->offset < lhs_offset) + { + if ((*p)->offset + (*p)->size > lhs_offset) + return NULL; + p = &(*p)->next; + } + + if (*p && (*p)->offset < lhs_offset + lhs_size) + { + if ((*p)->offset == lhs_offset && (*p)->size == lhs_size) + /* We already know this value is subsequently overwritten with + something else. */ + *already_there = true; + else + /* Otherwise this is a partial overlap which we cannot + represent. */ + return NULL; + } + return p; +} + +/* Build aggregate jump function from LIST, assuming there are exactly + CONST_COUNT constant entries there and that th offset of the passed argument + is ARG_OFFSET and store it into JFUNC. */ + +static void +build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list, + int const_count, HOST_WIDE_INT arg_offset, + struct ipa_jump_func *jfunc) +{ + vec_alloc (jfunc->agg.items, const_count); + while (list) + { + if (list->constant) + { + struct ipa_agg_jf_item item; + item.offset = list->offset - arg_offset; + gcc_assert ((item.offset % BITS_PER_UNIT) == 0); + item.value = unshare_expr_without_location (list->constant); + jfunc->agg.items->quick_push (item); + } + list = list->next; + } +} + /* Traverse statements from CALL backwards, scanning whether an aggregate given in ARG is filled in with constant values. ARG can either be an aggregate - expression or a pointer to an aggregate. ARG_TYPE is the type of the aggregate. - JFUNC is the jump function into which the constants are subsequently stored. */ + expression or a pointer to an aggregate. ARG_TYPE is the type of the + aggregate. JFUNC is the jump function into which the constants are + subsequently stored. */ static void -determine_known_aggregate_parts (gimple call, tree arg, tree arg_type, - struct ipa_jump_func *jfunc) +determine_locally_known_aggregate_parts (gimple call, tree arg, tree arg_type, + struct ipa_jump_func *jfunc) { struct ipa_known_agg_contents_list *list = NULL; int item_count = 0, const_count = 0; @@ -1728,10 +1786,8 @@ determine_known_aggregate_parts (gimple return; if (DECL_P (arg_base)) { - tree size; check_ref = false; - size = build_int_cst (integer_type_node, arg_size); - ao_ref_init_from_ptr_and_size (&r, arg_base, size); + ao_ref_init (&r, arg_base); } else return; @@ -1769,7 +1825,6 @@ determine_known_aggregate_parts (gimple gimple stmt = gsi_stmt (gsi); HOST_WIDE_INT lhs_offset, lhs_size, lhs_max_size; tree lhs, rhs, lhs_base; - bool partial_overlap; if (!stmt_may_clobber_ref_p_1 (stmt, &r)) continue; @@ -1786,11 +1841,7 @@ determine_known_aggregate_parts (gimple lhs_base = get_ref_base_and_extent (lhs, &lhs_offset, &lhs_size, &lhs_max_size); if (lhs_max_size == -1 - || lhs_max_size != lhs_size - || (lhs_offset < arg_offset - && lhs_offset + lhs_size > arg_offset) - || (lhs_offset < arg_offset + arg_size - && lhs_offset + lhs_size > arg_offset + arg_size)) + || lhs_max_size != lhs_size) break; if (check_ref) @@ -1808,34 +1859,13 @@ determine_known_aggregate_parts (gimple break; } - if (lhs_offset + lhs_size < arg_offset - || lhs_offset >= (arg_offset + arg_size)) - continue; - - partial_overlap = false; - p = &list; - while (*p && (*p)->offset < lhs_offset) - { - if ((*p)->offset + (*p)->size > lhs_offset) - { - partial_overlap = true; - break; - } - p = &(*p)->next; - } - if (partial_overlap) + bool already_there = false; + p = get_place_in_agg_contents_list (&list, lhs_offset, lhs_size, + &already_there); + if (!p) break; - if (*p && (*p)->offset < lhs_offset + lhs_size) - { - if ((*p)->offset == lhs_offset && (*p)->size == lhs_size) - /* We already know this value is subsequently overwritten with - something else. */ - continue; - else - /* Otherwise this is a partial overlap which we cannot - represent. */ - break; - } + if (already_there) + continue; rhs = get_ssa_def_if_simple_copy (rhs); n = XALLOCA (struct ipa_known_agg_contents_list); @@ -1864,19 +1894,7 @@ determine_known_aggregate_parts (gimple if (const_count) { jfunc->agg.by_ref = by_ref; - vec_alloc (jfunc->agg.items, const_count); - while (list) - { - if (list->constant) - { - struct ipa_agg_jf_item item; - item.offset = list->offset - arg_offset; - gcc_assert ((item.offset % BITS_PER_UNIT) == 0); - item.value = unshare_expr_without_location (list->constant); - jfunc->agg.items->quick_push (item); - } - list = list->next; - } + build_agg_jump_func_from_list (list, const_count, arg_offset, jfunc); } } @@ -2113,7 +2131,7 @@ ipa_compute_jump_functions_for_edge (str && jfunc->type != IPA_JF_ANCESTOR && (AGGREGATE_TYPE_P (TREE_TYPE (arg)) || POINTER_TYPE_P (param_type))) - determine_known_aggregate_parts (call, arg, param_type, jfunc); + determine_locally_known_aggregate_parts (call, arg, param_type, jfunc); } }