[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #21 from rguenther at suse dot de --- On Thu, 2 Sep 2021, petro.karashchenko at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 > > --- Comment #20 from Petro Karashchenko > --- > I just checked next case > > typedef int tolerant_int __attribute__((aligned(1))); > tolerant_int var; > > int foo(void) > { > return var; > } > -- > arm-none-eabi-gcc -save-temps -Wall -Wextra -c -mcpu=arm7tdmi -mthumb test.c > -O0 > -- > .cpu arm7tdmi > .eabi_attribute 20, 1 > .eabi_attribute 21, 1 > .eabi_attribute 23, 3 > .eabi_attribute 24, 1 > .eabi_attribute 25, 1 > .eabi_attribute 26, 1 > .eabi_attribute 30, 6 > .eabi_attribute 34, 0 > .eabi_attribute 18, 4 > .file "test.c" > .text > .comm var,4,1 > .align 1 > .global foo > .arch armv4t > .syntax unified > .code 16 > .thumb_func > .fpu softvfp > .type foo, %function > foo: > @ Function supports interworking. > @ args = 0, pretend = 0, frame = 0 > @ frame_needed = 1, uses_anonymous_args = 0 > push{r7, lr} > add r7, sp, #0 > ldr r3, .L3 > ldr r3, [r3] > movsr0, r3 > mov sp, r7 > @ sp needed > pop {r7} > pop {r1} > bx r1 > .L4: > .align 2 > .L3: > .word var > .size foo, .-foo > .ident "GCC: (GNU Tools for Arm Embedded Processors 9-2019-q4-major) > 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]" > - > > So seems the alignment decrease does not work on types. It works on trunk. There were bugs fixed for arm "recently" (your 9.2.1 is nearly two years old).
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #20 from Petro Karashchenko --- I just checked next case typedef int tolerant_int __attribute__((aligned(1))); tolerant_int var; int foo(void) { return var; } -- arm-none-eabi-gcc -save-temps -Wall -Wextra -c -mcpu=arm7tdmi -mthumb test.c -O0 -- .cpu arm7tdmi .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 6 .eabi_attribute 34, 0 .eabi_attribute 18, 4 .file "test.c" .text .comm var,4,1 .align 1 .global foo .arch armv4t .syntax unified .code 16 .thumb_func .fpu softvfp .type foo, %function foo: @ Function supports interworking. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 push{r7, lr} add r7, sp, #0 ldr r3, .L3 ldr r3, [r3] movsr0, r3 mov sp, r7 @ sp needed pop {r7} pop {r1} bx r1 .L4: .align 2 .L3: .word var .size foo, .-foo .ident "GCC: (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]" - So seems the alignment decrease does not work on types.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #19 from Petro Karashchenko --- Sorry my bad again. Just checked with GCC 11 man page When used on a struct, or struct member, the aligned attribute can only increase the alignment; in order to decrease it, the packed attribute must be specified as well. When used as part of a typedef, the aligned attribute can both increase and decrease alignment, and specifying the packed attribute generates a warning.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #18 from Petro Karashchenko --- Yes. So I just checked GCC man and see that The aligned attribute can only increase the alignment; but you can decrease it by specifying packed as well. See below. Note that the effectiveness of aligned attributes may be limited by inherent limitations in your linker. On many systems, the linker is only able to arrange for variables to be aligned up to a certain maximum alignment. (For some linkers, the maximum supported alignment may be very very small.) If your linker is only able to align variables up to a maximum of 8 byte alignment, then specifying aligned(16) in an __attribute__ will still only provide you with 8 byte alignment. See your linker documentation for further information. So typedef int tolerant_int __attribute__((aligned(1))); extern tolerant_int possibly_misaligned_data; "possibly_misaligned_data" will still be 4 bytes aligned. The real problem is that "packed" can be applied only to struct or union type definition, I can't just do typedef int tolerant_int __attribute__((packed)); extern tolerant_int possibly_misaligned_data; So it will simply not work and I need to wrap a variable into a struct or union.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #17 from rguenther at suse dot de --- On Thu, 2 Sep 2021, petro.karashchenko at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 > > --- Comment #16 from Petro Karashchenko > --- > Again based on your description even if we go with putting "tolerance" on the > type should not work because in "typedef int tolerant_int > __attribute__((aligned(1)));" the "int" default alignment is 4 and we apply > "1", so according to "The @code{aligned} attribute specifies a MINIMUM > alignment for the variable or structure field, measured in bytes." the > compiler > should use the MAX of all alignments of the type MAX(4,1) is 4 and not 1. > > So > typedef int int_1 __attribute__((aligned(1))); > typedef int_1 int_2 __attribute__((aligned(2))); > typedef int_2 int_4 __attribute__((aligned(4))); > typedef int_4 int_8 __attribute__((aligned(8))); > typedef int_8 int_16 __attribute__((aligned(16))); > > int_16 a; > > Then a should get aligned on 16 and not on 1. It is (aligned to 16).
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #16 from Petro Karashchenko --- Again based on your description even if we go with putting "tolerance" on the type should not work because in "typedef int tolerant_int __attribute__((aligned(1)));" the "int" default alignment is 4 and we apply "1", so according to "The @code{aligned} attribute specifies a MINIMUM alignment for the variable or structure field, measured in bytes." the compiler should use the MAX of all alignments of the type MAX(4,1) is 4 and not 1. So typedef int int_1 __attribute__((aligned(1))); typedef int_1 int_2 __attribute__((aligned(2))); typedef int_2 int_4 __attribute__((aligned(4))); typedef int_4 int_8 __attribute__((aligned(8))); typedef int_8 int_16 __attribute__((aligned(16))); int_16 a; Then a should get aligned on 16 and not on 1.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #15 from rguenther at suse dot de --- On Thu, 2 Sep 2021, petro.karashchenko at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 > > --- Comment #13 from Petro Karashchenko > --- > Sorry that I brought some confusion. I was reading some latest comments and > didn't fully payed attention to a ticket description. The reason for my > comment > is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 that was closed as a > duplicate of this issue. > > For the variable alignment vs type alignment when it is specified your > statement seems to be correct, however I agree that it still has a lot of open > points. For example what should be the code if we put variable into a > structure > > typedef int __attribute__((vector_size(16))) v4si; > > struct { > v4si a __attribute__((aligned(4))); > } b; > > Should it still get aligned on 16 bytes or 4 bytes? > > In my case I was seeking for a way to generate alignment tolerant code without > using > struct { > int a; > } __attribute__((packed)); > > Obviously "int a __attribute__((packed));" does not work, so I tried to solve > it via "__attribute__((aligned(1)))" attribute. I don't think it makes much sense to generate alignment "tolerant" code for declarations, so when it is about indirect accesses via pointers then simply use a pointer to a type with appropriate alignment. Then the access will be "tolerant" but when the compiler sees the object accessed is actually of bigger alignment it isn't forced to honor your "tolerant" minimum alignment. When you're facing the situation that you have to access data at some symbol and that symbol can end up with alignment less than what its type specifies then you cannot just do extern int possibly_misaligned_data __attribute__((aligned(1))); which seems to be the case kernel folks run into with hppa. Instead you have to put the "tolerance" on the type again: typedef int tolerant_int __attribute__((aligned(1))); extern tolerant_int possibly_misaligned_data;
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #14 from Petro Karashchenko --- Probably I need to fill a ticket to allow "packed" to be applied for variables and not only to a types of structure fields.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #13 from Petro Karashchenko --- Sorry that I brought some confusion. I was reading some latest comments and didn't fully payed attention to a ticket description. The reason for my comment is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 that was closed as a duplicate of this issue. For the variable alignment vs type alignment when it is specified your statement seems to be correct, however I agree that it still has a lot of open points. For example what should be the code if we put variable into a structure typedef int __attribute__((vector_size(16))) v4si; struct { v4si a __attribute__((aligned(4))); } b; Should it still get aligned on 16 bytes or 4 bytes? In my case I was seeking for a way to generate alignment tolerant code without using struct { int a; } __attribute__((packed)); Obviously "int a __attribute__((packed));" does not work, so I tried to solve it via "__attribute__((aligned(1)))" attribute.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #12 from Richard Biener --- (In reply to Petro Karashchenko from comment #11) > Sorry but based on > > @cindex @code{aligned} variable attribute > @item aligned > @itemx aligned (@var{alignment}) > The @code{aligned} attribute specifies a MINIMUM alignment for the variable > or structure field, measured in bytes. When specified, @var{alignment} must > be an integer constant power of 2. Specifying no @var{alignment} argument > implies the maximum alignment for the target, which is often, but by no > means always, 8 or 16 bytes. > > I do not see any statement saying that giving a lower alignment is invalid. > I see "attribute specifies a MINIMUM alignment" so "int i > __attribute__((aligned(1)));" specifies that between 1 and 4 the 1 should be > chosen as a "MINIMUM". > > The statement "must be an integer constant power of 2" is also valid because > 1 is a 0 power of 2. So no questions here. > > "Thus IMHO this bug is invalid." -- I do not see any strong argument on > this. All prerequisites from a description are met, so this is a pure bug. The testcase of the description is typedef int __attribute__((vector_size(16))) v4si; v4si a4 __attribute__((aligned(4))); that creates a variable with minimum alignment 4 (as seen in the assembly output). But you give the variable a type of 'v4si' which has larger alignment and thus is in conflict with the alignment for the storage you specified. That automatically runs into the standard mandated rule that any access has to be aligned according to its type. The expectation that accesses should be unaligned is wrong unless you also use an unaligned type. That GCC creates an object with the desired alignment isn't wrong - you told it so. As I said the conflict should probably be diagnosed as it results in unexpected behavior.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #11 from Petro Karashchenko --- Sorry but based on @cindex @code{aligned} variable attribute @item aligned @itemx aligned (@var{alignment}) The @code{aligned} attribute specifies a MINIMUM alignment for the variable or structure field, measured in bytes. When specified, @var{alignment} must be an integer constant power of 2. Specifying no @var{alignment} argument implies the maximum alignment for the target, which is often, but by no means always, 8 or 16 bytes. I do not see any statement saying that giving a lower alignment is invalid. I see "attribute specifies a MINIMUM alignment" so "int i __attribute__((aligned(1)));" specifies that between 1 and 4 the 1 should be chosen as a "MINIMUM". The statement "must be an integer constant power of 2" is also valid because 1 is a 0 power of 2. So no questions here. "Thus IMHO this bug is invalid." -- I do not see any strong argument on this. All prerequisites from a description are met, so this is a pure bug.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Richard Biener changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |INVALID --- Comment #10 from Richard Biener --- The implementation issue is that extern int var __attribute__((aligned(1))); has DECL_ALIGN of 8 but the type still has alignment of 32, so when you take the address and dereference it you'll get a ref with 32 bit alignment. For aligned attributes that increase alignment that's not a correctness issue but for aligned attributes decreasing alignment it becomes a problem. If we want to make the above work reliably we have to arrange for the type of 'var' to be adjusted by the aligned attribute on the decl. But IMHO diagnosing alignment decreasing attributes on decls would be appropriate. The docs clearly say (emphasis mine): @cindex @code{aligned} variable attribute @item aligned @itemx aligned (@var{alignment}) The @code{aligned} attribute specifies a MINIMUM alignment for the variable or structure field, measured in bytes. When specified, @var{alignment} must be an integer constant power of 2. Specifying no @var{alignment} argument implies the maximum alignment for the target, which is often, but by no means always, 8 or 16 bytes. so giving a larger alignment is valid. Likewise for extern int i __attribute__((aligned(1))); the alignment of 'i' is known to be at least 1 from the attribute but we also know that 'int' is aligned to 4 and thus can use that larger alignment. Thus IMHO this bug is invalid. You have to reduce the alignment of the type which is another alignment constraint seen by the compiler.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Andrew Pinski changed: What|Removed |Added CC||andrew.bennett at imgtec dot com --- Comment #9 from Andrew Pinski --- *** Bug 71106 has been marked as a duplicate of this bug. ***
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #8 from Andrew Pinski --- An obvious workaround is to have a type which is also aligned to what you want the global to be aligned to and that will work. typedef int __attribute__((vector_size(16))) v4si; typedef v4si __attribute__((aligned(4))) v4sia4; v4sia4 a4 __attribute__((aligned(4))); or: typedef int __attribute__((aligned(1))) inta1; inta1 __attribute__((aligned(1))) var; or for the case in PR 102162 : typedef unsigned int u32a1 __attribute__((__aligned__(1))); extern u32a1 output_len __attribute__((__aligned__(1)));
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Andrew Pinski changed: What|Removed |Added CC||danglin at gcc dot gnu.org --- Comment #7 from Andrew Pinski --- *** Bug 102162 has been marked as a duplicate of this bug. ***
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #6 from Andrew Pinski --- A simpler testcase is: int __attribute__((aligned(1))) var; int foo(void) { return var; } - CUT --- Compile this on a strict alignment target and you get the wrong code.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Andrew Pinski changed: What|Removed |Added CC||petro.karashchenko at gmail dot co ||m --- Comment #5 from Andrew Pinski --- *** Bug 94662 has been marked as a duplicate of this bug. ***
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Andrew Pinski changed: What|Removed |Added Keywords||wrong-code --- Comment #4 from Andrew Pinski --- PR 102162 just ran into this same problem on hppa-linux-gnu even inside the Linux kernel.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Andrew Pinski changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2021-09-02 Ever confirmed|0 |1 --- Comment #3 from Andrew Pinski --- Confirmed.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 --- Comment #2 from Andreas Krebbel --- (In reply to Richard Biener from comment #1) ... > which is bogus again unless the caller already had pre-existing attrs > on the MEM. I guess using > > attrs.align = refattrs ? MAX (refattrs.align, obj_align) : obj_align; > > fixes your issue? Or are you objectp == true? I think an INDIRECT_REF never > happens today. Yes, it does. objectp is true as well. t is a var decl.
[Bug middle-end/88085] User alignments on var decls not respected if smaller than type alignment
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88085 Richard Biener changed: What|Removed |Added CC||rguenth at gcc dot gnu.org --- Comment #1 from Richard Biener --- ISTR you have to use packed to decrease alignment. OTOH /* 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)); is fishy but so is the preceeding /* Otherwise, default values from the mode of the MEM reference. */ else { ... /* Respect mode alignment for STRICT_ALIGNMENT targets if T is a type; if T is an object, always compute the object alignment below. */ if (TYPE_P (t)) attrs.align = defattrs->align; else attrs.align = BITS_PER_UNIT; IMHO alignment setting should be left to the callers and it should be conservative here (the objectp == true case can probably be preserved). Note we already set the alignment later in a correct way if ! TYPE_P but likewise using attrs.align = MAX (attrs.align, obj_align); which is bogus again unless the caller already had pre-existing attrs on the MEM. I guess using attrs.align = refattrs ? MAX (refattrs.align, obj_align) : obj_align; fixes your issue? Or are you objectp == true? I think an INDIRECT_REF never happens today.