aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2022-07-24 11:20:49 -0700
committerFangrui Song <i@maskray.me>2022-07-24 11:20:49 -0700
commit85cfd917231c14757f01f4be66c1bbd10fb933d0 (patch)
treee345630e9094621a87b66579f4644ee01c792126 /lld
parent81f0f5a0e57c99c77dcf7e005cb38fcf807bada0 (diff)
downloadllvm-85cfd917231c14757f01f4be66c1bbd10fb933d0.zip
llvm-85cfd917231c14757f01f4be66c1bbd10fb933d0.tar.gz
llvm-85cfd917231c14757f01f4be66c1bbd10fb933d0.tar.bz2
[ELF] Optimize some non-constant alignTo with alignToPowerOf2. NFC
My x86-64 lld executable is 2KiB smaller. .eh_frame writing gets faster as there were lots of divisions.
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Driver.cpp8
-rw-r--r--lld/ELF/LinkerScript.cpp12
-rw-r--r--lld/ELF/ScriptParser.cpp7
-rw-r--r--lld/ELF/SyntheticSections.cpp12
-rw-r--r--lld/ELF/Writer.cpp30
-rw-r--r--lld/test/ELF/linkerscript/operators.test2
6 files changed, 39 insertions, 32 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index dd17adc..30534f7 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1691,8 +1691,10 @@ void LinkerDriver::inferMachineType() {
static uint64_t getMaxPageSize(opt::InputArgList &args) {
uint64_t val = args::getZOptionValue(args, OPT_z, "max-page-size",
target->defaultMaxPageSize);
- if (!isPowerOf2_64(val))
+ if (!isPowerOf2_64(val)) {
error("max-page-size: value isn't a power of 2");
+ return target->defaultMaxPageSize;
+ }
if (config->nmagic || config->omagic) {
if (val != target->defaultMaxPageSize)
warn("-z max-page-size set, but paging disabled by omagic or nmagic");
@@ -1706,8 +1708,10 @@ static uint64_t getMaxPageSize(opt::InputArgList &args) {
static uint64_t getCommonPageSize(opt::InputArgList &args) {
uint64_t val = args::getZOptionValue(args, OPT_z, "common-page-size",
target->defaultCommonPageSize);
- if (!isPowerOf2_64(val))
+ if (!isPowerOf2_64(val)) {
error("common-page-size: value isn't a power of 2");
+ return target->defaultCommonPageSize;
+ }
if (config->nmagic || config->omagic) {
if (val != target->defaultCommonPageSize)
warn("-z common-page-size set, but paging disabled by omagic or nmagic");
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 3be4290..9f30117c 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -112,9 +112,9 @@ static StringRef getOutputSectionName(const InputSectionBase *s) {
uint64_t ExprValue::getValue() const {
if (sec)
- return alignTo(sec->getOutputSection()->addr + sec->getOffset(val),
- alignment);
- return alignTo(val, alignment);
+ return alignToPowerOf2(sec->getOutputSection()->addr + sec->getOffset(val),
+ alignment);
+ return alignToPowerOf2(val, alignment);
}
uint64_t ExprValue::getSecAddr() const {
@@ -989,7 +989,7 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
// sec->alignment is the max of ALIGN and the maximum of input
// section alignments.
const uint64_t pos = dot;
- dot = alignTo(dot, sec->alignment);
+ dot = alignToPowerOf2(dot, sec->alignment);
sec->addr = dot;
expandMemoryRegions(dot - pos);
}
@@ -1003,7 +1003,7 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
if (sec->lmaExpr) {
ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
} else if (MemoryRegion *mr = sec->lmaRegion) {
- uint64_t lmaStart = alignTo(mr->curPos, sec->alignment);
+ uint64_t lmaStart = alignToPowerOf2(mr->curPos, sec->alignment);
if (mr->curPos < lmaStart)
expandMemoryRegion(mr, lmaStart - mr->curPos, sec->name);
ctx->lmaOffset = lmaStart - dot;
@@ -1046,7 +1046,7 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
for (InputSection *isec : cast<InputSectionDescription>(cmd)->sections) {
assert(isec->getParent() == sec);
const uint64_t pos = dot;
- dot = alignTo(dot, isec->alignment);
+ dot = alignToPowerOf2(dot, isec->alignment);
isec->outSecOff = dot - sec->addr;
dot += isec->getSize();
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 4d73541..7fc50b2 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1392,7 +1392,7 @@ Expr ScriptParser::readPrimary() {
Expr e = readExpr();
if (consume(")")) {
e = checkAlignment(e, location);
- return [=] { return alignTo(script->getDot(), e().getValue()); };
+ return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
}
expect(",");
Expr e2 = checkAlignment(readExpr(), location);
@@ -1423,7 +1423,8 @@ Expr ScriptParser::readPrimary() {
expect(")");
seenDataAlign = true;
return [=] {
- return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue()));
+ uint64_t align = std::max(uint64_t(1), e().getValue());
+ return (script->getDot() + align - 1) & -align;
};
}
if (tok == "DATA_SEGMENT_END") {
@@ -1443,7 +1444,7 @@ Expr ScriptParser::readPrimary() {
expect(")");
seenRelroEnd = true;
Expr e = getPageSize();
- return [=] { return alignTo(script->getDot(), e().getValue()); };
+ return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
}
if (tok == "DEFINED") {
StringRef name = unquote(readParenLiteral());
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index a0c5e6d..919afc7 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -498,7 +498,7 @@ void EhFrameSection::iterateFDEWithLSDA(
static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
memcpy(buf, d.data(), d.size());
- size_t aligned = alignTo(d.size(), config->wordsize);
+ size_t aligned = alignToPowerOf2(d.size(), config->wordsize);
assert(std::all_of(buf + d.size(), buf + aligned,
[](uint8_t c) { return c == 0; }));
@@ -533,11 +533,11 @@ void EhFrameSection::finalizeContents() {
size_t off = 0;
for (CieRecord *rec : cieRecords) {
rec->cie->outputOff = off;
- off += alignTo(rec->cie->size, config->wordsize);
+ off += alignToPowerOf2(rec->cie->size, config->wordsize);
for (EhSectionPiece *fde : rec->fdes) {
fde->outputOff = off;
- off += alignTo(fde->size, config->wordsize);
+ off += alignToPowerOf2(fde->size, config->wordsize);
}
}
@@ -919,7 +919,7 @@ void MipsGotSection::build() {
for (SectionCommand *cmd : os->commands) {
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
for (InputSection *isec : isd->sections) {
- uint64_t off = alignTo(secSize, isec->alignment);
+ uint64_t off = alignToPowerOf2(secSize, isec->alignment);
secSize = off + isec->getSize();
}
}
@@ -3330,7 +3330,7 @@ void MergeNoTailSection::finalizeContents() {
for (size_t i = 0; i < numShards; ++i) {
shards[i].finalizeInOrder();
if (shards[i].getSize() > 0)
- off = alignTo(off, alignment);
+ off = alignToPowerOf2(off, alignment);
shardOffsets[i] = off;
off += shards[i].getSize();
}
@@ -3612,7 +3612,7 @@ InputSection *ThunkSection::getTargetInputSection() const {
bool ThunkSection::assignOffsets() {
uint64_t off = 0;
for (Thunk *t : thunks) {
- off = alignTo(off, t->alignment);
+ off = alignToPowerOf2(off, t->alignment);
t->setOffset(off);
uint32_t size = t->size();
t->getThunkTargetSym()->size = size;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 2994e79..c9345d8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2483,7 +2483,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
(prev->p_flags & PF_X) != (p->p_flags & PF_X)) ||
cmd->type == SHT_LLVM_PART_EHDR)
cmd->addrExpr = [] {
- return alignTo(script->getDot(), config->maxPageSize);
+ return alignToPowerOf2(script->getDot(), config->maxPageSize);
};
// PT_TLS is at the start of the first RW PT_LOAD. If `p` includes PT_TLS,
// it must be the RW. Align to p_align(PT_TLS) to make sure
@@ -2500,13 +2500,13 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// blocks correctly. We need to keep the workaround for a while.
else if (Out::tlsPhdr && Out::tlsPhdr->firstSec == p->firstSec)
cmd->addrExpr = [] {
- return alignTo(script->getDot(), config->maxPageSize) +
- alignTo(script->getDot() % config->maxPageSize,
- Out::tlsPhdr->p_align);
+ return alignToPowerOf2(script->getDot(), config->maxPageSize) +
+ alignToPowerOf2(script->getDot() % config->maxPageSize,
+ Out::tlsPhdr->p_align);
};
else
cmd->addrExpr = [] {
- return alignTo(script->getDot(), config->maxPageSize) +
+ return alignToPowerOf2(script->getDot(), config->maxPageSize) +
script->getDot() % config->maxPageSize;
};
}
@@ -2540,7 +2540,7 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
// If the section is not in a PT_LOAD, we just have to align it.
if (!os->ptLoad)
- return alignTo(off, os->alignment);
+ return alignToPowerOf2(off, os->alignment);
// If two sections share the same PT_LOAD the file offset is calculated
// using this formula: Off2 = Off1 + (VA2 - VA1).
@@ -2599,15 +2599,15 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
// following section to avoid loading non-segments parts of the file.
if (config->zSeparate != SeparateSegmentKind::None && lastRX &&
lastRX->lastSec == sec)
- off = alignTo(off, config->maxPageSize);
+ off = alignToPowerOf2(off, config->maxPageSize);
}
for (OutputSection *osec : outputSections)
if (!(osec->flags & SHF_ALLOC)) {
- osec->offset = alignTo(off, osec->alignment);
+ osec->offset = alignToPowerOf2(off, osec->alignment);
off = osec->offset + osec->size;
}
- sectionHeaderOff = alignTo(off, config->wordsize);
+ sectionHeaderOff = alignToPowerOf2(off, config->wordsize);
fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr);
// Our logic assumes that sections have rising VA within the same segment.
@@ -2659,8 +2659,9 @@ template <class ELFT> void Writer<ELFT>::setPhdrs(Partition &part) {
// musl/glibc ld.so rounds the size down, so we need to round up
// to protect the last page. This is a no-op on FreeBSD which always
// rounds up.
- p->p_memsz = alignTo(p->p_offset + p->p_memsz, config->commonPageSize) -
- p->p_offset;
+ p->p_memsz =
+ alignToPowerOf2(p->p_offset + p->p_memsz, config->commonPageSize) -
+ p->p_offset;
}
}
}
@@ -2880,8 +2881,9 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
if (p->p_type == PT_LOAD && (p->p_flags & PF_X))
fillTrap(Out::bufferStart +
alignDown(p->firstSec->offset + p->p_filesz, 4),
- Out::bufferStart + alignTo(p->firstSec->offset + p->p_filesz,
- config->maxPageSize));
+ Out::bufferStart +
+ alignToPowerOf2(p->firstSec->offset + p->p_filesz,
+ config->maxPageSize));
// Round up the file size of the last segment to the page boundary iff it is
// an executable segment to ensure that other tools don't accidentally
@@ -2893,7 +2895,7 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
if (last && (last->p_flags & PF_X))
last->p_memsz = last->p_filesz =
- alignTo(last->p_filesz, config->maxPageSize);
+ alignToPowerOf2(last->p_filesz, config->maxPageSize);
}
}
diff --git a/lld/test/ELF/linkerscript/operators.test b/lld/test/ELF/linkerscript/operators.test
index 5fb73c6..3958b95 100644
--- a/lld/test/ELF/linkerscript/operators.test
+++ b/lld/test/ELF/linkerscript/operators.test
@@ -100,7 +100,7 @@ SECTIONS {
# CHECK-NEXT: 0000000000000009 A precedence2
# CHECK-NEXT: 0000000000001000 A maxpagesize
# CHECK-NEXT: 0000000000001000 A commonpagesize
-# CHECK-NEXT: 000000000000ffff A datasegmentalign
+# CHECK-NEXT: 0000000000010000 A datasegmentalign
# CHECK-NEXT: 000000000000fff0 A datasegmentalign2
# CHECK-NEXT: 000000000000ffe0 T minus_rel
# CHECK-NEXT: 000000000000fff0 A minus_abs