Skip to content

Commit a94c3ed

Browse files
authored
Merge branch 'main' into strong-siv-overflow-2
2 parents f372751 + 831e79a commit a94c3ed

File tree

443 files changed

+41185
-5450
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

443 files changed

+41185
-5450
lines changed

bolt/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ Once you have `perf.fdata` ready, you can use it for optimizations with
173173
BOLT. Assuming your environment is setup to include the right path, execute
174174
`llvm-bolt`:
175175
```
176-
$ llvm-bolt <executable> -o <executable>.bolt -data=perf.fdata -reorder-blocks=ext-tsp -reorder-functions=hfsort -split-functions -split-all-cold -split-eh -dyno-stats
176+
$ llvm-bolt <executable> -o <executable>.bolt -data=perf.fdata -reorder-blocks=ext-tsp -reorder-functions=cdsort -split-functions -split-all-cold -split-eh -dyno-stats
177177
```
178178

179179
If you do need an updated debug info, then add `-update-debug-sections` option

bolt/docs/CommandLineArgumentReference.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,6 @@
381381

382382
Set verbosity level for diagnostic output
383383

384-
- `--write-dwp`
385-
386-
Output a single dwarf package file (dwp) instead of multiple non-relocatable
387-
dwarf object files (dwo).
388-
389384
### BOLT optimization options:
390385

391386
- `--align-blocks`

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,16 @@ class MCPlusBuilder {
840840
return false;
841841
}
842842

843+
virtual bool isLDRWl(const MCInst &Inst) const {
844+
llvm_unreachable("not implemented");
845+
return false;
846+
}
847+
848+
virtual bool isLDRXl(const MCInst &Inst) const {
849+
llvm_unreachable("not implemented");
850+
return false;
851+
}
852+
843853
virtual bool isMOVW(const MCInst &Inst) const {
844854
llvm_unreachable("not implemented");
845855
return false;
@@ -1789,6 +1799,19 @@ class MCPlusBuilder {
17891799
llvm_unreachable("not implemented");
17901800
}
17911801

1802+
/// Take \p LDRInst and return ADRP+LDR instruction sequence - for
1803+
///
1804+
/// ldr x0, [label]
1805+
///
1806+
/// the following sequence will be generated:
1807+
///
1808+
/// adrp x0, PageBase(label)
1809+
/// ldr x0, [x0, PageOffset(label)]
1810+
virtual InstructionListType createAdrpLdr(const MCInst &LDRInst,
1811+
MCContext *Ctx) const {
1812+
llvm_unreachable("not implemented");
1813+
}
1814+
17921815
/// Return not 0 if the instruction CurInst, in combination with the recent
17931816
/// history of disassembled instructions supplied by [Begin, End), is a linker
17941817
/// generated veneer/stub that needs patching. This happens in AArch64 when

bolt/include/bolt/Passes/ADRRelaxationPass.h renamed to bolt/include/bolt/Passes/AArch64RelaxationPass.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
1-
//===- bolt/Passes/ADRRelaxationPass.h --------------------------*- C++ -*-===//
1+
//===- bolt/Passes/AArch64RelaxationPass.h ----------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file declares the ADRRelaxationPass class, which replaces AArch64
10-
// non-local ADR instructions with ADRP + ADD due to small offset range of ADR
11-
// instruction (+- 1MB) which could be easily overflowed after BOLT
12-
// optimizations. Such problems are usually connected with errata 843419
13-
// https://developer.arm.com/documentation/epm048406/2100/
9+
// This file declares the AArch64RelaxationPass class, which replaces AArch64
10+
// non-local ADR/LDR instructions with ADRP + ADD/LDR due to small offset
11+
// range of ADR and LDR instruction (+- 1MB) which could be easily overflowed
12+
// after BOLT optimizations. Such problems are usually connected with errata
13+
// 843419: https://developer.arm.com/documentation/epm048406/2100/
1414
// The linker could replace ADRP instruction with ADR in some cases.
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
#ifndef BOLT_PASSES_ADRRELAXATIONPASS_H
19-
#define BOLT_PASSES_ADRRELAXATIONPASS_H
18+
#ifndef BOLT_PASSES_AARCH64RELAXATIONPASS_H
19+
#define BOLT_PASSES_AARCH64RELAXATIONPASS_H
2020

2121
#include "bolt/Passes/BinaryPasses.h"
2222

2323
namespace llvm {
2424
namespace bolt {
2525

26-
class ADRRelaxationPass : public BinaryFunctionPass {
26+
class AArch64RelaxationPass : public BinaryFunctionPass {
2727
public:
28-
explicit ADRRelaxationPass(const cl::opt<bool> &PrintPass)
28+
explicit AArch64RelaxationPass(const cl::opt<bool> &PrintPass)
2929
: BinaryFunctionPass(PrintPass) {}
3030

31-
const char *getName() const override { return "adr-relaxation"; }
31+
const char *getName() const override { return "aarch64-relaxation"; }
3232

3333
/// Pass entry point
3434
Error runOnFunctions(BinaryContext &BC) override;

bolt/include/bolt/Passes/FixRelaxationPass.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===- bolt/Passes/ADRRelaxationPass.h --------------------------*- C++ -*-===//
1+
//===- bolt/Passes/FixRelaxationPass.h --------------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.

bolt/lib/Core/BinaryContext.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ cl::opt<std::string> CompDirOverride(
7878
"to *.dwo files."),
7979
cl::Hidden, cl::init(""), cl::cat(BoltCategory));
8080

81+
static cl::opt<bool> CloneConstantIsland("clone-constant-island",
82+
cl::desc("clone constant islands"),
83+
cl::Hidden, cl::init(true),
84+
cl::ZeroOrMore, cl::cat(BoltCategory));
85+
8186
static cl::opt<bool>
8287
FailOnInvalidPadding("fail-on-invalid-padding", cl::Hidden, cl::init(false),
8388
cl::desc("treat invalid code padding as error"),
@@ -461,14 +466,21 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
461466
// of dynamic relocs, as we currently do not support cloning them.
462467
// Notice: we might fail to link because of this, if the original constant
463468
// island we are referring would be emitted too far away.
464-
if (IslandIter->second->hasDynamicRelocationAtIsland()) {
469+
if (IslandIter->second->hasDynamicRelocationAtIsland() ||
470+
!opts::CloneConstantIsland) {
465471
MCSymbol *IslandSym =
466472
IslandIter->second->getOrCreateIslandAccess(Address);
467473
if (IslandSym)
468474
return std::make_pair(IslandSym, 0);
469475
} else if (MCSymbol *IslandSym =
470476
IslandIter->second->getOrCreateProxyIslandAccess(Address,
471477
BF)) {
478+
LLVM_DEBUG(
479+
dbgs() << "BOLT-DEBUG: clone constant island at address 0x"
480+
<< Twine::utohexstr(IslandIter->first) << " with size of 0x"
481+
<< Twine::utohexstr(
482+
IslandIter->second->estimateConstantIslandSize())
483+
<< " bytes, referenced by " << BF << "\n");
472484
BF.createIslandDependency(IslandSym, IslandIter->second);
473485
return std::make_pair(IslandSym, 0);
474486
}

bolt/lib/Passes/ADRRelaxationPass.cpp renamed to bolt/lib/Passes/AArch64RelaxationPass.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
//===- bolt/Passes/ADRRelaxationPass.cpp ----------------------------------===//
1+
//===- bolt/Passes/AArch64RelaxationPass.cpp ------------------------------===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
88
//
9-
// This file implements the ADRRelaxationPass class.
9+
// This file implements the AArch64RelaxationPass class.
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "bolt/Passes/ADRRelaxationPass.h"
13+
#include "bolt/Passes/AArch64RelaxationPass.h"
1414
#include "bolt/Core/ParallelUtilities.h"
1515
#include "bolt/Utils/CommandLineOpts.h"
1616
#include <iterator>
@@ -20,10 +20,10 @@ using namespace llvm;
2020
namespace opts {
2121
extern cl::OptionCategory BoltCategory;
2222

23-
static cl::opt<bool>
24-
AdrPassOpt("adr-relaxation",
25-
cl::desc("Replace ARM non-local ADR instructions with ADRP"),
26-
cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden);
23+
static cl::opt<bool> AArch64PassOpt(
24+
"aarch64-relaxation",
25+
cl::desc("Replace ARM non-local ADR/LDR instructions with ADRP"),
26+
cl::init(true), cl::cat(BoltCategory), cl::ReallyHidden);
2727
} // namespace opts
2828

2929
namespace llvm {
@@ -35,18 +35,21 @@ namespace bolt {
3535
// jobs and checking the exit flag after it.
3636
static bool PassFailed = false;
3737

38-
void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
38+
void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
3939
if (PassFailed)
4040
return;
4141

4242
BinaryContext &BC = BF.getBinaryContext();
4343
for (BinaryBasicBlock &BB : BF) {
4444
for (auto It = BB.begin(); It != BB.end(); ++It) {
4545
MCInst &Inst = *It;
46-
if (!BC.MIB->isADR(Inst))
46+
bool IsADR = BC.MIB->isADR(Inst);
47+
48+
// TODO: Handle other types of LDR (literal, PC-relative) instructions.
49+
if (!IsADR && !BC.MIB->isLDRXl(Inst) && !BC.MIB->isLDRWl(Inst))
4750
continue;
4851

49-
const MCSymbol *Symbol = BC.MIB->getTargetSymbol(Inst);
52+
const MCSymbol *Symbol = BC.MIB->getTargetSymbol(Inst, IsADR ? 0 : 1);
5053
if (!Symbol)
5154
continue;
5255

@@ -56,25 +59,27 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
5659
continue;
5760
}
5861

59-
// Don't relax ADR if it points to the same function and is in the main
60-
// fragment and BF initial size is < 1MB.
62+
// Don't relax ADR/LDR if it points to the same function and is in the
63+
// main fragment and BF initial size is < 1MB.
6164
const unsigned OneMB = 0x100000;
6265
if (BF.getSize() < OneMB) {
6366
BinaryFunction *TargetBF = BC.getFunctionForSymbol(Symbol);
6467
if (TargetBF == &BF && !BB.isSplit())
6568
continue;
6669

67-
// No relaxation needed if ADR references a basic block in the same
70+
// No relaxation needed if ADR/LDR references a basic block in the same
6871
// fragment.
6972
if (BinaryBasicBlock *TargetBB = BF.getBasicBlockForLabel(Symbol))
7073
if (BB.getFragmentNum() == TargetBB->getFragmentNum())
7174
continue;
7275
}
7376

74-
InstructionListType AdrpAdd;
77+
InstructionListType AdrpMaterialization;
7578
{
7679
auto L = BC.scopeLock();
77-
AdrpAdd = BC.MIB->undoAdrpAddRelaxation(Inst, BC.Ctx.get());
80+
AdrpMaterialization =
81+
IsADR ? BC.MIB->undoAdrpAddRelaxation(Inst, BC.Ctx.get())
82+
: BC.MIB->createAdrpLdr(Inst, BC.Ctx.get());
7883
}
7984

8085
if (It != BB.begin() && BC.MIB->isNoop(*std::prev(It))) {
@@ -88,18 +93,18 @@ void ADRRelaxationPass::runOnFunction(BinaryFunction &BF) {
8893
// invalidate this offset, so we have to rely on linker-inserted NOP to
8994
// replace it with ADRP, and abort if it is not present.
9095
auto L = BC.scopeLock();
91-
BC.errs() << "BOLT-ERROR: cannot relax ADR in non-simple function "
92-
<< BF << '\n';
96+
BC.errs() << "BOLT-ERROR: cannot relax " << (IsADR ? "ADR" : "LDR")
97+
<< " in non-simple function " << BF << '\n';
9398
PassFailed = true;
9499
return;
95100
}
96-
It = BB.replaceInstruction(It, AdrpAdd);
101+
It = BB.replaceInstruction(It, AdrpMaterialization);
97102
}
98103
}
99104
}
100105

101-
Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
102-
if (!opts::AdrPassOpt || !BC.HasRelocations)
106+
Error AArch64RelaxationPass::runOnFunctions(BinaryContext &BC) {
107+
if (!opts::AArch64PassOpt || !BC.HasRelocations)
103108
return Error::success();
104109

105110
ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
@@ -108,7 +113,7 @@ Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
108113

109114
ParallelUtilities::runOnEachFunction(
110115
BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, nullptr,
111-
"ADRRelaxationPass");
116+
"AArch64RelaxationPass");
112117

113118
if (PassFailed)
114119
return createFatalBOLTError("");

bolt/lib/Passes/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
add_llvm_library(LLVMBOLTPasses
2-
ADRRelaxationPass.cpp
2+
AArch64RelaxationPass.cpp
33
Aligner.cpp
44
AllocCombiner.cpp
55
AsmDump.cpp

bolt/lib/Rewrite/BinaryPassManager.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "bolt/Rewrite/BinaryPassManager.h"
10-
#include "bolt/Passes/ADRRelaxationPass.h"
10+
#include "bolt/Passes/AArch64RelaxationPass.h"
1111
#include "bolt/Passes/Aligner.h"
1212
#include "bolt/Passes/AllocCombiner.h"
1313
#include "bolt/Passes/AsmDump.h"
@@ -129,10 +129,10 @@ static cl::opt<bool> PrintJTFootprintReduction(
129129
cl::desc("print function after jt-footprint-reduction pass"), cl::Hidden,
130130
cl::cat(BoltOptCategory));
131131

132-
static cl::opt<bool>
133-
PrintAdrRelaxation("print-adr-relaxation",
134-
cl::desc("print functions after ADR Relaxation pass"),
135-
cl::Hidden, cl::cat(BoltOptCategory));
132+
static cl::opt<bool> PrintAArch64Relaxation(
133+
"print-adr-ldr-relaxation",
134+
cl::desc("print functions after ADR/LDR Relaxation pass"), cl::Hidden,
135+
cl::cat(BoltOptCategory));
136136

137137
static cl::opt<bool>
138138
PrintLongJmp("print-longjmp",
@@ -517,7 +517,7 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
517517

518518
if (BC.isAArch64()) {
519519
Manager.registerPass(
520-
std::make_unique<ADRRelaxationPass>(PrintAdrRelaxation));
520+
std::make_unique<AArch64RelaxationPass>(PrintAArch64Relaxation));
521521

522522
// Tighten branches according to offset differences between branch and
523523
// targets. No extra instructions after this pass, otherwise we may have

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ static InstructionListType createIncMemory(MCPhysReg RegTo, MCPhysReg RegTmp) {
142142
atomicAdd(Insts.back(), RegTo, RegTmp);
143143
return Insts;
144144
}
145+
145146
class AArch64MCPlusBuilder : public MCPlusBuilder {
146147
public:
147148
using MCPlusBuilder::MCPlusBuilder;
@@ -583,6 +584,14 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
583584
return Inst.getOpcode() == AArch64::ADDXri;
584585
}
585586

587+
bool isLDRWl(const MCInst &Inst) const override {
588+
return Inst.getOpcode() == AArch64::LDRWl;
589+
}
590+
591+
bool isLDRXl(const MCInst &Inst) const override {
592+
return Inst.getOpcode() == AArch64::LDRXl;
593+
}
594+
586595
MCPhysReg getADRReg(const MCInst &Inst) const {
587596
assert((isADR(Inst) || isADRP(Inst)) && "Not an ADR instruction");
588597
assert(MCPlus::getNumPrimeOperands(Inst) != 0 &&
@@ -602,6 +611,39 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
602611
return materializeAddress(Target, Ctx, Reg, Addend);
603612
}
604613

614+
InstructionListType createAdrpLdr(const MCInst &LDRInst,
615+
MCContext *Ctx) const override {
616+
assert((isLDRXl(LDRInst) || isLDRWl(LDRInst)) &&
617+
"LDR (literal, 32 or 64-bit integer load) instruction expected");
618+
assert(LDRInst.getOperand(0).isReg() &&
619+
"unexpected operand in LDR instruction");
620+
const MCPhysReg DataReg = LDRInst.getOperand(0).getReg();
621+
const MCPhysReg AddrReg =
622+
isLDRXl(LDRInst) ? DataReg
623+
: (MCPhysReg)RegInfo->getMatchingSuperReg(
624+
DataReg, AArch64::sub_32,
625+
&RegInfo->getRegClass(AArch64::GPR64RegClassID));
626+
const MCSymbol *Target = getTargetSymbol(LDRInst, 1);
627+
assert(Target && "missing target symbol in LDR instruction");
628+
629+
InstructionListType Insts(2);
630+
Insts[0].setOpcode(AArch64::ADRP);
631+
Insts[0].clear();
632+
Insts[0].addOperand(MCOperand::createReg(AddrReg));
633+
Insts[0].addOperand(MCOperand::createImm(0));
634+
setOperandToSymbolRef(Insts[0], /* OpNum */ 1, Target, 0, Ctx,
635+
ELF::R_AARCH64_NONE);
636+
Insts[1].setOpcode(isLDRXl(LDRInst) ? AArch64::LDRXui : AArch64::LDRWui);
637+
Insts[1].clear();
638+
Insts[1].addOperand(MCOperand::createReg(DataReg));
639+
Insts[1].addOperand(MCOperand::createReg(AddrReg));
640+
Insts[1].addOperand(MCOperand::createImm(0));
641+
Insts[1].addOperand(MCOperand::createImm(0));
642+
setOperandToSymbolRef(Insts[1], /* OpNum */ 2, Target, 0, Ctx,
643+
ELF::R_AARCH64_ADD_ABS_LO12_NC);
644+
return Insts;
645+
}
646+
605647
bool isTB(const MCInst &Inst) const {
606648
return (Inst.getOpcode() == AArch64::TBNZW ||
607649
Inst.getOpcode() == AArch64::TBNZX ||

0 commit comments

Comments
 (0)