OSDN Git Service

PR tree-optimization/50569
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Dec 2011 18:22:13 +0000 (18:22 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Dec 2011 18:22:13 +0000 (18:22 +0000)
* tree-sra.c (build_ref_for_model): Replicate a chain of COMPONENT_REFs
in the expression of MODEL instead of just the last one.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182252 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20111212-1.c [new file with mode: 0644]
gcc/tree-sra.c

index d429ea5..0d1dea3 100644 (file)
@@ -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>
 
 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>
 
 
 2011-12-12  Jakub Jelinek  <jakub@redhat.com>
 
index c74c878..dbe8ac6 100644 (file)
@@ -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
 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 (file)
index 0000000..c46e6e9
--- /dev/null
@@ -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;
+}
index 346519a..b921c76 100644 (file)
@@ -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);
 }
 
   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
 /* 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)
 {
 
 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)
     {
   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
 }
 
 /* Construct a memory reference consisting of component_refs and array_refs to