forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
81f0f5a0e5
commit
85cfd91723
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -747,6 +747,12 @@ inline uint64_t alignTo(uint64_t Value, uint64_t Align) {
|
|||
return (Value + Align - 1) / Align * Align;
|
||||
}
|
||||
|
||||
inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
|
||||
assert(Align != 0 && (Align & Align - 1) == 0 &&
|
||||
"Align must be a power of 2");
|
||||
return (Value + Align - 1) & -Align;
|
||||
}
|
||||
|
||||
/// If non-zero \p Skew is specified, the return value will be a minimal integer
|
||||
/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
|
||||
/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
|
||||
|
|
Loading…
Reference in New Issue