Groups | Search | Server Info | Login | Register
Groups > comp.arch.embedded > #32478
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Newsgroups | comp.arch.embedded |
| Subject | Re: arm-gcc, Cortex-M0+, uint64_t and alignment |
| Date | 2026-01-21 17:57 +0100 |
| Organization | A noiseless patient Spider |
| Message-ID | <10kr0gf$29a7t$1@dont-email.me> (permalink) |
| References | (4 earlier) <10koet6$1dlne$2@dont-email.me> <10kq1m7$1un41$1@dont-email.me> <10kq4mi$1vcdq$1@dont-email.me> <10kqpg9$26oa0$1@dont-email.me> <10kqu02$280ts$1@dont-email.me> |
Il 21/01/2026 17:13, David Brown ha scritto:
> On 21/01/2026 15:58, pozz wrote:
>> Il 21/01/2026 10:02, David Brown ha scritto:
>>> On 21/01/2026 09:11, pozz wrote:
>>>> Il 20/01/2026 18:44, David Brown ha scritto:
>>>>> On 20/01/2026 18:09, pozz wrote:
>>>>>> Il 20/01/2026 17:41, Grant Edwards ha scritto:
>>>>>>> On 2026-01-20, David Brown <david.brown@hesbynett.no> wrote:
>>>>>>>
>>>>>>>> You can't reduce the alignment of a struct or its elements by
>>>>>>>> adding an
>>>>>>>> __aligned_ attribute to the struct itself or any of its fields.
>>>>>>>> The
>>>>>>>> best you can do on the struct itself is __attribute__((packed)).
>>>>>>>> But
>>>>>>>> that can come with disadvantages, and inefficient use.
>>>>>>>
>>>>>>> Yep making a structure aligned is an excellent way to introduce
>>>>>>> subtle
>>>>>>> bugs that happen when somebody, somewhere passes a pointer to one of
>>>>>>> those structure fields to some library function.
>>>>>>
>>>>>> However, as long as the application runs on Cortex-M0+, the
>>>>>> aligned version shouldn't introduce issues, should it?
>>>>>>
>>>>>>
>>>>>
>>>>> Correctly aligned data is never a problem. /Misaligned/ data is a
>>>>> problem.
>>>>>
>>>>> The Cortex-M0+ cannot access misaligned data directly. But if the
>>>>> compiler knows that it is misaligned - by "packed" struct, or
>>>>> "aligned" attribute on the typedef - it should break apart the
>>>>> accesses into bytes or 16-bit half-words as necessary. (Aligning a
>>>>> uint64_t to 4 byte alignment will not be a problem.)
>>>>
>>>> However for Cortex-M0+ uint64_t aligned at 4 bytes is:
>>>> - aligned for the core (two 4-bytes aligned accesses are required)
>>>
>>> Yes. As far as I know, the M0+ core does not need any alignment
>>> greater than 4 for any purpose. (But I might not know everything
>>> about the core!) There can be alignment requirements for other
>>> things, such as DMA.
>>>
>>>> - misaligned for the ABI and the compiler
>>>
>>> Yes.
>>>
>>>>
>>>> We agree that forcing the gcc compiler to consider 4-bytes as the
>>>> required alignment of uint64_t (using aligned attribute) is always
>>>> safe.
>>>
>>> No.
>>>
>>> It will almost always be safe, but you don't have any guarantees.
>>> The compiler knows that if "p" is of type "uint64_t *", then
>>> "(uintptr_t) p & 0x07" will always be zero. Is it likely that you
>>> would have anything in your code where that is relevant, and also
>>> that the compiler would generate code that relies on that
>>> assumption? No, it is very unlikely.
>>>
>>> But there is a general principle that you should not lie to your
>>> compiler - don't write code that executes UB, breaks ABIs, or is
>>> otherwise breaking the contract you have with the compiler unless you
>>> are using compiler features that let you keep everything honest.
>>>
>>> Part of that is that code you are writing now for the M0+ might be
>>> copied or adapted to a different target at a different time. Maybe
>>> on a different core, the same data will be read using some kind of
>>> SIMD or vector instruction that /does/ require 8-byte alignment.
>>> Don't mess these things without telling your compiler. And don't
>>> mess with them without telling future maintainers and programmers
>>> using the code (including your future self).
>>
>> But it is exactly what I wanted to do: explictly tell the compiler to
>> align uint64_t at a 4-bytes address (as I wrote, with attribute
>> align). I didn't think to lie my best friend compiler.
>>
>
> uint64_t on 32-bit EABI ARM has an alignment of 8 bytes. That's cut in
> stone, and you cannot change it (short of adding a new ABI to the
> toolchain). If you try to use uint64_t objects that are not 8-byte
> aligned, or try to use pointers that are not 8-byte aligned to access
> uint64_t types, you are lying to your compiler.
>
> If you make a new type that is like a uint64_t but with an "aligned(4)"
> attribute, you have a /new/ type. And that type will work just like you
> want - it is an 8 byte unsigned integer with a 4 byte alignment. As
> long as you use that consistently, you'll be fine.
>
>> What I wanted to know is if there were other issues or drawback, such
>> as more instructions penalty.
>
> The drawback from trying to use an object of a type with an improper
> alignment is that you have UB. What more reasons do you want for not
> doing it?
Most probably I can't explain what I want to say. I don't want to use an
*improper* alignment (different from the one that gcc really is using).
I want to know what happens when I *instruct* the compiler to use a
4-bytes alignment for uint64_t in the context of Cortex-M0+ core only.
In other words, is it completely safe to use, as you suggested,
typedef uint64_t __attribute__((align(4))) uint64_a;
???
From what you wrote, I think yes. Maybe just a very small optimization
penalty.
>> From the goldbot link that you share in another post, it seems there's
>> a penalty of a single instruction (it's strange, it seems the compiler
>> needs to save the struct pointer to r3, before loading the two halves
>> of the word, but only if uint64_t is aligned to 4-bytes).
>>
>
> The compiler is not perfect here - there is definitely an extra
> instruction because it is reading the low word first. (clang reads the
> low word first for uint64_t as well, meaning it gives worse code for A
> and B as well.) In real code, rather than a brief test snippet, other
> factors could mean this does not happen - it's only because the pointer
> happens to be in r0 that you see it here.
>
> But there's no harm in filing a gcc bug on this, looking for an obvious
> improvement.
>
>>
>>> I would be extremely surprised to find code that fails to work on an
>>> M0+ because of a uint64_t pointer that is 4-byte aligned but not
>>> 8-byte aligned. But if /I/ want to use 64-bit integers with 4-byte
>>> alignments, I'd use the typedef'd aligned type for the object type
>>> and for any relevant pointers.
>>
>> Yes, of course. Even if I don't understand why the compiler isn't able
>> to align at 4-bytes address the uint64_t member in struct B.
>>
>
> It can't align the uint64_t member because the EABI says uint64_t (or,
> rather, unsigned long long) is 8 bytes aligned. gcc didn't make those
> rules - ARM did.
But struct B is defined with correct alignment attribute for uint64_t
member. I tried also:
struct B {
uint32_t x;
uint64_t y __attribute__((aligned(4)));
};
The struct size is always 16, so y is placed at offset 8 and not 4. It
seems to me gcc isn't able to respect the aligned attribute of 4 bytes
when it is specified inside the struct definition.
I don't see many differences with:
typedef __attribute__((aligned(4))) uint64_t uint64_a;
struct C {
uint32_t x;
uint64_a y;
};
>
> As I briefly mentioned before, there are a number of very poor choices
> in the EABI (and the 32-bit ARM ABI used for Linux). This is far from
> the worst.
>
>>>> However, what really changes in the binary output?
>>>>
>>>> In some cases, the address of uint64_t can change from 8-bytes to
>>>> 4-bytes aligned address (because we instructed it to do so). What
>>>> about the code that accesses uint64_t aligned to 4-bytes? Is it
>>>> identical between 4- and 8-bytes alignment requirement? I think so,
>>>> because in both case, the compiler should add two load/store 4-bytes
>>>> instructions.
>>>>
>>>
>>
>
Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar
arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-20 13:26 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-20 17:07 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment Grant Edwards <invalid@invalid.invalid> - 2026-01-20 16:41 +0000
Re: arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-20 18:09 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-20 18:44 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-21 09:11 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-21 10:02 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-21 15:58 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-21 17:13 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-21 17:57 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-22 10:03 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment Grant Edwards <invalid@invalid.invalid> - 2026-01-20 17:48 +0000
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-20 18:41 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment Grant Edwards <invalid@invalid.invalid> - 2026-01-20 18:10 +0000
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-20 22:32 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment Grant Edwards <invalid@invalid.invalid> - 2026-01-21 03:38 +0000
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-21 08:54 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment pozz <pozzugno@gmail.com> - 2026-01-20 17:55 +0100
Re: arm-gcc, Cortex-M0+, uint64_t and alignment David Brown <david.brown@hesbynett.no> - 2026-01-20 22:24 +0100
csiph-web