From 6084da09a030fd735c7ff46bcd5aefbdbe91ddc5 Mon Sep 17 00:00:00 2001 From: aoliva Date: Mon, 30 Apr 2007 17:41:11 +0000 Subject: [PATCH] PR middle-end/22156 Temporarily revert: 2007-04-06 Andreas Tobler 2007-04-05 Alexandre Oliva * tree-sra.c (try_instantiate_multiple_fields): Needlessly initialize align to silence bogus warning. 2007-04-05 Alexandre Oliva * tree-sra.c (struct sra_elt): Add in_bitfld_block. Remove all_no_warning. (struct sra_walk_fns): Remove use_all parameter from use. (sra_hash_tree): Handle BIT_FIELD_REFs. (sra_elt_hash): Don't hash bitfld blocks. (sra_elt_eq): Skip them in parent compares as well. Handle BIT_FIELD_REFs. (sra_walk_expr): Don't maintain or pass down use_all_p. (scan_use): Remove use_all parameter. (scalarize_use): Likewise. Re-expand assignment to BIT_FIELD_REF of gimple_reg. De-scalarize before input or output, and re-scalarize after output. Don't mark anything for no warning. (scalarize_ldst): Adjust. (scalarize_walk_gimple_modify_statement): Likewise. (build_element_name_1): Handle BIT_FIELD_REFs. (instantiate_element): Don't warn for any element whose parent is used as a whole. (instantiate_missing_elements_1): Return the sra_elt. (canon_type_for_field): New. (try_instantiate_multiple_fields): New. (instantiate_missing_elemnts): Use them. (mark_no_warning): Removed. (generate_one_element_ref): Handle BIT_FIELD_REFs. (REPLDUP, sra_build_elt_assignment): New. (generate_copy_inout): Use them. (generate_element_copy): Likewise. Handle bitfld differences. (generate_element_zero): Don't recurse for blocks. Use sra_build_elt_assignment. (generate_one_element_int): Take elt instead of var. Use sra_build_elt_assignment. (generate_element_init_1): Adjust. (scalarize_use, scalarize_copy): Use REPLDUP. (scalarize_ldst): Move assert before dereference. (dump_sra_elt_name): Handle BIT_FIELD_REFs. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124302 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 46 +++++ gcc/tree-sra.c | 587 ++++++--------------------------------------------------- 2 files changed, 106 insertions(+), 527 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index da8aaf6b53d..906135b4a71 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,49 @@ +2007-04-30 Alexandre Oliva + + PR middle-end/22156 + Temporarily revert: + 2007-04-06 Andreas Tobler + * tree-sra.c (sra_build_elt_assignment): Initialize min/maxshift. + 2007-04-05 Alexandre Oliva + * tree-sra.c (try_instantiate_multiple_fields): Needlessly + initialize align to silence bogus warning. + 2007-04-05 Alexandre Oliva + * tree-sra.c (struct sra_elt): Add in_bitfld_block. Remove + all_no_warning. + (struct sra_walk_fns): Remove use_all parameter from use. + (sra_hash_tree): Handle BIT_FIELD_REFs. + (sra_elt_hash): Don't hash bitfld blocks. + (sra_elt_eq): Skip them in parent compares as well. Handle + BIT_FIELD_REFs. + (sra_walk_expr): Don't maintain or pass down use_all_p. + (scan_use): Remove use_all parameter. + (scalarize_use): Likewise. Re-expand assignment to + BIT_FIELD_REF of gimple_reg. De-scalarize before input or + output, and re-scalarize after output. Don't mark anything + for no warning. + (scalarize_ldst): Adjust. + (scalarize_walk_gimple_modify_statement): Likewise. + (build_element_name_1): Handle BIT_FIELD_REFs. + (instantiate_element): Don't warn for any element whose parent + is used as a whole. + (instantiate_missing_elements_1): Return the sra_elt. + (canon_type_for_field): New. + (try_instantiate_multiple_fields): New. + (instantiate_missing_elemnts): Use them. + (mark_no_warning): Removed. + (generate_one_element_ref): Handle BIT_FIELD_REFs. + (REPLDUP, sra_build_elt_assignment): New. + (generate_copy_inout): Use them. + (generate_element_copy): Likewise. Handle bitfld differences. + (generate_element_zero): Don't recurse for blocks. Use + sra_build_elt_assignment. + (generate_one_element_int): Take elt instead of var. Use + sra_build_elt_assignment. + (generate_element_init_1): Adjust. + (scalarize_use, scalarize_copy): Use REPLDUP. + (scalarize_ldst): Move assert before dereference. + (dump_sra_elt_name): Handle BIT_FIELD_REFs. + 2007-04-30 Andrew Pinski PR C++/31721 diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 6cf5e8ee876..239fd847969 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -147,10 +147,6 @@ struct sra_elt /* True if there is BIT_FIELD_REF on the lhs with a vector. */ bool is_vector_lhs; - - /* 1 if the element is a field that is part of a block, 2 if the field - is the block itself, 0 if it's neither. */ - char in_bitfld_block; }; #define IS_ELEMENT_FOR_GROUP(ELEMENT) (TREE_CODE (ELEMENT) == RANGE_EXPR) @@ -465,12 +461,6 @@ sra_hash_tree (tree t) h = iterative_hash_expr (DECL_FIELD_BIT_OFFSET (t), h); break; - case BIT_FIELD_REF: - /* Don't take operand 0 into account, that's our parent. */ - h = iterative_hash_expr (TREE_OPERAND (t, 1), 0); - h = iterative_hash_expr (TREE_OPERAND (t, 2), h); - break; - default: gcc_unreachable (); } @@ -489,14 +479,12 @@ sra_elt_hash (const void *x) h = sra_hash_tree (e->element); - /* Take into account everything except bitfield blocks back up the - chain. Given that chain lengths are rarely very long, this - should be acceptable. If we truly identify this as a performance - problem, it should work to hash the pointer value - "e->parent". */ + /* Take into account everything back up the chain. Given that chain + lengths are rarely very long, this should be acceptable. If we + truly identify this as a performance problem, it should work to + hash the pointer value "e->parent". */ for (p = e->parent; p ; p = p->parent) - if (!p->in_bitfld_block) - h = (h * 65521) ^ sra_hash_tree (p->element); + h = (h * 65521) ^ sra_hash_tree (p->element); return h; } @@ -509,17 +497,8 @@ sra_elt_eq (const void *x, const void *y) const struct sra_elt *a = x; const struct sra_elt *b = y; tree ae, be; - const struct sra_elt *ap = a->parent; - const struct sra_elt *bp = b->parent; - if (ap) - while (ap->in_bitfld_block) - ap = ap->parent; - if (bp) - while (bp->in_bitfld_block) - bp = bp->parent; - - if (ap != bp) + if (a->parent != b->parent) return false; ae = a->element; @@ -554,11 +533,6 @@ sra_elt_eq (const void *x, const void *y) return false; return fields_compatible_p (ae, be); - case BIT_FIELD_REF: - return - tree_int_cst_equal (TREE_OPERAND (ae, 1), TREE_OPERAND (be, 1)) - && tree_int_cst_equal (TREE_OPERAND (ae, 2), TREE_OPERAND (be, 2)); - default: gcc_unreachable (); } @@ -697,9 +671,10 @@ struct sra_walk_fns /* Invoked when ELT is required as a unit. Note that ELT might refer to a leaf node, in which case this is a simple scalar reference. *EXPR_P points to the location of the expression. IS_OUTPUT is true if this - is a left-hand-side reference. */ + is a left-hand-side reference. USE_ALL is true if we saw something we + couldn't quite identify and had to force the use of the entire object. */ void (*use) (struct sra_elt *elt, tree *expr_p, - block_stmt_iterator *bsi, bool is_output); + block_stmt_iterator *bsi, bool is_output, bool use_all); /* Invoked when we have a copy between two scalarizable references. */ void (*copy) (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt, @@ -753,6 +728,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output, tree expr = *expr_p; tree inner = expr; bool disable_scalarization = false; + bool use_all_p = false; /* We're looking to collect a reference expression between EXPR and INNER, such that INNER is a scalarizable decl and all other nodes through EXPR @@ -773,7 +749,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output, if (disable_scalarization) elt->cannot_scalarize = true; else - fns->use (elt, expr_p, bsi, is_output); + fns->use (elt, expr_p, bsi, is_output, use_all_p); } return; @@ -860,6 +836,7 @@ sra_walk_expr (tree *expr_p, block_stmt_iterator *bsi, bool is_output, use_all: expr_p = &TREE_OPERAND (inner, 0); inner = expr = *expr_p; + use_all_p = true; break; default: @@ -907,14 +884,11 @@ sra_walk_asm_expr (tree expr, block_stmt_iterator *bsi, sra_walk_tree_list (ASM_OUTPUTS (expr), bsi, true, fns); } -static void sra_replace (block_stmt_iterator *bsi, tree list); -static tree sra_build_elt_assignment (struct sra_elt *elt, tree src); - /* Walk a GIMPLE_MODIFY_STMT and categorize the assignment appropriately. */ static void sra_walk_gimple_modify_stmt (tree expr, block_stmt_iterator *bsi, - const struct sra_walk_fns *fns) + const struct sra_walk_fns *fns) { struct sra_elt *lhs_elt, *rhs_elt; tree lhs, rhs; @@ -937,7 +911,7 @@ sra_walk_gimple_modify_stmt (tree expr, block_stmt_iterator *bsi, if (!rhs_elt->is_scalar && !TREE_SIDE_EFFECTS (lhs)) fns->ldst (rhs_elt, lhs, bsi, false); else - fns->use (rhs_elt, &GIMPLE_STMT_OPERAND (expr, 1), bsi, false); + fns->use (rhs_elt, &GIMPLE_STMT_OPERAND (expr, 1), bsi, false, false); } /* If it isn't scalarizable, there may be scalarizable variables within, so @@ -984,9 +958,7 @@ sra_walk_gimple_modify_stmt (tree expr, block_stmt_iterator *bsi, /* Otherwise we're being used in some context that requires the aggregate to be seen as a whole. Invoke USE. */ else - { - fns->use (lhs_elt, &GIMPLE_STMT_OPERAND (expr, 0), bsi, true); - } + fns->use (lhs_elt, &GIMPLE_STMT_OPERAND (expr, 0), bsi, true, false); } /* Similarly to above, LHS_ELT being null only means that the LHS as a @@ -1097,7 +1069,7 @@ find_candidates_for_sra (void) static void scan_use (struct sra_elt *elt, tree *expr_p ATTRIBUTE_UNUSED, block_stmt_iterator *bsi ATTRIBUTE_UNUSED, - bool is_output ATTRIBUTE_UNUSED) + bool is_output ATTRIBUTE_UNUSED, bool use_all ATTRIBUTE_UNUSED) { elt->n_uses += 1; } @@ -1205,15 +1177,6 @@ build_element_name_1 (struct sra_elt *elt) sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (t)); obstack_grow (&sra_obstack, buffer, strlen (buffer)); } - else if (TREE_CODE (t) == BIT_FIELD_REF) - { - sprintf (buffer, "B" HOST_WIDE_INT_PRINT_DEC, - tree_low_cst (TREE_OPERAND (t, 2), 1)); - obstack_grow (&sra_obstack, buffer, strlen (buffer)); - sprintf (buffer, "F" HOST_WIDE_INT_PRINT_DEC, - tree_low_cst (TREE_OPERAND (t, 1), 1)); - obstack_grow (&sra_obstack, buffer, strlen (buffer)); - } else { tree name = DECL_NAME (t); @@ -1246,12 +1209,9 @@ instantiate_element (struct sra_elt *elt) { struct sra_elt *base_elt; tree var, base; - bool nowarn = TREE_NO_WARNING (elt->element); for (base_elt = elt; base_elt->parent; base_elt = base_elt->parent) - if (!nowarn) - nowarn = base_elt->parent->n_uses - || TREE_NO_WARNING (base_elt->parent->element); + continue; base = base_elt->element; elt->replacement = var = make_rename_temp (elt->type, "SR"); @@ -1280,7 +1240,9 @@ instantiate_element (struct sra_elt *elt) DECL_DEBUG_EXPR_IS_FROM (var) = 1; DECL_IGNORED_P (var) = 0; - TREE_NO_WARNING (var) = nowarn; + TREE_NO_WARNING (var) = TREE_NO_WARNING (base); + if (elt->element && TREE_NO_WARNING (elt->element)) + TREE_NO_WARNING (var) = 1; } else { @@ -1375,7 +1337,7 @@ sum_instantiated_sizes (struct sra_elt *elt, unsigned HOST_WIDE_INT *sizep) static void instantiate_missing_elements (struct sra_elt *elt); -static struct sra_elt * +static void instantiate_missing_elements_1 (struct sra_elt *elt, tree child, tree type) { struct sra_elt *sub = lookup_element (elt, child, type, INSERT); @@ -1386,266 +1348,6 @@ instantiate_missing_elements_1 (struct sra_elt *elt, tree child, tree type) } else instantiate_missing_elements (sub); - return sub; -} - -/* Obtain the canonical type for field F of ELEMENT. */ - -static tree -canon_type_for_field (tree f, tree element) -{ - tree field_type = TREE_TYPE (f); - - /* canonicalize_component_ref() unwidens some bit-field types (not - marked as DECL_BIT_FIELD in C++), so we must do the same, lest we - may introduce type mismatches. */ - if (INTEGRAL_TYPE_P (field_type) - && DECL_MODE (f) != TYPE_MODE (field_type)) - field_type = TREE_TYPE (get_unwidened (build3 (COMPONENT_REF, - field_type, - element, - f, NULL_TREE), - NULL_TREE)); - - return field_type; -} - -/* Look for adjacent fields of ELT starting at F that we'd like to - scalarize as a single variable. Return the last field of the - group. */ - -static tree -try_instantiate_multiple_fields (struct sra_elt *elt, tree f) -{ - unsigned HOST_WIDE_INT align, oalign, word, bit, size, alchk; - enum machine_mode mode; - tree first = f, prev; - tree type, var; - struct sra_elt *block; - - if (!is_sra_scalar_type (TREE_TYPE (f)) - || !host_integerp (DECL_FIELD_OFFSET (f), 1) - || !host_integerp (DECL_FIELD_BIT_OFFSET (f), 1) - || !host_integerp (DECL_SIZE (f), 1) - || lookup_element (elt, f, NULL, NO_INSERT)) - return f; - - /* Taking the alignment of elt->element is not enough, since it - might be just an array index or some such. We shouldn't need to - initialize align here, but our optimizers don't always realize - that, if we leave the loop without initializing align, we'll fail - the assertion right after the loop. */ - align = (unsigned HOST_WIDE_INT)-1; - for (block = elt; block; block = block->parent) - if (DECL_P (block->element)) - { - align = DECL_ALIGN (block->element); - break; - } - gcc_assert (block); - - oalign = DECL_OFFSET_ALIGN (f); - word = tree_low_cst (DECL_FIELD_OFFSET (f), 1); - bit = tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1); - size = tree_low_cst (DECL_SIZE (f), 1); - - if (align > oalign) - align = oalign; - - alchk = align - 1; - alchk = ~alchk; - - if ((bit & alchk) != ((bit + size - 1) & alchk)) - return f; - - /* Find adjacent fields in the same alignment word. */ - - for (prev = f, f = TREE_CHAIN (f); - f && TREE_CODE (f) == FIELD_DECL - && is_sra_scalar_type (TREE_TYPE (f)) - && host_integerp (DECL_FIELD_OFFSET (f), 1) - && host_integerp (DECL_FIELD_BIT_OFFSET (f), 1) - && host_integerp (DECL_SIZE (f), 1) - && (HOST_WIDE_INT)word == tree_low_cst (DECL_FIELD_OFFSET (f), 1) - && !lookup_element (elt, f, NULL, NO_INSERT); - prev = f, f = TREE_CHAIN (f)) - { - unsigned HOST_WIDE_INT nbit, nsize; - - nbit = tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1); - nsize = tree_low_cst (DECL_SIZE (f), 1); - - if (bit + size == nbit) - { - if ((bit & alchk) != ((nbit + nsize - 1) & alchk)) - break; - size += nsize; - } - else if (nbit + nsize == bit) - { - if ((nbit & alchk) != ((bit + size - 1) & alchk)) - break; - bit = nbit; - size += nsize; - } - else - break; - } - - f = prev; - - if (f == first) - return f; - - gcc_assert ((bit & alchk) == ((bit + size - 1) & alchk)); - - /* Try to widen the bit range so as to cover padding bits as well. */ - - if ((bit & ~alchk) || size != align) - { - unsigned HOST_WIDE_INT mbit = bit & alchk; - unsigned HOST_WIDE_INT msize = align; - - for (f = TYPE_FIELDS (elt->type); - f; f = TREE_CHAIN (f)) - { - unsigned HOST_WIDE_INT fword, fbit, fsize; - - /* Skip the fields from first to prev. */ - if (f == first) - { - f = prev; - continue; - } - - if (!(TREE_CODE (f) == FIELD_DECL - && host_integerp (DECL_FIELD_OFFSET (f), 1) - && host_integerp (DECL_FIELD_BIT_OFFSET (f), 1))) - continue; - - fword = tree_low_cst (DECL_FIELD_OFFSET (f), 1); - /* If we're past the selected word, we're fine. */ - if (word < fword) - continue; - - fbit = tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1); - - if (host_integerp (DECL_SIZE (f), 1)) - fsize = tree_low_cst (DECL_SIZE (f), 1); - else - /* Assume a variable-sized field takes up all space till - the end of the word. ??? Endianness issues? */ - fsize = align - fbit; - - if (fword < word) - { - /* A large field might start at a previous word and - extend into the selected word. Exclude those - bits. ??? Endianness issues? */ - HOST_WIDE_INT diff = fbit + fsize - - (HOST_WIDE_INT)((word - fword) * BITS_PER_UNIT + mbit); - - if (diff <= 0) - continue; - - mbit += diff; - msize -= diff; - } - else - { - gcc_assert (fword == word); - - /* Non-overlapping, great. */ - if (fbit + fsize <= mbit - || mbit + msize <= fbit) - continue; - - if (fbit <= mbit) - { - unsigned HOST_WIDE_INT diff = fbit + fsize - mbit; - mbit += diff; - msize -= diff; - } - else if (fbit > mbit) - msize -= (mbit + msize - fbit); - else - gcc_unreachable (); - } - } - - bit = mbit; - size = msize; - } - - /* Now we know the bit range we're interested in. Find the smallest - machine mode we can use to access it. */ - - for (mode = smallest_mode_for_size (size, MODE_INT); - ; - mode = GET_MODE_WIDER_MODE (mode)) - { - gcc_assert (mode != VOIDmode); - - alchk = GET_MODE_PRECISION (mode) - 1; - alchk = ~alchk; - - if ((bit & alchk) == ((bit + size - 1) & alchk)) - break; - } - - gcc_assert (~alchk < align); - - /* Create the field group as a single variable. */ - - type = lang_hooks.types.type_for_mode (mode, 1); - gcc_assert (type); - var = build3 (BIT_FIELD_REF, type, NULL_TREE, - bitsize_int (size), - bitsize_int (word * BITS_PER_UNIT + bit)); - BIT_FIELD_REF_UNSIGNED (var) = 1; - - block = instantiate_missing_elements_1 (elt, var, type); - gcc_assert (block && block->is_scalar); - - var = block->replacement; - - if (((word * BITS_PER_UNIT + bit) & ~alchk) - || (HOST_WIDE_INT)size != tree_low_cst (DECL_SIZE (var), 1)) - { - block->replacement = build3 (BIT_FIELD_REF, - TREE_TYPE (block->element), var, - bitsize_int (size), - bitsize_int ((word * BITS_PER_UNIT - + bit) & ~alchk)); - BIT_FIELD_REF_UNSIGNED (block->replacement) = 1; - TREE_NO_WARNING (block->replacement) = 1; - } - - block->in_bitfld_block = 2; - - /* Add the member fields to the group, such that they access - portions of the group variable. */ - - for (f = first; f != TREE_CHAIN (prev); f = TREE_CHAIN (f)) - { - tree field_type = canon_type_for_field (f, elt->element); - struct sra_elt *fld = lookup_element (block, f, field_type, INSERT); - - gcc_assert (fld && fld->is_scalar && !fld->replacement); - - fld->replacement = build3 (BIT_FIELD_REF, field_type, var, - DECL_SIZE (f), - bitsize_int - ((word * BITS_PER_UNIT - + (TREE_INT_CST_LOW - (DECL_FIELD_BIT_OFFSET (f)))) - & ~alchk)); - BIT_FIELD_REF_UNSIGNED (fld->replacement) = TYPE_UNSIGNED (field_type); - TREE_NO_WARNING (block->replacement) = 1; - fld->in_bitfld_block = 1; - } - - return prev; } static void @@ -1661,17 +1363,21 @@ instantiate_missing_elements (struct sra_elt *elt) for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f)) if (TREE_CODE (f) == FIELD_DECL) { - tree last = try_instantiate_multiple_fields (elt, f); - - if (last != f) - { - f = last; - continue; - } - - instantiate_missing_elements_1 (elt, f, - canon_type_for_field - (f, elt->element)); + tree field_type = TREE_TYPE (f); + + /* canonicalize_component_ref() unwidens some bit-field + types (not marked as DECL_BIT_FIELD in C++), so we + must do the same, lest we may introduce type + mismatches. */ + if (INTEGRAL_TYPE_P (field_type) + && DECL_MODE (f) != TYPE_MODE (field_type)) + field_type = TREE_TYPE (get_unwidened (build3 (COMPONENT_REF, + field_type, + elt->element, + f, NULL_TREE), + NULL_TREE)); + + instantiate_missing_elements_1 (elt, f, field_type); } break; } @@ -1983,16 +1689,6 @@ generate_one_element_ref (struct sra_elt *elt, tree base) { tree field = elt->element; - /* We can't test elt->in_bitfld_blk here because, when this is - called from instantiate_element, we haven't set this field - yet. */ - if (TREE_CODE (field) == BIT_FIELD_REF) - { - tree ret = copy_node (field); - TREE_OPERAND (ret, 0) = base; - return ret; - } - /* Watch out for compatible records with differing field lists. */ if (DECL_FIELD_CONTEXT (field) != TYPE_MAIN_VARIANT (TREE_TYPE (base))) field = find_compatible_field (TREE_TYPE (base), field); @@ -2045,126 +1741,6 @@ sra_build_assignment (tree dst, tree src) return build_gimple_modify_stmt (dst, src); } -/* BIT_FIELD_REFs must not be shared. sra_build_elt_assignment() - takes care of assignments, but we must create copies for uses. */ -#define REPLDUP(t) (TREE_CODE (t) != BIT_FIELD_REF ? (t) : copy_node (t)) - -static tree -sra_build_elt_assignment (struct sra_elt *elt, tree src) -{ - tree dst = elt->replacement; - tree var, type, tmp, tmp2, tmp3; - tree list, stmt; - tree cst, cst2, mask; - tree minshift = NULL, maxshift = NULL; - - if (TREE_CODE (dst) != BIT_FIELD_REF - || !elt->in_bitfld_block) - return sra_build_assignment (REPLDUP (dst), src); - - var = TREE_OPERAND (dst, 0); - - /* Try to widen the assignment to the entire variable. - We need the source to be a BIT_FIELD_REF as well, such that, for - BIT_FIELD_REF = BIT_FIELD_REF, - if sp >= dp, we can turn it into - d = BIT_FIELD_REF. */ - if (elt->in_bitfld_block == 2 - && TREE_CODE (src) == BIT_FIELD_REF - && !tree_int_cst_lt (TREE_OPERAND (src, 2), TREE_OPERAND (dst, 2))) - { - src = fold_build3 (BIT_FIELD_REF, TREE_TYPE (var), - TREE_OPERAND (src, 0), - size_binop (PLUS_EXPR, TREE_OPERAND (src, 1), - TREE_OPERAND (dst, 2)), - size_binop (MINUS_EXPR, TREE_OPERAND (src, 2), - TREE_OPERAND (dst, 2))); - BIT_FIELD_REF_UNSIGNED (src) = 1; - - return sra_build_assignment (var, src); - } - - if (!is_gimple_reg (var)) - return sra_build_assignment (REPLDUP (dst), src); - - list = alloc_stmt_list (); - - cst = TREE_OPERAND (dst, 2); - if (WORDS_BIG_ENDIAN) - { - cst = size_binop (MINUS_EXPR, DECL_SIZE (var), cst); - maxshift = cst; - } - else - minshift = cst; - - cst2 = size_binop (PLUS_EXPR, TREE_OPERAND (dst, 1), - TREE_OPERAND (dst, 2)); - if (WORDS_BIG_ENDIAN) - { - cst2 = size_binop (MINUS_EXPR, DECL_SIZE (var), cst2); - minshift = cst2; - } - else - maxshift = cst2; - - type = TREE_TYPE (var); - - mask = build_int_cst_wide (type, 1, 0); - cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, 1); - cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, 1); - mask = int_const_binop (MINUS_EXPR, cst, cst2, 1); - mask = fold_build1 (BIT_NOT_EXPR, type, mask); - - if (!WORDS_BIG_ENDIAN) - cst2 = TREE_OPERAND (dst, 2); - - tmp = make_rename_temp (type, "SR"); - stmt = build_gimple_modify_stmt (tmp, - fold_build2 (BIT_AND_EXPR, type, - var, mask)); - append_to_statement_list (stmt, &list); - - if (is_gimple_reg (src)) - tmp2 = src; - else - { - tmp2 = make_rename_temp (TREE_TYPE (src), "SR"); - stmt = sra_build_assignment (tmp2, src); - append_to_statement_list (stmt, &list); - } - - if (!TYPE_UNSIGNED (TREE_TYPE (tmp2)) - || TYPE_MAIN_VARIANT (TREE_TYPE (tmp2)) != TYPE_MAIN_VARIANT (type)) - { - tmp3 = make_rename_temp (type, "SR"); - tmp2 = fold_build3 (BIT_FIELD_REF, type, tmp2, TREE_OPERAND (dst, 1), - bitsize_int (0)); - if (TREE_CODE (tmp2) == BIT_FIELD_REF) - BIT_FIELD_REF_UNSIGNED (tmp2) = 1; - stmt = sra_build_assignment (tmp3, tmp2); - append_to_statement_list (stmt, &list); - tmp2 = tmp3; - } - - if (!integer_zerop (minshift)) - { - tmp3 = make_rename_temp (type, "SR"); - stmt = build_gimple_modify_stmt (tmp3, - fold_build2 (LSHIFT_EXPR, type, - tmp2, minshift)); - append_to_statement_list (stmt, &list); - tmp2 = tmp3; - } - - stmt = build_gimple_modify_stmt (var, - fold_build2 (BIT_IOR_EXPR, type, - tmp, tmp2)); - append_to_statement_list (stmt, &list); - - return list; -} - /* Generate a set of assignment statements in *LIST_P to copy all instantiated elements under ELT to or from the equivalent structure rooted at EXPR. COPY_OUT controls the direction of the copy, with @@ -2195,9 +1771,9 @@ generate_copy_inout (struct sra_elt *elt, bool copy_out, tree expr, else if (elt->replacement) { if (copy_out) - t = sra_build_elt_assignment (elt, expr); + t = sra_build_assignment (elt->replacement, expr); else - t = sra_build_assignment (expr, REPLDUP (elt->replacement)); + t = sra_build_assignment (expr, elt->replacement); append_to_statement_list (t, list_p); } else @@ -2222,19 +1798,6 @@ generate_element_copy (struct sra_elt *dst, struct sra_elt *src, tree *list_p) FOR_EACH_ACTUAL_CHILD (dc, dst) { sc = lookup_element (src, dc->element, NULL, NO_INSERT); - if (!sc && dc->in_bitfld_block == 2) - { - struct sra_elt *dcs; - - FOR_EACH_ACTUAL_CHILD (dcs, dc) - { - sc = lookup_element (src, dcs->element, NULL, NO_INSERT); - gcc_assert (sc); - generate_element_copy (dcs, sc, list_p); - } - - continue; - } gcc_assert (sc); generate_element_copy (dc, sc, list_p); } @@ -2245,7 +1808,7 @@ generate_element_copy (struct sra_elt *dst, struct sra_elt *src, tree *list_p) gcc_assert (src->replacement); - t = sra_build_elt_assignment (dst, REPLDUP (src->replacement)); + t = sra_build_assignment (dst->replacement, src->replacement); append_to_statement_list (t, list_p); } } @@ -2266,9 +1829,8 @@ generate_element_zero (struct sra_elt *elt, tree *list_p) return; } - if (!elt->in_bitfld_block) - FOR_EACH_ACTUAL_CHILD (c, elt) - generate_element_zero (c, list_p); + FOR_EACH_ACTUAL_CHILD (c, elt) + generate_element_zero (c, list_p); if (elt->replacement) { @@ -2277,7 +1839,7 @@ generate_element_zero (struct sra_elt *elt, tree *list_p) gcc_assert (elt->is_scalar); t = fold_convert (elt->type, integer_zero_node); - t = sra_build_elt_assignment (elt, t); + t = sra_build_assignment (elt->replacement, t); append_to_statement_list (t, list_p); } } @@ -2286,10 +1848,10 @@ generate_element_zero (struct sra_elt *elt, tree *list_p) Add the result to *LIST_P. */ static void -generate_one_element_init (struct sra_elt *elt, tree init, tree *list_p) +generate_one_element_init (tree var, tree init, tree *list_p) { /* The replacement can be almost arbitrarily complex. Gimplify. */ - tree stmt = sra_build_elt_assignment (elt, init); + tree stmt = sra_build_assignment (var, init); gimplify_and_add (stmt, list_p); } @@ -2318,7 +1880,7 @@ generate_element_init_1 (struct sra_elt *elt, tree init, tree *list_p) { if (elt->replacement) { - generate_one_element_init (elt, init, list_p); + generate_one_element_init (elt->replacement, init, list_p); elt->visited = true; } return result; @@ -2477,7 +2039,7 @@ sra_replace (block_stmt_iterator *bsi, tree list) static void scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi, - bool is_output) + bool is_output, bool use_all) { tree list = NULL, stmt = bsi_stmt (*bsi); @@ -2486,27 +2048,8 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi, /* If we have a replacement, then updating the reference is as simple as modifying the existing statement in place. */ if (is_output) - { - if (TREE_CODE (elt->replacement) == BIT_FIELD_REF - && is_gimple_reg (TREE_OPERAND (elt->replacement, 0)) - && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT - && &GIMPLE_STMT_OPERAND (stmt, 0) == expr_p) - { - tree newstmt = sra_build_elt_assignment - (elt, GIMPLE_STMT_OPERAND (stmt, 1)); - if (TREE_CODE (newstmt) != STATEMENT_LIST) - { - tree list = alloc_stmt_list (); - append_to_statement_list (newstmt, &list); - newstmt = list; - } - sra_replace (bsi, newstmt); - return; - } - - mark_all_v_defs (stmt); - } - *expr_p = REPLDUP (elt->replacement); + mark_all_v_defs (stmt); + *expr_p = elt->replacement; update_stmt (stmt); } else @@ -2524,23 +2067,17 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi, This optimization would be most effective if sra_walk_function processed the blocks in dominator order. */ - generate_copy_inout (elt, false, generate_element_ref (elt), &list); - if (list) - { - mark_all_v_defs (list); - sra_insert_before (bsi, list); - mark_no_warning (elt); - } - + generate_copy_inout (elt, is_output, generate_element_ref (elt), &list); + if (list == NULL) + return; + mark_all_v_defs (list); if (is_output) + sra_insert_after (bsi, list); + else { - list = NULL; - generate_copy_inout (elt, true, generate_element_ref (elt), &list); - if (list) - { - mark_all_v_defs (list); - sra_insert_after (bsi, list); - } + sra_insert_before (bsi, list); + if (use_all) + mark_no_warning (elt); } } } @@ -2564,7 +2101,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt, gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT); GIMPLE_STMT_OPERAND (stmt, 0) = lhs_elt->replacement; - GIMPLE_STMT_OPERAND (stmt, 1) = REPLDUP (rhs_elt->replacement); + GIMPLE_STMT_OPERAND (stmt, 1) = rhs_elt->replacement; update_stmt (stmt); } else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy) @@ -2706,7 +2243,7 @@ scalarize_ldst (struct sra_elt *elt, tree other, { /* Since ELT is not fully instantiated, we have to leave the block copy in place. Treat this as a USE. */ - scalarize_use (elt, NULL, bsi, is_output); + scalarize_use (elt, NULL, bsi, is_output, false); } else { @@ -2718,8 +2255,8 @@ scalarize_ldst (struct sra_elt *elt, tree other, mark_all_v_defs (stmt); generate_copy_inout (elt, is_output, other, &list); - gcc_assert (list); mark_all_v_defs (list); + gcc_assert (list); /* Preserve EH semantics. */ if (stmt_ends_bb_p (stmt)) @@ -2815,10 +2352,6 @@ dump_sra_elt_name (FILE *f, struct sra_elt *elt) fputc ('.', f); print_generic_expr (f, elt->element, dump_flags); } - else if (TREE_CODE (elt->element) == BIT_FIELD_REF) - fprintf (f, "$B" HOST_WIDE_INT_PRINT_DEC "F" HOST_WIDE_INT_PRINT_DEC, - tree_low_cst (TREE_OPERAND (elt->element, 2), 1), - tree_low_cst (TREE_OPERAND (elt->element, 1), 1)); else if (TREE_CODE (elt->element) == RANGE_EXPR) fprintf (f, "["HOST_WIDE_INT_PRINT_DEC".."HOST_WIDE_INT_PRINT_DEC"]", TREE_INT_CST_LOW (TREE_OPERAND (elt->element, 0)), -- 2.11.0