[Compiler-rt] Implement AEABI Unaligned Read/Write Helpers in compiler-rt#167913
Conversation
…r-rt This patch adds implementations for the __aeabi_uread and __aeabi_uwrite helper functions to compiler-rt..
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===-----------------------------------------------------------------------------===// |
There was a problem hiding this comment.
Probably a good idea to link to the document defining these functions.
https://github.com/ARM-software/abi-aa/blob/main/rtabi32/rtabi32.rst#unaligned-memory-access
| char v[4]; | ||
| } v4; | ||
|
|
||
| int __aeabi_uread4(void *p) { |
There was a problem hiding this comment.
I was going to say that surely the read functions should take a const void *, but in RTABI, they don't! I suppose because nobody ever calls these functions from C, so the C prototype isn't really important, only the machine-level PCS that it translates into.
| extern long long __aeabi_uread8(void *); | ||
| extern long long __aeabi_uwrite8(long long, void *); | ||
|
|
||
| #define lenof(x) (sizeof((x)) / sizeof(*(x))) |
There was a problem hiding this comment.
It's 2025, so we can use _Countof for this! \o/
| long long target8; | ||
| int target4; | ||
| const char source[] = "abcdefghijklmno"; | ||
| static char dest1[lenof(source)], dest2[lenof(source)]; |
There was a problem hiding this comment.
Using static is optional. It’s used here mainly to improve reproducibility — since it provides a stable address from which we can repeatably test unaligned writes.
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
…compiler-rt Apply clang-format to address style issues in the previous patch.
efriedma-quic
left a comment
There was a problem hiding this comment.
LLVM currently doesn't generate calls to these functions. From what I recall, my team did some internal testing of these functions at one point, and we found it basically doesn't make sense to call the 4-byte versions; on cores that still care about misaligned accesses, calls are expensive, so the tradeoff isn't really worth it for normal code.
Do you have some plan to use these functions?
|
|
||
| typedef struct { | ||
| char v[4]; | ||
| } v4; |
There was a problem hiding this comment.
Technically, to avoid breaking TBAA rules, this needs to be __attribute__((__may_alias__)). Not sure if it's likely to matter in practice.
Yes, we are currently working on enabling LLVM to emit these functions. I don’t have the patch ready right now, but I’m working on it and will send it soon. These helpers are not intended for performance-oriented code paths—indeed, the call overhead can make them unsuitable for that. These functions are planned to be emitted only for size-optimised code paths (-Os/-Oz) and also when -mno-unaligned-access (or equivalent) is used. Without these helpers, LLVM would need to inline byte wise sequences , which can increases code size, especially at -Os/-Oz. Using the helper functions allows to retain correctness while avoiding that code-size growth. We haven’t benchmarked this yet, but we do expect some code-size savings in real workloads. Even though many modern Arm cores handle unaligned accesses natively, there are still deployments—particularly in embedded and legacy environments—where unaligned support is limited or intentionally disabled. The AEABI helpers can give a mechanism to handle these cases. Another motivation is ABI and ecosystem consistency. GCC-based toolchains already provide these AEABI helpers, so supporting them in compiler-rt ensures parity and avoids accidental dependencies on libgcc when LLVM begins emitting these calls. Happy to hear any thoughts or concerns. Feedback on additional use-cases or scenarios we should consider would be very welcome. |
|
Okay, that's fine. I suspect the performance penalty is too large at -Os; maybe it's okay at -Oz. |
From initial measurements, both -Os and -Oz appear to have a comparable performance degradation. This is the patch for the corresponding codegen emission #172672. At the moment, this implementation emits AEABI calls for unaligned accesses when building with -Os or -Oz together with -mno-unaligned-access. |
|
I'll approve after the following:
|
My point is that users using -Os may not find that degradation acceptable. But we can continue that discussion that on the codegen patch. |
…ers in compiler-rt Make the AEABI Unaligned Read/Write Helpers implementation in assembly.
Hi, A C implementation cannot reliably guarantee this. When you have a chance, please have another look at the implementation. |
I verified this — arm/aeabi_unaligned_access_test.c is in the passed tests list (see test output/logs). |
|
Is it not sufficient to build the C code with -mfpu=none or something like that? Maybe easier to just write it in assembly and not worry about it, though. |
Yeah - It would help make sure we don't do anything silly like use the stack. |
Yeah. These functions are relatively simple, I prefer to keep them implemented in assembly. |
|
Thank you @efriedma-quic |
…r-rt (llvm#167913) This patch adds implementations for the __aeabi_uread and __aeabi_uwrite helper functions to compiler-rt. Without these helpers, LLVM would need to inline byte wise sequences , which can increases code size, especially at -Os/-Oz. Using the helper functions allows to retain correctness while avoiding the code-size growth. GCC-based toolchains already provide these AEABI helpers, so supporting them in compiler-rt ensures parity and avoids accidental dependencies on libgcc when LLVM begins emitting these calls.
… unaligned i32/i64 loads/stores to __aeabi_uread/uwrite{4,8} (#734)
Downstream issue:#727
This was committed upstream after the LLVM 22 branch was created. Mostly
upstream will not accept it into the 22 branch, as it is not considered
critical enough for backporting.
When targeting ARM (in particular architectures or variants that do not
allow unaligned memory accesses, e.g., with -mno-unaligned-access or
older cores like ARMv6-M) the backend currently handles unaligned loads
or stores by expanding them into sequences of byte/half-word
loads/stores.
This change proposes to detect unaligned loads/stores of size 4 bytes
(i32) or 8 bytes (i64) when alignment is insufficient, and instead emit
calls to the AEABI helper functions by llvm:
• __aeabi_uread4, __aeabi_uread8 for unaligned reads
• __aeabi_uwrite4, __aeabi_uwrite8 for unaligned writes
By lowering to these functions, code size can be reduced compared to
in-lined byte/half-word sequences providing they are invoked more than
once across a program. This also needs to add the implementations for
the __aeabi_uread and __aeabi_uwrite helper functions to compiler-rt.
List of upstream PRs:
- llvm/llvm-project#167913
- llvm/llvm-project#172672
This patch adds implementations for the __aeabi_uread and __aeabi_uwrite helper functions to compiler-rt.
Without these helpers, LLVM would need to inline byte wise sequences , which can increases code size, especially at -Os/-Oz. Using the helper functions allows to retain correctness while avoiding the code-size growth.
GCC-based toolchains already provide these AEABI helpers, so supporting them in compiler-rt ensures parity and avoids accidental dependencies on libgcc when LLVM begins emitting these calls.