summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/builtins.c25
-rw-r--r--gcc/expr.c21
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20111208-1.c94
-rw-r--r--gcc/tree-sra.c36
-rw-r--r--gcc/tree.h1
7 files changed, 158 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 325c1e0763e..1f26fa946c4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 019da159dd4..b00749848a6 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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.
diff --git a/gcc/expr.c b/gcc/expr.c
index 524ddab1f9e..b2166bdac81 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ededf0425f6..898478b87a2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..8bcb10accb5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20111208-1.c
@@ -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;
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index dec5316468c..346519a6af5 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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;
diff --git a/gcc/tree.h b/gcc/tree.h
index 4544f1ad126..a72a3f613e4 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);