Live data from Hacker News

GCC always assumes aligned pointer accesses

trust-in-soft.com

31–40 of 93 posts

Re: GCC always assumes aligned pointer accesses

#31

About 30 years ago, I was porting an Ethernet driver to the MC88K, which also didn't allow misaligned accesses. Guess what happens when you fill a page-aligned buffer with an Ethernet packet, go past the 14-byte Ethernet header, and try to read the first 4-byte value in the IP header as a single word? You guessed it: SIGBUS. Every time. The same problem existed many other places, so I had to go find all of them. Even…

Mixed memory order as in, a memory write stores the data in an order like 5, 7, 6, 4 instead of 4, 5, 6, 7?

Basically yeah, but it gets much more complicated. For example, when a write hits memory is actually not the same thing as when it's observable by some particular other processor. There might be particular rules for writes that have dependencies too. Here's some good reading material if you have a spare afternoon.

https://www.kernel.org/doc/Documentation/memory-barriers.txt

Amusingly, it treats dependency issues as obsolete, but I worked on a processor as late as 2009 that had all of the weak-memory-ordering issues of the Alpha (because it was the same design team). We uncovered lots of missing memory barriers in the Linux kernel. Good times.

Re: GCC always assumes aligned pointer accesses

#32
post #8

No. [as in: this isn't about GCC.] The C standard requires that pointers generally be created from referencing a valid, existing object. A misaligned integer is not a valid "object", thus the compiler may assume that all pointers to ints are aligned (to 4 bytes.) https://en.cppreference.com/w/cpp/language/pointer Every value of pointer type is one of the following: - a pointer to an object or function (in which case…

That misaligned access is UB and that gcc's particular behaviour is assuming alignment are two related but different things. The article says that both are true, and the title is simply the second, as that is the more impactful fact.

Re: GCC always assumes aligned pointer accesses

#33
post #30

Earlier quoted context omitted.

Sort of. He definitely talks about the fact that it is undefined behaviour to create a misaligned pointer: > Strictly speaking, the function f invokes Undefined Behavior when it computes [the misaligned pointer] But he thinks it is still a problem with GCC, in that GCC should not be allowed to take advantage of this particular UB. He explains his view much better in the bug report: > GCC assumes that pointers must be…

The problem with disabling this optimisation is that it will produce garbage code for basically every architecture. Code which does unaligned accesses are noticeably slow compared to aligned accesses -- this is why there are separate instructions and intrinsics for aligned and unaligned addresses on most architectures. That way you don't pay the penalty of unaligned accesses all the time. But if you try to use the al…

> And note that this slowdown would have to apply to every pointer operation in your program because

No, because I think that on x86 the instructions are the same for aligned and unaligned up to, and including, 64 bits (quadword). The only slowdown that would occur is due to missed compiler optimizations, and the author proposed disabling them as an option.

Re: GCC always assumes aligned pointer accesses

#34
post #14

Earlier quoted context omitted.

"No, it's not GCC's fault / doing something weird." :) But, yes. Edited to clarify. FWIW this isn't a new problem either. If you wrote some C code in the 90ies using misaligned pointers, and then tried porting it to, say, a DEC Alpha, you'd get a SIGBUS in your face on first dereferencing such a pointer.

MC68k (anno 1979) didn't like misaligned memory access either and I have no reasons to believe that this started with Motorola. But yes, it's always fun watching a new generation falling into the old traps.

Indeed, PDP/11s don't like it. Older ARM designs too, though I believe they allow it since about ARM6 (perhaqps because x86 does?).

Re: GCC always assumes aligned pointer accesses

#35
post #32
post #8

No. [as in: this isn't about GCC.] The C standard requires that pointers generally be created from referencing a valid, existing object. A misaligned integer is not a valid "object", thus the compiler may assume that all pointers to ints are aligned (to 4 bytes.) https://en.cppreference.com/w/cpp/language/pointer Every value of pointer type is one of the following: - a pointer to an object or function (in which case…

That misaligned access is UB and that gcc's particular behaviour is assuming alignment are two related but different things. The article says that both are true, and the title is simply the second, as that is the more impactful fact.

I disagree that the second is more impactful, but that's because I work with oddball architectures where the UB actually crashes the program ;).

I'm wondering though, does UBSAN catch this?

Re: GCC always assumes aligned pointer accesses

#36
post #29
post #15

Earlier quoted context omitted.

It literally cannot. The function in the linked article, that takes two pointers, must be compiled in isolation. If it needs to depend on alignment or overlapping, it needs to emit code to check it. And the standard does not require it to, nor do typical users want that. It's true that fancy tricks like LTO can make that kind of behavior visible to the optimizer, but the standard predates that kind of magic by severa…

That's not what I meant. On an architecture where "long long" is 8 bytes, but only has a 4 byte alignment requirement, the compiler knows this, and knows that 2 pointers of type "long long * " may overlap. Therefore it would disable the optimization. (Except the pointers still aren't supposed to overlap, but...)

No, it wouldn't disable the optimization, because a pointer 4 bytes into a live long long object isn't a valid pointer to another long long object that is live at the same time (even though it could abstractly be a valid pointer to long long over the life of the program). If you want to disable the optimization you can use a union (which would also be technically UB but in practice compilers document that they do the right thing).

Re: GCC always assumes aligned pointer accesses

#37
post #34

Earlier quoted context omitted.

MC68k (anno 1979) didn't like misaligned memory access either and I have no reasons to believe that this started with Motorola. But yes, it's always fun watching a new generation falling into the old traps.

Indeed, PDP/11s don't like it. Older ARM designs too, though I believe they allow it since about ARM6 (perhaqps because x86 does?).

The arms allow it since ARMv5, but it's still not quite what one would expect until ARMv7. However it has a significant performance penalty when doing it.

https://medium.com/@iLevex/the-curious-case-of-unaligned-acc...

Re: GCC always assumes aligned pointer accesses

#38
post #33
post #30

Earlier quoted context omitted.

The problem with disabling this optimisation is that it will produce garbage code for basically every architecture. Code which does unaligned accesses are noticeably slow compared to aligned accesses -- this is why there are separate instructions and intrinsics for aligned and unaligned addresses on most architectures. That way you don't pay the penalty of unaligned accesses all the time. But if you try to use the al…

> And note that this slowdown would have to apply to every pointer operation in your program because No, because I think that on x86 the instructions are the same for aligned and unaligned up to, and including, 64 bits (quadword). The only slowdown that would occur is due to missed compiler optimizations, and the author proposed disabling them as an option.

Yes, up to 64 bits. They're different for x86 SIMD (128 bits and up, SSE & AVX). For example vmovapd (requires alignment) vs vmovupd (can be unaligned).

Re: GCC always assumes aligned pointer accesses

#39
post #30

Earlier quoted context omitted.

Sort of. He definitely talks about the fact that it is undefined behaviour to create a misaligned pointer: > Strictly speaking, the function f invokes Undefined Behavior when it computes [the misaligned pointer] But he thinks it is still a problem with GCC, in that GCC should not be allowed to take advantage of this particular UB. He explains his view much better in the bug report: > GCC assumes that pointers must be…

The problem with disabling this optimisation is that it will produce garbage code for basically every architecture. Code which does unaligned accesses are noticeably slow compared to aligned accesses -- this is why there are separate instructions and intrinsics for aligned and unaligned addresses on most architectures. That way you don't pay the penalty of unaligned accesses all the time. But if you try to use the al…

> The problem with disabling this optimisation is that it will produce garbage code for basically every architecture.

I'm pretty sure this this is not true for modern x64, which is one of the most common desktop architectures: https://lemire.me/blog/2012/05/31/data-alignment-for-speed-m...

Which current architectures are you thinking of? Do you have comparable benchmarks showing the slowdown?

Re: GCC always assumes aligned pointer accesses

#40
post #35
post #32

Earlier quoted context omitted.

That misaligned access is UB and that gcc's particular behaviour is assuming alignment are two related but different things. The article says that both are true, and the title is simply the second, as that is the more impactful fact.

I disagree that the second is more impactful, but that's because I work with oddball architectures where the UB actually crashes the program ;). I'm wondering though, does UBSAN catch this?

In my experience, yes, it’ll warn you if you access something aligned to the wrong boundary.
Post reply on HN