diff options
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r-- | gcc/tree-sra.c | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 3922c22d824..67001a64564 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -144,7 +144,9 @@ struct access points to the first one. */ struct access *first_child; - /* Pointer to the next sibling in the access tree as described above. */ + /* In intraprocedural SRA, pointer to the next sibling in the access tree as + described above. In IPA-SRA this is a pointer to the next access + belonging to the same group (having the same representative). */ struct access *next_sibling; /* Pointers to the first and last element in the linked list of assign @@ -1231,7 +1233,6 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, case UNION_TYPE: case QUAL_UNION_TYPE: case RECORD_TYPE: - /* Some ADA records are half-unions, treat all of them the same. */ for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld)) { HOST_WIDE_INT pos, size; @@ -1242,7 +1243,10 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, pos = int_bit_position (fld); gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0); - size = tree_low_cst (DECL_SIZE (fld), 1); + tr_size = DECL_SIZE (fld); + if (!tr_size || !host_integerp (tr_size, 1)) + continue; + size = tree_low_cst (tr_size, 1); if (pos > offset || (pos + size) <= offset) continue; @@ -1300,7 +1304,8 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset, /* Construct an expression that would reference a part of aggregate *EXPR of type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the function only determines whether it can build such a reference without - actually doing it. + actually doing it, otherwise, the tree it points to is unshared first and + then used as a base for furhter sub-references. FIXME: Eventually this should be replaced with maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a @@ -1313,6 +1318,9 @@ build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset, { location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION; + if (expr) + *expr = unshare_expr (*expr); + if (allow_ptr && POINTER_TYPE_P (type)) { type = TREE_TYPE (type); @@ -1755,7 +1763,7 @@ create_artificial_child_access (struct access *parent, struct access *model, access but LACC is not, change the type of the latter, if possible. */ static bool -propagate_subacesses_accross_link (struct access *lacc, struct access *racc) +propagate_subaccesses_across_link (struct access *lacc, struct access *racc) { struct access *rchild; HOST_WIDE_INT norm_delta = lacc->offset - racc->offset; @@ -1796,7 +1804,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc) rchild->grp_hint = 1; new_acc->grp_hint |= new_acc->grp_read; if (rchild->first_child) - ret |= propagate_subacesses_accross_link (new_acc, rchild); + ret |= propagate_subaccesses_across_link (new_acc, rchild); } continue; } @@ -1814,7 +1822,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc) { ret = true; if (racc->first_child) - propagate_subacesses_accross_link (new_acc, rchild); + propagate_subaccesses_across_link (new_acc, rchild); } } @@ -1840,7 +1848,7 @@ propagate_all_subaccesses (void) if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base))) continue; lacc = lacc->group_representative; - if (propagate_subacesses_accross_link (lacc, racc) + if (propagate_subaccesses_across_link (lacc, racc) && lacc->first_link) add_access_to_work_queue (lacc); } @@ -1956,7 +1964,7 @@ generate_subtree_copies (struct access *access, tree agg, { do { - tree expr = unshare_expr (agg); + tree expr = agg; if (chunk_size && access->offset >= start_offset + chunk_size) return; @@ -2231,7 +2239,7 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc, rhs = unshare_expr (lacc->expr); else { - rhs = unshare_expr (top_racc->base); + rhs = top_racc->base; repl_found = build_ref_for_offset (&rhs, TREE_TYPE (top_racc->base), offset, lacc->type, false); @@ -2368,7 +2376,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, if (AGGREGATE_TYPE_P (TREE_TYPE (lhs)) && !access_has_children_p (lacc)) { - tree expr = unshare_expr (lhs); + tree expr = lhs; if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0, TREE_TYPE (rhs), false)) { @@ -2379,7 +2387,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi, else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs)) && !access_has_children_p (racc)) { - tree expr = unshare_expr (rhs); + tree expr = rhs; if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0, TREE_TYPE (lhs), false)) rhs = expr; @@ -2812,33 +2820,34 @@ analyze_modified_params (VEC (access_p, heap) *representatives) for (i = 0; i < func_param_count; i++) { - struct access *repr = VEC_index (access_p, representatives, i); - VEC (access_p, heap) *access_vec; - int j, access_count; - tree parm; + struct access *repr; - if (!repr || no_accesses_p (repr)) - continue; - parm = repr->base; - if (!POINTER_TYPE_P (TREE_TYPE (parm)) - || repr->grp_maybe_modified) - continue; - - access_vec = get_base_access_vector (parm); - access_count = VEC_length (access_p, access_vec); - for (j = 0; j < access_count; j++) + for (repr = VEC_index (access_p, representatives, i); + repr; + repr = repr->next_grp) { struct access *access; + bitmap visited; ao_ref ar; - /* All accesses are read ones, otherwise grp_maybe_modified would be - trivially set. */ - access = VEC_index (access_p, access_vec, j); - ao_ref_init (&ar, access->expr); - walk_aliased_vdefs (&ar, gimple_vuse (access->stmt), - mark_maybe_modified, repr, NULL); - if (repr->grp_maybe_modified) - break; + if (no_accesses_p (repr)) + continue; + if (!POINTER_TYPE_P (TREE_TYPE (repr->base)) + || repr->grp_maybe_modified) + continue; + + ao_ref_init (&ar, repr->expr); + visited = BITMAP_ALLOC (NULL); + for (access = repr; access; access = access->next_sibling) + { + /* All accesses are read ones, otherwise grp_maybe_modified would + be trivially set. */ + walk_aliased_vdefs (&ar, gimple_vuse (access->stmt), + mark_maybe_modified, repr, &visited); + if (repr->grp_maybe_modified) + break; + } + BITMAP_FREE (visited); } } } @@ -3007,24 +3016,30 @@ static struct access * unmodified_by_ref_scalar_representative (tree parm) { int i, access_count; - struct access *access; + struct access *repr; VEC (access_p, heap) *access_vec; access_vec = get_base_access_vector (parm); gcc_assert (access_vec); - access_count = VEC_length (access_p, access_vec); + repr = VEC_index (access_p, access_vec, 0); + if (repr->write) + return NULL; + repr->group_representative = repr; - for (i = 0; i < access_count; i++) + access_count = VEC_length (access_p, access_vec); + for (i = 1; i < access_count; i++) { - access = VEC_index (access_p, access_vec, i); + struct access *access = VEC_index (access_p, access_vec, i); if (access->write) return NULL; + access->group_representative = repr; + access->next_sibling = repr->next_sibling; + repr->next_sibling = access; } - access = VEC_index (access_p, access_vec, 0); - access->grp_read = 1; - access->grp_scalar_ptr = 1; - return access; + repr->grp_read = 1; + repr->grp_scalar_ptr = 1; + return repr; } /* Sort collected accesses for parameter PARM, identify representatives for @@ -3079,6 +3094,9 @@ splice_param_accesses (tree parm, bool *ro_grp) return NULL; modification |= ac2->write; + ac2->group_representative = access; + ac2->next_sibling = access->next_sibling; + access->next_sibling = ac2; j++; } |