diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20111212-1.c | 34 | ||||
-rw-r--r-- | gcc/tree-sra.c | 66 |
4 files changed, 94 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d429ea5..0d1dea3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,7 +1,12 @@ +2011-12-12 Eric Botcazou <ebotcazou@adacore.com> + + PR tree-optimization/50569 + * tree-sra.c (build_ref_for_model): Replicate a chain of COMPONENT_REFs + in the expression of MODEL instead of just the last one. + 2011-12-12 Dmitry Vyukov <dvyukov@google.com> - * cgraphunit.c (init_lowered_empty_function): - Fix flags for new edges. + * cgraphunit.c (init_lowered_empty_function): Fix flags for new edges. 2011-12-12 Jakub Jelinek <jakub@redhat.com> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c74c878..dbe8ac6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-12-12 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20111212-1.c: New test. + 2011-12-12 Jakub Jelinek <jakub@redhat.com> PR testsuite/51511 diff --git a/gcc/testsuite/gcc.c-torture/execute/20111212-1.c b/gcc/testsuite/gcc.c-torture/execute/20111212-1.c new file mode 100644 index 0000000..c46e6e9 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20111212-1.c @@ -0,0 +1,34 @@ +/* PR tree-optimization/50569 */ +/* Reported by Paul Koning <pkoning@gcc.gnu.org> */ +/* Reduced testcase by Mikael Pettersson <mikpe@it.uu.se> */ + +struct event { + struct { + unsigned int sec; + } sent __attribute__((packed)); +}; + +void __attribute__((noinline,noclone)) frob_entry(char *buf) +{ + struct event event; + + __builtin_memcpy(&event, buf, sizeof(event)); + if (event.sent.sec < 64) { + event.sent.sec = -1U; + __builtin_memcpy(buf, &event, sizeof(event)); + } +} + +int main(void) +{ + union { + char buf[1 + sizeof(struct event)]; + int align; + } u; + + __builtin_memset(&u, 0, sizeof u); + + frob_entry(&u.buf[1]); + + return 0; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 346519a..b921c76 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1492,33 +1492,65 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset, return fold_build2_loc (loc, MEM_REF, exp_type, base, off); } +DEF_VEC_ALLOC_P_STACK (tree); +#define VEC_tree_stack_alloc(alloc) VEC_stack_alloc (tree, alloc) + /* Construct a memory reference to a part of an aggregate BASE at the given - OFFSET and of the same type as MODEL. In case this is a reference to a - component, the function will replicate the last COMPONENT_REF of model's - expr to access it. GSI and INSERT_AFTER have the same meaning as in - build_ref_for_offset. */ + OFFSET and of the type of MODEL. In case this is a chain of references + to component, the function will replicate the chain of COMPONENT_REFs of + the expression of MODEL to access it. GSI and INSERT_AFTER have the same + meaning as in build_ref_for_offset. */ static tree build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset, struct access *model, gimple_stmt_iterator *gsi, bool insert_after) { + tree type = model->type, t; + VEC(tree,stack) *cr_stack = NULL; + if (TREE_CODE (model->expr) == COMPONENT_REF) { - tree t, exp_type, fld = TREE_OPERAND (model->expr, 1); - tree cr_offset = component_ref_field_offset (model->expr); - - gcc_assert (cr_offset && host_integerp (cr_offset, 1)); - offset -= TREE_INT_CST_LOW (cr_offset) * BITS_PER_UNIT; - offset -= TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld)); - exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0)); - t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after); - return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld, - TREE_OPERAND (model->expr, 2)); + tree expr = model->expr; + + /* Create a stack of the COMPONENT_REFs so later we can walk them in + order from inner to outer. */ + cr_stack = VEC_alloc (tree, stack, 6); + + do { + tree field = TREE_OPERAND (expr, 1); + tree cr_offset = component_ref_field_offset (expr); + gcc_assert (cr_offset && host_integerp (cr_offset, 1)); + + offset -= TREE_INT_CST_LOW (cr_offset) * BITS_PER_UNIT; + offset -= TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); + + VEC_safe_push (tree, stack, cr_stack, expr); + + expr = TREE_OPERAND (expr, 0); + type = TREE_TYPE (expr); + } while (TREE_CODE (expr) == COMPONENT_REF); } - else - return build_ref_for_offset (loc, base, offset, model->type, - gsi, insert_after); + + t = build_ref_for_offset (loc, base, offset, type, gsi, insert_after); + + if (TREE_CODE (model->expr) == COMPONENT_REF) + { + unsigned i; + tree expr; + + /* Now replicate the chain of COMPONENT_REFs from inner to outer. */ + FOR_EACH_VEC_ELT_REVERSE (tree, cr_stack, i, expr) + { + tree field = TREE_OPERAND (expr, 1); + t = fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (field), t, field, + TREE_OPERAND (expr, 2)); + } + + VEC_free (tree, stack, cr_stack); + } + + return t; } /* Construct a memory reference consisting of component_refs and array_refs to |