https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085
Bug ID: 88085 Summary: User alignments on var decls not respected if smaller than type alignment Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: krebbel at gcc dot gnu.org Target Milestone: --- typedef int __attribute__((vector_size(16))) v4si; v4si a4 __attribute__((aligned(4))); void foo (v4si a) { a4 += a; } -O3 -dP MEM_ALIGN for variable a4 is 128 bits although it is emitted with an alignment requirement of just 4: .comm a4,16,4 It works when moving the aligned attribute over to the typedef instead. foo: #(insn:TI 6 3 7 2 (set (reg:V4SI 20 xmm0 [85]) # (plus:V4SI (reg:V4SI 20 xmm0 [86]) # (mem/c:V4SI (symbol_ref:DI ("a4") [flags 0x2] <var_decl 0x7ff6d222eab0 a4>) [1 a4+0 S16 A128]))) "t.c":8:6 3122 {*addv4si3} # (expr_list:REG_EQUIV (mem/c:V4SI (symbol_ref:DI ("a4") [flags 0x2] <var_decl 0x7ff6d222eab0 a4>) [1 a4+0 S16 A128]) # (nil))) paddd a4(%rip), %xmm0 # 6 [c=12 l=8] *addv4si3/0 #(insn:TI 7 6 18 2 (set (mem/c:V4SI (symbol_ref:DI ("a4") [flags 0x2] <var_decl 0x7ff6d222eab0 a4>) [1 a4+0 S16 A128]) # (reg:V4SI 20 xmm0 [85])) "t.c":8:6 1198 {movv4si_internal} # (expr_list:REG_DEAD (reg:V4SI 20 xmm0 [85]) # (nil))) movaps %xmm0, a4(%rip) # 7 [c=4 l=7] movv4si_internal/3 #(jump_insn:TI 14 18 15 2 (simple_return) "t.c":9:1 688 {simple_return_internal} # (nil) # -> simple_return) ret # 14 [c=0 l=1] simple_return_internal .size foo, .-foo .comm a4,16,4 .ident "GCC: (GNU) 9.0.0 20181114 (experimental)" set_mem_attributes_minus_bitpos in emit-rtl.c: This code sets the alignment field based on the type alignment: /* ??? If T is a type, respecting mode alignment may *also* be wrong e.g. if the type carries an alignment attribute. Should we be able to simply always use TYPE_ALIGN? */ } /* We can set the alignment from the type if we are making an object or if this is an INDIRECT_REF. */ if (objectp || TREE_CODE (t) == INDIRECT_REF) attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); This code later would use the alignment in the aligned attribute (in obj_align) but ignores it if it is lower than the alignment we already have?! As expected setting bigger alignments on the var decl works. /* If this is an indirect reference, record it. */ else if (TREE_CODE (t) == MEM_REF || TREE_CODE (t) == TARGET_MEM_REF) { attrs.expr = t; attrs.offset_known_p = true; attrs.offset = 0; apply_bitpos = bitpos; } /* Compute the alignment. */ unsigned int obj_align; unsigned HOST_WIDE_INT obj_bitpos; get_object_alignment_1 (t, &obj_align, &obj_bitpos); unsigned int diff_align = known_alignment (obj_bitpos - bitpos); if (diff_align != 0) obj_align = MIN (obj_align, diff_align); attrs.align = MAX (attrs.align, obj_align); }