diff options
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r-- | gcc/tree-sra.c | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 1d4a632..a896308 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -179,12 +179,15 @@ struct access when grp_to_be_replaced flag is set. */ tree replacement_decl; - /* Is this particular access write access? */ - unsigned write : 1; - /* Is this access an access to a non-addressable field? */ unsigned non_addressable : 1; + /* Is this access made in reverse storage order? */ + unsigned reverse : 1; + + /* Is this particular access write access? */ + unsigned write : 1; + /* Is this access currently in the work queue? */ unsigned grp_queued : 1; @@ -423,6 +426,8 @@ dump_access (FILE *f, struct access *access, bool grp) print_generic_expr (f, access->expr, 0); fprintf (f, ", type = "); print_generic_expr (f, access->type, 0); + fprintf (f, ", non_addressable = %d, reverse = %d", + access->non_addressable, access->reverse); if (grp) fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, " "grp_assignment_write = %d, grp_scalar_read = %d, " @@ -839,9 +844,9 @@ create_access (tree expr, gimple *stmt, bool write) struct access *access; HOST_WIDE_INT offset, size, max_size; tree base = expr; - bool ptr, unscalarizable_region = false; + bool reverse, ptr, unscalarizable_region = false; - base = get_ref_base_and_extent (expr, &offset, &size, &max_size); + base = get_ref_base_and_extent (expr, &offset, &size, &max_size, &reverse); if (sra_mode == SRA_MODE_EARLY_IPA && TREE_CODE (base) == MEM_REF) @@ -895,6 +900,7 @@ create_access (tree expr, gimple *stmt, bool write) access->write = write; access->grp_unscalarizable_region = unscalarizable_region; access->stmt = stmt; + access->reverse = reverse; if (TREE_CODE (expr) == COMPONENT_REF && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1))) @@ -959,7 +965,7 @@ scalarizable_type_p (tree type) } } -static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); +static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, bool, tree, tree); /* Create total_scalarization accesses for all scalar fields of a member of type DECL_TYPE conforming to scalarizable_type_p. BASE @@ -980,8 +986,9 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref) tree ft = TREE_TYPE (fld); tree nref = build3 (COMPONENT_REF, ft, ref, fld, NULL_TREE); - scalarize_elem (base, pos, tree_to_uhwi (DECL_SIZE (fld)), nref, - ft); + scalarize_elem (base, pos, tree_to_uhwi (DECL_SIZE (fld)), + TYPE_REVERSE_STORAGE_ORDER (decl_type), + nref, ft); } break; case ARRAY_TYPE: @@ -1015,7 +1022,9 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref) ref, wide_int_to_tree (domain, idx), NULL_TREE, NULL_TREE); - scalarize_elem (base, el_off, el_size, nref, elemtype); + scalarize_elem (base, el_off, el_size, + TYPE_REVERSE_STORAGE_ORDER (decl_type), + nref, elemtype); el_off += el_size; } } @@ -1029,11 +1038,12 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref) /* Create total_scalarization accesses for a member of type TYPE, which must satisfy either is_gimple_reg_type or scalarizable_type_p. BASE must be the top-most VAR_DECL representing the variable; within that, POS and SIZE locate - the member and REF must be the reference expression for it. */ + the member, REVERSE gives its torage order. and REF must be the reference + expression for it. */ static void -scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size, - tree ref, tree type) +scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size, bool reverse, + tree ref, tree type) { if (is_gimple_reg_type (type)) { @@ -1041,6 +1051,7 @@ scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size, access->expr = ref; access->type = type; access->grp_total_scalarization = 1; + access->reverse = reverse; /* Accesses for intraprocedural SRA can have their stmt NULL. */ } else @@ -1116,7 +1127,7 @@ build_access_from_expr_1 (tree expr, gimple *stmt, bool write) and not the result type. Ada produces such statements. We are also capable of handling the topmost V_C_E but not any of those buried in other handled components. */ - if (TREE_CODE (expr) == VIEW_CONVERT_EXPR) + if (TREE_CODE (expr) == VIEW_CONVERT_EXPR && !storage_order_barrier_p (expr)) expr = TREE_OPERAND (expr, 0); if (contains_view_convert_expr_p (expr)) @@ -1249,7 +1260,11 @@ build_accesses_from_assign (gimple *stmt) lacc = build_access_from_expr_1 (lhs, stmt, true); if (lacc) - lacc->grp_assignment_write = 1; + { + lacc->grp_assignment_write = 1; + if (storage_order_barrier_p (rhs)) + lacc->grp_unscalarizable_region = 1; + } if (racc) { @@ -1257,6 +1272,8 @@ build_accesses_from_assign (gimple *stmt) if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt) && !is_gimple_reg_type (racc->type)) bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base)); + if (storage_order_barrier_p (lhs)) + racc->grp_unscalarizable_region = 1; } if (lacc && racc @@ -1564,17 +1581,15 @@ make_fancy_name (tree expr) } /* Construct a MEM_REF that would reference a part of aggregate BASE of type - EXP_TYPE at the given OFFSET. If BASE is something for which - get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used - to insert new statements either before or below the current one as specified - by INSERT_AFTER. This function is not capable of handling bitfields. - - BASE must be either a declaration or a memory reference that has correct - alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */ + EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is + something for which get_addr_base_and_unit_offset returns NULL, gsi must + be non-NULL and is used to insert new statements either before or below + the current one as specified by INSERT_AFTER. This function is not capable + of handling bitfields. */ tree build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset, - tree exp_type, gimple_stmt_iterator *gsi, + bool reverse, tree exp_type, gimple_stmt_iterator *gsi, bool insert_after) { tree prev_base = base; @@ -1631,6 +1646,7 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset, exp_type = build_aligned_type (exp_type, align); mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off); + REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse; if (TREE_THIS_VOLATILE (prev_base)) TREE_THIS_VOLATILE (mem_ref) = 1; if (TREE_SIDE_EFFECTS (prev_base)) @@ -1657,13 +1673,17 @@ build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset, offset -= int_bit_position (fld); exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0)); - t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after); + t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type, + gsi, insert_after); + /* The flag will be set on the record type. */ + REF_REVERSE_STORAGE_ORDER (t) = 0; return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld, NULL_TREE); } else - return build_ref_for_offset (loc, base, offset, model->type, - gsi, insert_after); + return + build_ref_for_offset (loc, base, offset, model->reverse, model->type, + gsi, insert_after); } /* Attempt to build a memory reference that we could but into a gimple @@ -2320,8 +2340,8 @@ analyze_access_subtree (struct access *root, struct access *parent, && (root->size % BITS_PER_UNIT) == 0); root->type = build_nonstandard_integer_type (root->size, TYPE_UNSIGNED (rt)); - root->expr = build_ref_for_offset (UNKNOWN_LOCATION, - root->base, root->offset, + root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base, + root->offset, root->reverse, root->type, NULL, false); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -2445,6 +2465,7 @@ create_artificial_child_access (struct access *parent, struct access *model, access->type = model->type; access->grp_write = true; access->grp_read = false; + access->reverse = model->reverse; child = &parent->first_child; while (*child && (*child)->offset < new_offset) @@ -2829,6 +2850,7 @@ get_access_for_expr (tree expr) { HOST_WIDE_INT offset, size, max_size; tree base; + bool reverse; /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of a different size than the size of its argument and we need the latter @@ -2836,7 +2858,7 @@ get_access_for_expr (tree expr) if (TREE_CODE (expr) == VIEW_CONVERT_EXPR) expr = TREE_OPERAND (expr, 0); - base = get_ref_base_and_extent (expr, &offset, &size, &max_size); + base = get_ref_base_and_extent (expr, &offset, &size, &max_size, &reverse); if (max_size == -1 || !DECL_P (base)) return NULL; @@ -4469,6 +4491,7 @@ turn_representatives_into_adjustments (vec<access_p> representatives, adj.type = repr->type; adj.alias_ptr_type = reference_alias_ptr_type (repr->expr); adj.offset = repr->offset; + adj.reverse = repr->reverse; adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base)) && (repr->grp_maybe_modified || repr->grp_not_necessarilly_dereferenced)); @@ -5099,9 +5122,9 @@ ipa_sra_check_caller (struct cgraph_node *node, void *data) tree offset; HOST_WIDE_INT bitsize, bitpos; machine_mode mode; - int unsignedp, volatilep = 0; + int unsignedp, reversep, volatilep = 0; get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &volatilep, false); + &unsignedp, &reversep, &volatilep, false); if (bitpos % BITS_PER_UNIT) { iscc->bad_arg_alignment = true; |