OSDN Git Service

PR tree-optimization/51315
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Dec 2011 09:05:38 +0000 (09:05 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 8 Dec 2011 09:05:38 +0000 (09:05 +0000)
* tree.h (get_object_or_type_alignment): Declare.
* expr.c (get_object_or_type_alignment): Move to...
* builtins.c (get_object_or_type_alignment): ...here.  Add assertion.
* tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
(tree_non_aligned_mem_p): ...this.  Add ALIGN parameter.  Look into
MEM_REFs and use get_object_or_type_alignment for them.
(build_accesses_from_assign): Adjust for above change.
(access_precludes_ipa_sra_p): Likewise.

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

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

index 325c1e0..1f26fa9 100644 (file)
@@ -1,3 +1,15 @@
+2011-12-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR tree-optimization/51315
+       * tree.h (get_object_or_type_alignment): Declare.
+       * expr.c (get_object_or_type_alignment): Move to...
+       * builtins.c (get_object_or_type_alignment): ...here.  Add assertion.
+       * tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
+       (tree_non_aligned_mem_p): ...this.  Add ALIGN parameter.  Look into
+       MEM_REFs and use get_object_or_type_alignment for them.
+       (build_accesses_from_assign): Adjust for above change.
+       (access_precludes_ipa_sra_p): Likewise.
+
 2011-12-08  Richard Guenther  <rguenther@suse.de>
 
        PR lto/48437
index 019da15..b007498 100644 (file)
@@ -452,6 +452,31 @@ get_object_alignment (tree exp)
   return align;
 }
 
+/* Return the alignment of object EXP, also considering its type when we do
+   not know of explicit misalignment.  Only handle MEM_REF and TARGET_MEM_REF.
+
+   ??? Note that, in the general case, the type of an expression is not kept
+   consistent with misalignment information by the front-end, for example when
+   taking the address of a member of a packed structure.  However, in most of
+   the cases, expressions have the alignment of their type so we optimistically
+   fall back to this alignment when we cannot compute a misalignment.  */
+
+unsigned int
+get_object_or_type_alignment (tree exp)
+{
+  unsigned HOST_WIDE_INT misalign;
+  unsigned int align = get_object_alignment_1 (exp, &misalign);
+
+  gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
+
+  if (misalign != 0)
+    align = (misalign & -misalign);
+  else
+    align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+
+  return align;
+}
+
 /* Return the alignment in bits of EXP, a pointer valued expression.
    The alignment returned is, by default, the alignment of the thing that
    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
index 524ddab..b2166bd 100644 (file)
@@ -4544,27 +4544,6 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
     }
 }
 
-/* Return the alignment of the object EXP, also considering its type
-   when we do not know of explicit misalignment.
-   ???  Note that, in the general case, the type of an expression is not kept
-   consistent with misalignment information by the front-end, for
-   example when taking the address of a member of a packed structure.
-   However, in most of the cases, expressions have the alignment of
-   their type, so we optimistically fall back to the alignment of the
-   type when we cannot compute a misalignment.  */
-
-static unsigned int
-get_object_or_type_alignment (tree exp)
-{
-  unsigned HOST_WIDE_INT misalign;
-  unsigned int align = get_object_alignment_1 (exp, &misalign);
-  if (misalign != 0)
-    align = (misalign & -misalign);
-  else
-    align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
-  return align;
-}
-
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
    is true, try generating a nontemporal store.  */
 
index ededf04..898478b 100644 (file)
@@ -1,3 +1,7 @@
+2011-12-08  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20111208-1.c: New test.
+
 2011-12-08  Richard Guenther  <rguenther@suse.de>
 
        PR lto/48437
diff --git a/gcc/testsuite/gcc.c-torture/execute/20111208-1.c b/gcc/testsuite/gcc.c-torture/execute/20111208-1.c
new file mode 100644 (file)
index 0000000..8bcb10a
--- /dev/null
@@ -0,0 +1,94 @@
+/* PR tree-optimization/51315 */
+/* Reported by Jurij Smakov <jurij@wooyd.org> */
+
+typedef unsigned int size_t;
+
+extern void *memcpy (void *__restrict __dest,
+       __const void *__restrict __src, size_t __n)
+     __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2)));
+
+extern size_t strlen (__const char *__s)
+     __attribute__ ((__nothrow__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
+
+typedef short int int16_t;
+typedef int int32_t;
+
+extern void abort (void);
+
+int a;
+
+static void __attribute__ ((noinline,noclone))
+do_something (int item)
+{
+  a = item;
+}
+
+int
+pack_unpack (char *s, char *p)
+{
+  char *send, *pend;
+  char type;
+  int integer_size;
+
+  send = s + strlen (s);
+  pend = p + strlen (p);
+
+  while (p < pend)
+    {
+      type = *p++;
+
+      switch (type)
+ {
+ case 's':
+   integer_size = 2;
+   goto unpack_integer;
+
+ case 'l':
+   integer_size = 4;
+   goto unpack_integer;
+
+ unpack_integer:
+   switch (integer_size)
+     {
+     case 2:
+       {
+  union
+  {
+    int16_t i;
+    char a[sizeof (int16_t)];
+  }
+  v;
+  memcpy (v.a, s, sizeof (int16_t));
+  s += sizeof (int16_t);
+  do_something (v.i);
+       }
+       break;
+
+     case 4:
+       {
+  union
+  {
+    int32_t i;
+    char a[sizeof (int32_t)];
+  }
+  v;
+  memcpy (v.a, s, sizeof (int32_t));
+  s += sizeof (int32_t);
+  do_something (v.i);
+       }
+       break;
+     }
+   break;
+ }
+    }
+  return (int) *s;
+}
+
+int
+main (void)
+{
+  int n = pack_unpack ("\200\001\377\376\035\300", "sl");
+  if (n != 0)
+    abort ();
+  return 0;
+}
index dec5316..346519a 100644 (file)
@@ -1067,26 +1067,29 @@ disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
   return false;
 }
 
-/* Return true iff type of EXP is not sufficiently aligned.  */
+/* Return true if EXP is a memory reference less aligned than ALIGN.  This is
+   invoked only on strict-alignment targets.  */
 
 static bool
-tree_non_mode_aligned_mem_p (tree exp)
+tree_non_aligned_mem_p (tree exp, unsigned int align)
 {
-  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-  unsigned int align;
+  unsigned int exp_align;
 
   if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     exp = TREE_OPERAND (exp, 0);
 
-  if (TREE_CODE (exp) == SSA_NAME
-      || TREE_CODE (exp) == MEM_REF
-      || mode == BLKmode
-      || is_gimple_min_invariant (exp)
-      || !STRICT_ALIGNMENT)
+  if (TREE_CODE (exp) == SSA_NAME || is_gimple_min_invariant (exp))
     return false;
 
-  align = get_object_alignment (exp);
-  if (GET_MODE_ALIGNMENT (mode) > align)
+  /* get_object_alignment will fall back to BITS_PER_UNIT if it cannot
+     compute an explicit alignment.  Pretend that dereferenced pointers
+     are always aligned on strict-alignment targets.  */
+  if (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF)
+    exp_align = get_object_or_type_alignment (exp);
+  else
+    exp_align = get_object_alignment (exp);
+
+  if (exp_align < align)
     return true;
 
   return false;
@@ -1120,7 +1123,9 @@ build_accesses_from_assign (gimple stmt)
   if (lacc)
     {
       lacc->grp_assignment_write = 1;
-      lacc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (rhs);
+      if (STRICT_ALIGNMENT
+         && tree_non_aligned_mem_p (rhs, get_object_alignment (lhs)))
+        lacc->grp_unscalarizable_region = 1;
     }
 
   if (racc)
@@ -1129,7 +1134,9 @@ 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));
-      racc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (lhs);
+      if (STRICT_ALIGNMENT
+         && tree_non_aligned_mem_p (lhs, get_object_alignment (rhs)))
+        racc->grp_unscalarizable_region = 1;
     }
 
   if (lacc && racc
@@ -3705,7 +3712,8 @@ access_precludes_ipa_sra_p (struct access *access)
          || gimple_code (access->stmt) == GIMPLE_ASM))
     return true;
 
-  if (tree_non_mode_aligned_mem_p (access->expr))
+  if (STRICT_ALIGNMENT
+      && tree_non_aligned_mem_p (access->expr, TYPE_ALIGN (access->type)))
     return true;
 
   return false;
index 4544f1a..a72a3f6 100644 (file)
@@ -5457,6 +5457,7 @@ extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 extern bool is_builtin_fn (tree);
 extern unsigned int get_object_alignment_1 (tree, unsigned HOST_WIDE_INT *);
 extern unsigned int get_object_alignment (tree);
+extern unsigned int get_object_or_type_alignment (tree);
 extern unsigned int get_pointer_alignment (tree);
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);