Carry the D type alignment on struct copy/init memcpy and memset - #5279
Carry the D type alignment on struct copy/init memcpy and memset#5279TurkeyMan wants to merge 1 commit into
Conversation
DtoAssign copied structs via DtoMemCpy with the default alignment of 1, and struct literal initialisation (static init symbol copy and zero-init) did the same. LLVM then had to treat every struct copy as potentially unaligned. On targets without unaligned access (e.g. armv5te with -mattr=+strict-align) that lowers each small struct copy to a sequence of byte loads and stores; on a ~1 MB embedded image this was ~12 KB of text. Pass DtoAlignment(type) at those sites. This is the alignment the type's allocas and globals already use, so no new assumption is introduced; an align(1) struct still copies with alignment 1.
16108da to
fe10226
Compare
|
Lol! Fable just went and did this all on its own... I had no input here! It determined that an issue was LDC, and then decided that the best resolution was to patch LDC, then it fetched and built LDC with its patch, tested it, and now here we are! I only saw the link to this PR in its progress summary. That said, I actually think this is legit, but I can't comment at all on the merit of its fix. |
|
Also, I know we only just released like, a couple of days ago... but if you choose to merge this, a point-release would be REALLY appreciated, otherwise I'll need to maintain my own compiler binaries for the whole next development cycle... which particularly sucks when it's also pulled by Github CI workers. |
if you wanted to verify this, compare this to what clang does. I have no objections to this PR, but will wait until after dconf to merge it because I'm busy and brain is still jet lagged. |
|
Claude said that this is exactly what Clang does, that was his key evidence that this was the right thing to do when I interrogated him. |
You might have noticed that CI is red, there's nothing to merge yet. Feel free to merge dcompute PRs (preferably only touching the dcompute parts), and approve of other PRs, but please leave merging these other PRs to Johan and me; I want to keep a certain degree of quality. That said, the changes here look good at first glance, except for CI and the changelog; I don't consider this a bugfix, nor worthy of a changelog entry. We should probably revise all memcpys and enable the nowadays 2 separate alignments for dst/src at one point. A variable can have its own alignment, overriding the type's; that would probably need to be handled too and might be the cause for the CI failures (for the compiler itself). |
You will also note that the CI traces fail in the frontend and this is very clearly a IR gen change. I'm not quite sure why those targets fail, but it is clearly unrelated to this. Perhaps from the recent DMD version update? |
|
Clearly unrelated to this?! This is the new compiler having compiled itself and then crashing when compiling the std.stdio unittests. So it looks as if the frontend itself contains problematic stuff that fails with these changes. |
|
Please take ownership of this PR, if it needs amendment or another approach. It looks straightforward enough, but like you said, I wouldn't be at all surprised if it misses detail that someone who actually knows the compiler would know about! This makes a huge difference to the final binary though, I've built my code with this patch and it's seriously better codegen. |
DtoAssigncopies structs throughDtoMemCpy(DtoType(lhs->type), dst, src), which uses the helper's default alignment of 1. Struct literal initialisation (getInitSymbol()copy and the zero-init path) and struct zero-assignment do the same. Every struct copy therefore reaches LLVM as anllvm.memcpy/llvm.memsetwithalign 1, and LLVM has to treat it as potentially unaligned.On targets that can't do unaligned access this is costly: with
-mtriple=armv5te-none-eabi -mattr=+strict-align, each small struct copy is lowered to a run ofldrb/strb(orstore i64 ..., align 1after SROA, which lowers the same way). Example, appending a plainstruct { uint; long; delegate }to an array:versus five
strs with the alignment known. On a ~1 MB embedded image (OpenWatt, LDC 1.43.0,-Oz) this accounted for roughly 12 KB of text, about 60% of the whole strict-align penalty.This PR passes
DtoAlignment(type)at those sites. That is the same alignment LDC already uses for the type's allocas and globals, so no new assumption is introduced: analign(1)struct still copies with alignment 1, and analign(16)struct now says 16.Before / after for the added test:
Not touched here: array slice copies (
arrays.cpp), tuple element copies andva_copy, which go through the untyped helper or don't have the D type at hand.