From e3694d1dc050cd9d8d66ac56810a66abc138d4b7 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Thu, 8 Dec 2011 09:05:38 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182102 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 +++ gcc/builtins.c | 25 +++++++ gcc/expr.c | 21 ------ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.c-torture/execute/20111208-1.c | 94 ++++++++++++++++++++++++ gcc/tree-sra.c | 36 +++++---- gcc/tree.h | 1 + 7 files changed, 158 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20111208-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 325c1e0..1f26fa9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2011-12-08 Eric Botcazou + + 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 PR lto/48437 diff --git a/gcc/builtins.c b/gcc/builtins.c index 019da15..b007498 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 524ddab..b2166bd 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 ededf04..898478b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-12-08 Eric Botcazou + + * gcc.c-torture/execute/20111208-1.c: New test. + 2011-12-08 Richard Guenther 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 0000000..8bcb10a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20111208-1.c @@ -0,0 +1,94 @@ +/* PR tree-optimization/51315 */ +/* Reported by Jurij Smakov */ + +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 dec5316..346519a 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 4544f1a..a72a3f6 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); -- 2.7.4