Hi, On Thu, Dec 06, 2012 at 10:35:04AM +0100, Richard Guenther wrote: > Don't you want to use get_object_alignment_1 to record whether > 'base' is for example at offset 3 of a 16-byte aligned object > so that if 'offset' then makes the result aligned you use > that alignment instead of the conservative 1-byte alignment > you'd otherwise get from get_object_alignment? > > That is, how do 'offset' and 'base' relate? As far as I understand > align should be computed as the alignment of the access to > 'base' plus offset 'offset', no?
You're right, such situation can occur too, even though probably only rarely. Below is a patch that uses get_object_alignment_1, it has passed bootstrap and testing on x86_64-linux, and powerpc64-linux, the same on sparc64-linux is underway. OK for trunk if it passes there too? Thanks, Martin 2012-12-06 Martin Jambor <mjam...@suse.cz> PR tree-optimization/55590 * tree-sra.c (build_ref_for_offset): Use get_object_alignment_1 to get base alignment. * testsuite/gcc.target/i386/pr55590-1.c: New test. * testsuite/gcc.target/i386/pr55590-2.c: Likewise. *** /dev/null Thu Oct 25 13:49:30 2012 --- gcc/testsuite/gcc.target/i386/pr55590-1.c Tue Dec 4 11:36:54 2012 *************** *** 0 **** --- 1,27 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -mavx" } */ + + #include <immintrin.h> + + struct S + { + __m128 a, b; + }; + + struct T + { + int a; + struct S s; + }; + + + void foo (struct T *p, __m128 v) + { + struct S s; + + s = p->s; + s.b = _mm_add_ps(s.b, v); + p->s = s; + } + + /* { dg-final { scan-assembler-not "vmovups" } } */ *** /dev/null Thu Oct 25 13:49:30 2012 --- gcc/testsuite/gcc.target/i386/pr55590-2.c Tue Dec 4 11:37:02 2012 *************** *** 0 **** --- 1,27 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -mavx" } */ + + #include <immintrin.h> + + struct S + { + __m128 a, b; + }; + + struct T + { + int a; + struct S s[8]; + }; + + + void foo (struct T *p, int i, __m128 v) + { + struct S s; + + s = p->s[i]; + s.b = _mm_add_ps(s.b, v); + p->s[i] = s; + } + + /* { dg-final { scan-assembler-not "vmovups" } } */ *** /tmp/sOn2fd_tree-sra.c Thu Dec 6 15:49:23 2012 --- gcc/tree-sra.c Thu Dec 6 11:46:23 2012 *************** make_fancy_name (tree expr) *** 1423,1429 **** EXP_TYPE at the given OFFSET. If BASE is something for which get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used to insert new statements either before or below the current one as specified ! by INSERT_AFTER. This function is not capable of handling bitfields. */ tree build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset, --- 1423,1432 ---- EXP_TYPE at the given OFFSET. If BASE is something for which get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used to insert new statements either before or below the current one as specified ! by INSERT_AFTER. This function is not capable of handling bitfields. ! ! BASE must be either a declaration or a memory reference that has correct ! alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */ tree build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset, *************** build_ref_for_offset (location_t loc, tr *** 1437,1443 **** unsigned int align; gcc_checking_assert (offset % BITS_PER_UNIT == 0); ! base = get_addr_base_and_unit_offset (base, &base_offset); /* get_addr_base_and_unit_offset returns NULL for references with a variable --- 1440,1446 ---- unsigned int align; gcc_checking_assert (offset % BITS_PER_UNIT == 0); ! get_object_alignment_1 (base, &align, &misalign); base = get_addr_base_and_unit_offset (base, &base_offset); /* get_addr_base_and_unit_offset returns NULL for references with a variable *************** build_ref_for_offset (location_t loc, tr *** 1476,1497 **** base = build_fold_addr_expr (unshare_expr (base)); } ! /* If prev_base were always an originally performed access ! we can extract more optimistic alignment information ! by looking at the access mode. That would constrain the ! alignment of base + base_offset which we would need to ! adjust according to offset. */ ! if (!get_pointer_alignment_1 (base, &align, &misalign)) ! { ! gcc_assert (misalign == 0); ! if (TREE_CODE (prev_base) == MEM_REF ! || TREE_CODE (prev_base) == TARGET_MEM_REF) ! align = TYPE_ALIGN (TREE_TYPE (prev_base)); ! } ! misalign += (tree_to_double_int (off) ! .sext (TYPE_PRECISION (TREE_TYPE (off))).low ! * BITS_PER_UNIT); ! misalign = misalign & (align - 1); if (misalign != 0) align = (misalign & -misalign); if (align < TYPE_ALIGN (exp_type)) --- 1479,1485 ---- base = build_fold_addr_expr (unshare_expr (base)); } ! misalign = (misalign + offset) & (align - 1); if (misalign != 0) align = (misalign & -misalign); if (align < TYPE_ALIGN (exp_type))