This is an archive of the discontinued LLVM Phabricator instance.

[lld][Alignment][NFC] Use Align instead of log2 of alignment in Wasm Sections
ClosedPublic

Authored by gchatelet on Dec 2 2022, 2:14 AM.

Details

Summary

I intend to slowly upgrade all alignments to the Align type in lld as well.
Some places talk about alignment in Bytes while other specify them as Log2(Bytes).
Let's make sure all of this is coherent.

Diff Detail

Event Timeline

gchatelet created this revision.Dec 2 2022, 2:14 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 2 2022, 2:14 AM
gchatelet requested review of this revision.Dec 2 2022, 2:14 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 2 2022, 2:14 AM
courbet accepted this revision.Dec 2 2022, 2:57 AM
This revision is now accepted and ready to land.Dec 2 2022, 2:57 AM
gchatelet updated this revision to Diff 479601.Dec 2 2022, 4:48 AM
  • rebase and reformat
This revision was landed with ongoing or failed builds.Dec 2 2022, 4:56 AM
This revision was automatically updated to reflect the committed changes.
arichardson added inline comments.
lld/wasm/InputChunks.h
88

Reordering the fields would reduce padding.

lld/wasm/OutputSegment.h
41

Same here

sbc100 added inline comments.Dec 2 2022, 8:30 AM
lld/wasm/InputChunks.h
112

It would be nice if there was a way to explicitly construct an llvm::Align from a p2align constant such as this? fromP2Align?

lld/wasm/OutputSegment.cpp
28

How about we skip the Log2 here and write p2align= in the log message just to be explict?

61

ditto

lld/wasm/Writer.cpp
291

Can we use Align for the memAlign member here too?

gchatelet added inline comments.Dec 2 2022, 9:02 AM
lld/wasm/InputChunks.h
112

We could, by making LogValue public here.
I was reluctant to do so because of the lack of use cases but it seems to be a thing in the linker.

lld/wasm/OutputSegment.cpp
28

wait, I thought p2align was the log2 of alignment?
So either "align=" << align or "p2_align=" << Log2(align).

Let me know if I misunderstood.

lld/wasm/Writer.cpp
291

Yes, I intend to fix it all but it needs to be incremental otherwise it's hard to review. Same for the Ditto above, it will be converted once SyntheticMergedChunk takes an Align.

sbc100 added inline comments.Dec 2 2022, 9:31 AM
lld/wasm/OutputSegment.cpp
28

At yes sorry. I think it would be more clear if the log message said p2align=.. but since your change didn't effect that we don't need to make that change here. Sorry for the noise.

MaskRay added a comment.EditedDec 2 2022, 10:15 AM

Drive-by: llvm::Align probably won't improve lld/ELF (and the extra dependency llvm/Support/Alignment.h and MathExtras.h is somewhat unnecessary). I've checked using p2align for lld::elf::Symbol, but I think it won't decrease the struct size and will likely lead to no less code size in most call sites.

Drive-by: llvm::Align probably won't improve lld/ELF (and the extra dependency llvm/Support/Alignment.h and MathExtras.h is somewhat unnecessary). I've checked using p2align for lld::elf::Symbol, but I think it won't decrease the struct size and will likely lead to no less code size in most call sites.

Thx @MaskRay. I think I should have started by explaining the rationale here. My apologies for that.

The main reason for this change is not code size nor performance (although it can help a bit) but making sure the semantic is correct.
In lld alignment is specified as uint8_t, uint32_t, or uint64_t. Sometimes it refers to the p2align semantic, sometimes it refers to powers of two alignments with no clear explanation of what the 0 value is for (could be : "consider 0 as a 1", "0 is forbidden", "0 => no alignment requirements, 1 => align to 1", "0 is a sentinel for the value not being set yet").
It also removes the need to check invariants, since they hold by definition.

 % git grep isPowerOf2_  
COFF/Chunks.cpp:  assert(isPowerOf2_32(c->getAlignment()));
COFF/Chunks.h:    assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");

Introducing this type makes sure we can consistently reason about the value. I understand that this comes at the cost of additional dependencies and probably increased compile time, but it already caught bugs (from the RFC, this one a few days ago) so I think it has value.
Even if there are no bugs today, the type helps when refactoring as the semantic is well defined.

Let me know what you think before I continue working on this. Meanwhile I'm putting D138778, D139205, D139206 on hold.

Drive-by: llvm::Align probably won't improve lld/ELF (and the extra dependency llvm/Support/Alignment.h and MathExtras.h is somewhat unnecessary). I've checked using p2align for lld::elf::Symbol, but I think it won't decrease the struct size and will likely lead to no less code size in most call sites.

Thx @MaskRay. I think I should have started by explaining the rationale here. My apologies for that.

The main reason for this change is not code size nor performance (although it can help a bit) but making sure the semantic is correct.
In lld alignment is specified as uint8_t, uint32_t, or uint64_t. Sometimes it refers to the p2align semantic, sometimes it refers to powers of two alignments with no clear explanation of what the 0 value is for (could be : "consider 0 as a 1", "0 is forbidden", "0 => no alignment requirements, 1 => align to 1", "0 is a sentinel for the value not being set yet").
It also removes the need to check invariants, since they hold by definition.

 % git grep isPowerOf2_  
COFF/Chunks.cpp:  assert(isPowerOf2_32(c->getAlignment()));
COFF/Chunks.h:    assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");

Introducing this type makes sure we can consistently reason about the value. I understand that this comes at the cost of additional dependencies and probably increased compile time, but it already caught bugs (from the RFC, this one a few days ago) so I think it has value.
Even if there are no bugs today, the type helps when refactoring as the semantic is well defined.

Let me know what you think before I continue working on this. Meanwhile I'm putting D138778, D139205, D139206 on hold.

llvm/ uses of alignment are very different from lld/ uses of alignment. lld/{COFF,ELF,wasm,MachO} are all different.
They are just different implementations put into one directory. One port preferring alignment and another preferring p2align doesn't imply inconsistency in the code base.

lld/COFF uses p2Align, so using llvm::Align may make sense.
For ELF, I think using llvm::Align will just lead to more log2 or pow2 operations and more conversions into integral types, and makes us lose the ability to preserve 0 in case of relocatable links.

Drive-by: llvm::Align probably won't improve lld/ELF (and the extra dependency llvm/Support/Alignment.h and MathExtras.h is somewhat unnecessary). I've checked using p2align for lld::elf::Symbol, but I think it won't decrease the struct size and will likely lead to no less code size in most call sites.

Thx @MaskRay. I think I should have started by explaining the rationale here. My apologies for that.

The main reason for this change is not code size nor performance (although it can help a bit) but making sure the semantic is correct.
In lld alignment is specified as uint8_t, uint32_t, or uint64_t. Sometimes it refers to the p2align semantic, sometimes it refers to powers of two alignments with no clear explanation of what the 0 value is for (could be : "consider 0 as a 1", "0 is forbidden", "0 => no alignment requirements, 1 => align to 1", "0 is a sentinel for the value not being set yet").
It also removes the need to check invariants, since they hold by definition.

 % git grep isPowerOf2_  
COFF/Chunks.cpp:  assert(isPowerOf2_32(c->getAlignment()));
COFF/Chunks.h:    assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");

Introducing this type makes sure we can consistently reason about the value. I understand that this comes at the cost of additional dependencies and probably increased compile time, but it already caught bugs (from the RFC, this one a few days ago) so I think it has value.
Even if there are no bugs today, the type helps when refactoring as the semantic is well defined.

Let me know what you think before I continue working on this. Meanwhile I'm putting D138778, D139205, D139206 on hold.

llvm/ uses of alignment are very different from lld/ uses of alignment. lld/{COFF,ELF,wasm,MachO} are all different.
They are just different implementations put into one directory. One port preferring alignment and another preferring p2align doesn't imply inconsistency in the code base.

lld/COFF uses p2Align, so using llvm::Align may make sense.
For ELF, I think using llvm::Align will just lead to more log2 or pow2 operations and more conversions into integral types, and makes us lose the ability to preserve 0 in case of relocatable links.

I've reverted the patches since they don't seem to provide much benefit. Would you also want me to revert this one?

MaskRay added a comment.EditedDec 19 2022, 11:42 AM

Thanks! I think @sbc100 will decide. From my look of these call sites, the number of Log2 call sites makes me feel that llvm::Align is probably not a good fit for lld/wasm as well.

Thanks! I think @sbc100 will decide. From my look of these call sites, the number of Log2 call sites makes me feel that llvm::Align is probably not a good fit for lld/wasm as well.

I tend to agree. I also tend to think we should either use this in all linkers on none.

Thanks! I think @sbc100 will decide. From my look of these call sites, the number of Log2 call sites makes me feel that llvm::Align is probably not a good fit for lld/wasm as well.

Sounds good, I'll revert then.
Note that Log2 is a noop though.