[lld] r361206 - [COFF] Store alignment in log2 form, NFC

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon May 20 15:57:52 PDT 2019


Author: rnk
Date: Mon May 20 15:57:52 2019
New Revision: 361206

URL: http://llvm.org/viewvc/llvm-project?rev=361206&view=rev
Log:
[COFF] Store alignment in log2 form, NFC

Summary:
Valid section or chunk alignments are powers of 2 in the range [1,
8192]. These can be stored more canonically in log2 form to free up some
bits in Chunk. Combined with D61696, SectionChunk gets 8 bytes smaller.

Reviewers: ruiu, aganea

Subscribers: llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D61698

Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/ICF.cpp
    lld/trunk/COFF/MapFile.cpp
    lld/trunk/COFF/Writer.cpp

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Mon May 20 15:57:52 2019
@@ -41,7 +41,7 @@ SectionChunk::SectionChunk(ObjFile *F, c
   SectionNameData = SectionName.data();
   SectionNameSize = SectionName.size();
 
-  Alignment = Header->getAlignment();
+  setAlignment(Header->getAlignment());
 
   // If linker GC is disabled, every chunk starts out alive.  If linker GC is
   // enabled, treat non-comdat sections as roots. Generally optimized object
@@ -53,7 +53,7 @@ SectionChunk::SectionChunk(ObjFile *F, c
 // SectionChunk is one of the most frequently allocated classes, so it is
 // important to keep it as compact as possible. As of this writing, the number
 // below is the size of this class on x64 platforms.
-static_assert(sizeof(SectionChunk) <= 112, "SectionChunk grew unexpectedly");
+static_assert(sizeof(SectionChunk) <= 104, "SectionChunk grew unexpectedly");
 
 static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
 static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
@@ -625,7 +625,7 @@ SectionChunk *SectionChunk::findByName(A
 }
 
 void SectionChunk::replace(SectionChunk *Other) {
-  Alignment = std::max(Alignment, Other->Alignment);
+  P2Align = std::max(P2Align, Other->P2Align);
   Other->Repl = Repl;
   Other->Live = false;
 }
@@ -640,7 +640,7 @@ uint32_t SectionChunk::getSectionNumber(
 CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
   // Common symbols are aligned on natural boundaries up to 32 bytes.
   // This is what MSVC link.exe does.
-  Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));
+  setAlignment(std::min(32U, Sym.getValue()));
 }
 
 uint32_t CommonChunk::getOutputCharacteristics() const {
@@ -656,7 +656,7 @@ void StringChunk::writeTo(uint8_t *Buf)
 ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
   // Intel Optimization Manual says that all branch targets
   // should be 16-byte aligned. MSVC linker does this too.
-  Alignment = 16;
+  setAlignment(16);
 }
 
 void ImportThunkChunkX64::writeTo(uint8_t *Buf) const {
@@ -854,17 +854,20 @@ uint8_t Baserel::getDefaultType() {
   }
 }
 
-std::map<uint32_t, MergeChunk *> MergeChunk::Instances;
+MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {};
 
 MergeChunk::MergeChunk(uint32_t Alignment)
     : Builder(StringTableBuilder::RAW, Alignment) {
-  this->Alignment = Alignment;
+  setAlignment(Alignment);
 }
 
 void MergeChunk::addSection(SectionChunk *C) {
-  auto *&MC = Instances[C->Alignment];
+  assert(isPowerOf2_32(C->getAlignment()));
+  uint8_t P2Align = llvm::Log2_32(C->getAlignment());
+  assert(P2Align >= 0 && P2Align < array_lengthof(Instances));
+  auto *&MC = Instances[P2Align];
   if (!MC)
-    MC = make<MergeChunk>(C->Alignment);
+    MC = make<MergeChunk>(C->getAlignment());
   MC->Sections.push_back(C);
 }
 

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Mon May 20 15:57:52 2019
@@ -44,6 +44,9 @@ const uint32_t PermMask = 0xFE000000;
 // Mask for section types (code, data, bss).
 const uint32_t TypeMask = 0x000000E0;
 
+// The log base 2 of the largest section alignment, which is log2(8192), or 13.
+enum : unsigned { Log2MaxSectionAlignment = 13 };
+
 // A Chunk represents a chunk of data that will occupy space in the
 // output (if the resolver chose that). It may or may not be backed by
 // a section of an input file. It could be linker-created data, or
@@ -57,6 +60,18 @@ public:
   // Returns the size of this chunk (even if this is a common or BSS.)
   virtual size_t getSize() const = 0;
 
+  // Returns chunk alignment in power of two form. Value values are powers of
+  // two from 1 to 8192.
+  uint32_t getAlignment() const { return 1U << P2Align; }
+  void setAlignment(uint32_t Align) {
+    // Treat zero byte alignment as 1 byte alignment.
+    Align = Align ? Align : 1;
+    assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2");
+    P2Align = llvm::Log2_32(Align);
+    assert(P2Align <= Log2MaxSectionAlignment &&
+           "impossible requested alignment");
+  }
+
   // Write this chunk to a mmap'ed file, assuming Buf is pointing to
   // beginning of the file. Because this function may use RVA values
   // of other chunks for relocations, you need to set them properly
@@ -103,9 +118,6 @@ public:
   // bytes, so this is used only for logging or debugging.
   virtual StringRef getDebugName() { return ""; }
 
-  // The alignment of this chunk. The writer uses the value.
-  uint32_t Alignment = 1;
-
   virtual bool isHotPatchable() const { return false; }
 
 protected:
@@ -118,6 +130,10 @@ public:
   bool KeepUnique = false;
 
 protected:
+  // The alignment of this chunk, stored in log2 form. The writer uses the
+  // value.
+  uint8_t P2Align = 0;
+
   // The RVA of this chunk in the output. The writer sets a value.
   uint32_t RVA = 0;
 
@@ -313,7 +329,7 @@ public:
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) const override;
 
-  static std::map<uint32_t, MergeChunk *> Instances;
+  static MergeChunk *Instances[Log2MaxSectionAlignment + 1];
   std::vector<SectionChunk *> Sections;
 
 private:
@@ -437,7 +453,7 @@ public:
 class LocalImportChunk : public Chunk {
 public:
   explicit LocalImportChunk(Defined *S) : Sym(S) {
-    Alignment = Config->Wordsize;
+    setAlignment(Config->Wordsize);
   }
   size_t getSize() const override;
   void getBaserels(std::vector<Baserel> *Res) override;
@@ -528,7 +544,7 @@ class PseudoRelocTableChunk : public Chu
 public:
   PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs)
       : Relocs(std::move(Relocs)) {
-    Alignment = 4;
+    setAlignment(4);
   }
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) const override;
@@ -558,7 +574,7 @@ public:
 class AbsolutePointerChunk : public Chunk {
 public:
   AbsolutePointerChunk(uint64_t Value) : Value(Value) {
-    Alignment = getSize();
+    setAlignment(getSize());
   }
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) const override;

Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Mon May 20 15:57:52 2019
@@ -59,7 +59,9 @@ private:
 // A chunk for the import descriptor table.
 class LookupChunk : public Chunk {
 public:
-  explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; }
+  explicit LookupChunk(Chunk *C) : HintName(C) {
+    setAlignment(Config->Wordsize);
+  }
   size_t getSize() const override { return Config->Wordsize; }
 
   void writeTo(uint8_t *Buf) const override {
@@ -78,7 +80,7 @@ public:
 class OrdinalOnlyChunk : public Chunk {
 public:
   explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {
-    Alignment = Config->Wordsize;
+    setAlignment(Config->Wordsize);
   }
   size_t getSize() const override { return Config->Wordsize; }
 
@@ -364,7 +366,7 @@ public:
 class DelayAddressChunk : public Chunk {
 public:
   explicit DelayAddressChunk(Chunk *C) : Thunk(C) {
-    Alignment = Config->Wordsize;
+    setAlignment(Config->Wordsize);
   }
   size_t getSize() const override { return Config->Wordsize; }
 
@@ -576,7 +578,7 @@ void DelayLoadContents::create(Defined *
     for (int I = 0, E = Syms.size(); I < E; ++I)
       Syms[I]->setLocation(Addresses[Base + I]);
     auto *MH = make<NullChunk>(8);
-    MH->Alignment = 8;
+    MH->setAlignment(8);
     ModuleHandles.push_back(MH);
 
     // Fill the delay import table header fields.

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Mon May 20 15:57:52 2019
@@ -1743,7 +1743,7 @@ void LinkerDriver::link(ArrayRef<const c
       continue;
 
     CommonChunk *C = DC->getChunk();
-    C->Alignment = std::max(C->Alignment, Alignment);
+    C->setAlignment(std::max(C->getAlignment(), Alignment));
   }
 
   // Windows specific -- Create a side-by-side manifest file.

Modified: lld/trunk/COFF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/ICF.cpp (original)
+++ lld/trunk/COFF/ICF.cpp Mon May 20 15:57:52 2019
@@ -256,9 +256,10 @@ void ICF::run(ArrayRef<Chunk *> Vec) {
 
   // Make sure that ICF doesn't merge sections that are being handled by string
   // tail merging.
-  for (auto &P : MergeChunk::Instances)
-    for (SectionChunk *SC : P.second->Sections)
-      SC->Class[0] = NextId++;
+  for (MergeChunk *MC : MergeChunk::Instances)
+    if (MC)
+      for (SectionChunk *SC : MC->Sections)
+        SC->Class[0] = NextId++;
 
   // Initially, we use hash values to partition sections.
   parallelForEach(Chunks, [&](SectionChunk *SC) {

Modified: lld/trunk/COFF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MapFile.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/MapFile.cpp (original)
+++ lld/trunk/COFF/MapFile.cpp Mon May 20 15:57:52 2019
@@ -114,7 +114,7 @@ void coff::writeMapFile(ArrayRef<OutputS
       if (!SC)
         continue;
 
-      writeHeader(OS, SC->getRVA(), SC->getSize(), SC->Alignment);
+      writeHeader(OS, SC->getRVA(), SC->getSize(), SC->getAlignment());
       OS << Indent8 << SC->File->getName() << ":(" << SC->getSectionName()
          << ")\n";
       for (DefinedRegular *Sym : SectionSyms[SC])

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=361206&r1=361205&r2=361206&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Mon May 20 15:57:52 2019
@@ -865,8 +865,9 @@ void Writer::createSections() {
 }
 
 void Writer::createMiscChunks() {
-  for (auto &P : MergeChunk::Instances)
-    RdataSec->addChunk(P.second);
+  for (MergeChunk *P : MergeChunk::Instances)
+    if (P)
+      RdataSec->addChunk(P);
 
   // Create thunks for locally-dllimported symbols.
   if (!Symtab->LocalImportChunks.empty()) {
@@ -1159,7 +1160,7 @@ void Writer::assignAddresses() {
     for (Chunk *C : Sec->Chunks) {
       if (Padding && C->isHotPatchable())
         VirtualSize += Padding;
-      VirtualSize = alignTo(VirtualSize, C->Alignment);
+      VirtualSize = alignTo(VirtualSize, C->getAlignment());
       C->setRVA(RVA + VirtualSize);
       C->finalizeContents();
       VirtualSize += C->getSize();
@@ -1519,8 +1520,8 @@ void Writer::createGuardCFTables() {
 
   // Ensure sections referenced in the gfid table are 16-byte aligned.
   for (const ChunkAndOffset &C : AddressTakenSyms)
-    if (C.InputChunk->Alignment < 16)
-      C.InputChunk->Alignment = 16;
+    if (C.InputChunk->getAlignment() < 16)
+      C.InputChunk->setAlignment(16);
 
   maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table",
                    "__guard_fids_count");




More information about the llvm-commits mailing list