Skip to content

Commit 69b7785

Browse files
iclsrcjsji
authored andcommitted
Merge from 'main' to 'sycl-web' (80 commits)
CONFLICT (content): Merge conflict in clang/lib/AST/ExprConstant.cpp
2 parents 982018e + 9e3bbbb commit 69b7785

File tree

335 files changed

+28401
-5176
lines changed

Some content is hidden

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

335 files changed

+28401
-5176
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class BinaryContext {
190190
/// Unique build ID if available for the binary.
191191
std::optional<std::string> FileBuildID;
192192

193+
/// GNU property note indicating AArch64 BTI.
194+
bool UsesBTI{false};
195+
193196
/// Set of all sections.
194197
struct CompareSections {
195198
bool operator()(const BinarySection *A, const BinarySection *B) const {
@@ -384,6 +387,9 @@ class BinaryContext {
384387
}
385388
void setFileBuildID(StringRef ID) { FileBuildID = std::string(ID); }
386389

390+
bool usesBTI() const { return UsesBTI; }
391+
void setUsesBTI(bool Value) { UsesBTI = Value; }
392+
387393
bool hasSymbolsWithFileName() const { return HasSymbolsWithFileName; }
388394
void setHasSymbolsWithFileName(bool Value) { HasSymbolsWithFileName = Value; }
389395

bolt/include/bolt/Passes/SplitFunctions.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,6 @@
1818
namespace llvm {
1919
namespace bolt {
2020

21-
/// Strategy used to partition blocks into fragments.
22-
enum SplitFunctionsStrategy : char {
23-
/// Split each function into a hot and cold fragment using profiling
24-
/// information.
25-
Profile2 = 0,
26-
/// Split each function into a hot, warm, and cold fragment using
27-
/// profiling information.
28-
CDSplit,
29-
/// Split each function into a hot and cold fragment at a randomly chosen
30-
/// split point (ignoring any available profiling information).
31-
Random2,
32-
/// Split each function into N fragments at a randomly chosen split points
33-
/// (ignoring any available profiling information).
34-
RandomN,
35-
/// Split all basic blocks of each function into fragments such that each
36-
/// fragment contains exactly a single basic block.
37-
All
38-
};
39-
4021
class SplitStrategy {
4122
public:
4223
using BlockIt = BinaryFunction::BasicBlockOrderType::iterator;

bolt/include/bolt/Rewrite/MetadataRewriters.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ std::unique_ptr<MetadataRewriter> createPseudoProbeRewriter(BinaryContext &);
2727

2828
std::unique_ptr<MetadataRewriter> createSDTRewriter(BinaryContext &);
2929

30+
std::unique_ptr<MetadataRewriter> createGNUPropertyRewriter(BinaryContext &);
31+
3032
} // namespace bolt
3133
} // namespace llvm
3234

bolt/include/bolt/Utils/CommandLineOpts.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ enum HeatmapModeKind {
2929
HM_Optional // perf2bolt --heatmap
3030
};
3131

32+
/// Strategy used to partition blocks into fragments.
33+
enum SplitFunctionsStrategy : char {
34+
/// Split each function into a hot and cold fragment using profiling
35+
/// information.
36+
Profile2 = 0,
37+
/// Split each function into a hot, warm, and cold fragment using
38+
/// profiling information.
39+
CDSplit,
40+
/// Split each function into a hot and cold fragment at a randomly chosen
41+
/// split point (ignoring any available profiling information).
42+
Random2,
43+
/// Split each function into N fragments at a randomly chosen split points
44+
/// (ignoring any available profiling information).
45+
RandomN,
46+
/// Split all basic blocks of each function into fragments such that each
47+
/// fragment contains exactly a single basic block.
48+
All
49+
};
50+
3251
using HeatmapBlockSizes = std::vector<unsigned>;
3352
struct HeatmapBlockSpecParser : public llvm::cl::parser<HeatmapBlockSizes> {
3453
explicit HeatmapBlockSpecParser(llvm::cl::Option &O)
@@ -78,6 +97,7 @@ extern llvm::cl::opt<std::string> OutputFilename;
7897
extern llvm::cl::opt<std::string> PerfData;
7998
extern llvm::cl::opt<bool> PrintCacheMetrics;
8099
extern llvm::cl::opt<bool> PrintSections;
100+
extern llvm::cl::opt<SplitFunctionsStrategy> SplitStrategy;
81101

82102
// The format to use with -o in aggregation mode (perf2bolt)
83103
enum ProfileFormatKind { PF_Fdata, PF_YAML };

bolt/lib/Passes/LongJmp.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,10 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {
895895

896896
Error LongJmpPass::runOnFunctions(BinaryContext &BC) {
897897

898+
assert((opts::CompactCodeModel ||
899+
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit) &&
900+
"LongJmp cannot work with functions split in more than two fragments");
901+
898902
if (opts::CompactCodeModel) {
899903
BC.outs()
900904
<< "BOLT-INFO: relaxing branches for compact code model (<128MB)\n";

bolt/lib/Passes/SplitFunctions.cpp

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,6 @@ static cl::opt<unsigned> SplitThreshold(
8686
"increase after splitting."),
8787
cl::init(0), cl::Hidden, cl::cat(BoltOptCategory));
8888

89-
static cl::opt<SplitFunctionsStrategy> SplitStrategy(
90-
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
91-
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
92-
"split each function into a hot and cold fragment "
93-
"using profiling information")),
94-
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
95-
"split each function into a hot, warm, and cold "
96-
"fragment using profiling information")),
97-
cl::values(clEnumValN(
98-
SplitFunctionsStrategy::Random2, "random2",
99-
"split each function into a hot and cold fragment at a randomly chosen "
100-
"split point (ignoring any available profiling information)")),
101-
cl::values(clEnumValN(
102-
SplitFunctionsStrategy::RandomN, "randomN",
103-
"split each function into N fragments at a randomly chosen split "
104-
"points (ignoring any available profiling information)")),
105-
cl::values(clEnumValN(
106-
SplitFunctionsStrategy::All, "all",
107-
"split all basic blocks of each function into fragments such that each "
108-
"fragment contains exactly a single basic block")),
109-
cl::desc("strategy used to partition blocks into fragments"),
110-
cl::cat(BoltOptCategory));
111-
11289
static cl::opt<double> CallScale(
11390
"call-scale",
11491
cl::desc("Call score scale coefficient (when --split-strategy=cdsplit)"),
@@ -724,14 +701,14 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
724701
// If split strategy is not CDSplit, then a second run of the pass is not
725702
// needed after function reordering.
726703
if (BC.HasFinalizedFunctionOrder &&
727-
opts::SplitStrategy != SplitFunctionsStrategy::CDSplit)
704+
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit)
728705
return Error::success();
729706

730707
std::unique_ptr<SplitStrategy> Strategy;
731708
bool ForceSequential = false;
732709

733710
switch (opts::SplitStrategy) {
734-
case SplitFunctionsStrategy::CDSplit:
711+
case opts::SplitFunctionsStrategy::CDSplit:
735712
// CDSplit runs two splitting passes: hot-cold splitting (SplitPrfoile2)
736713
// before function reordering and hot-warm-cold splitting
737714
// (SplitCacheDirected) after function reordering.
@@ -742,21 +719,21 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
742719
opts::AggressiveSplitting = true;
743720
BC.HasWarmSection = true;
744721
break;
745-
case SplitFunctionsStrategy::Profile2:
722+
case opts::SplitFunctionsStrategy::Profile2:
746723
Strategy = std::make_unique<SplitProfile2>();
747724
break;
748-
case SplitFunctionsStrategy::Random2:
725+
case opts::SplitFunctionsStrategy::Random2:
749726
Strategy = std::make_unique<SplitRandom2>();
750727
// If we split functions randomly, we need to ensure that across runs with
751728
// the same input, we generate random numbers for each function in the same
752729
// order.
753730
ForceSequential = true;
754731
break;
755-
case SplitFunctionsStrategy::RandomN:
732+
case opts::SplitFunctionsStrategy::RandomN:
756733
Strategy = std::make_unique<SplitRandomN>();
757734
ForceSequential = true;
758735
break;
759-
case SplitFunctionsStrategy::All:
736+
case opts::SplitFunctionsStrategy::All:
760737
Strategy = std::make_unique<SplitAll>();
761738
break;
762739
}

bolt/lib/Rewrite/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ add_llvm_library(LLVMBOLTRewrite
2525
PseudoProbeRewriter.cpp
2626
RewriteInstance.cpp
2727
SDTRewriter.cpp
28+
GNUPropertyRewriter.cpp
2829

2930
NO_EXPORT
3031
DISABLE_LLVM_LINK_LLVM_DYLIB
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//===- bolt/Rewrite/GNUPropertyRewriter.cpp -------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Read the .note.gnu.property section.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "bolt/Rewrite/MetadataRewriter.h"
14+
#include "bolt/Rewrite/MetadataRewriters.h"
15+
#include "llvm/Support/Errc.h"
16+
17+
using namespace llvm;
18+
using namespace bolt;
19+
20+
namespace {
21+
22+
class GNUPropertyRewriter final : public MetadataRewriter {
23+
24+
Expected<uint32_t> decodeGNUPropertyNote(StringRef Desc);
25+
26+
public:
27+
GNUPropertyRewriter(StringRef Name, BinaryContext &BC)
28+
: MetadataRewriter(Name, BC) {}
29+
30+
Error sectionInitializer() override;
31+
};
32+
33+
Error GNUPropertyRewriter::sectionInitializer() {
34+
35+
ErrorOr<BinarySection &> Sec =
36+
BC.getUniqueSectionByName(".note.gnu.property");
37+
if (!Sec)
38+
return Error::success();
39+
40+
// Accumulate feature bits
41+
uint32_t FeaturesAcc = 0;
42+
43+
StringRef Buf = Sec->getContents();
44+
DataExtractor DE(Buf, BC.AsmInfo->isLittleEndian(),
45+
BC.AsmInfo->getCodePointerSize());
46+
DataExtractor::Cursor Cursor(0);
47+
while (Cursor && !DE.eof(Cursor)) {
48+
const uint32_t NameSz = DE.getU32(Cursor);
49+
const uint32_t DescSz = DE.getU32(Cursor);
50+
const uint32_t Type = DE.getU32(Cursor);
51+
52+
StringRef Name =
53+
NameSz ? Buf.slice(Cursor.tell(), Cursor.tell() + NameSz) : "<empty>";
54+
Cursor.seek(alignTo(Cursor.tell() + NameSz, 4));
55+
56+
const uint64_t DescOffset = Cursor.tell();
57+
StringRef Desc =
58+
DescSz ? Buf.slice(DescOffset, DescOffset + DescSz) : "<empty>";
59+
Cursor.seek(alignTo(DescOffset + DescSz, 4));
60+
if (!Cursor)
61+
return createStringError(
62+
errc::executable_format_error,
63+
"out of bounds while reading .note.gnu.property section: %s",
64+
toString(Cursor.takeError()).c_str());
65+
66+
if (Type == ELF::NT_GNU_PROPERTY_TYPE_0 && Name.starts_with("GNU") &&
67+
DescSz) {
68+
auto Features = decodeGNUPropertyNote(Desc);
69+
if (!Features)
70+
return Features.takeError();
71+
FeaturesAcc |= *Features;
72+
}
73+
}
74+
75+
if (BC.isAArch64()) {
76+
BC.setUsesBTI(FeaturesAcc & llvm::ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
77+
if (BC.usesBTI())
78+
BC.outs() << "BOLT-WARNING: binary is using BTI. Optimized binary may be "
79+
"corrupted\n";
80+
}
81+
82+
return Error::success();
83+
}
84+
85+
/// \p Desc contains an array of property descriptors. Each member has the
86+
/// following structure:
87+
/// typedef struct {
88+
/// Elf_Word pr_type;
89+
/// Elf_Word pr_datasz;
90+
/// unsigned char pr_data[PR_DATASZ];
91+
/// unsigned char pr_padding[PR_PADDING];
92+
/// } Elf_Prop;
93+
///
94+
/// As there is no guarantee that the features are encoded in which element of
95+
/// the array, we have to read all, and OR together the result.
96+
Expected<uint32_t> GNUPropertyRewriter::decodeGNUPropertyNote(StringRef Desc) {
97+
DataExtractor DE(Desc, BC.AsmInfo->isLittleEndian(),
98+
BC.AsmInfo->getCodePointerSize());
99+
DataExtractor::Cursor Cursor(0);
100+
const uint32_t Align = DE.getAddressSize();
101+
102+
std::optional<uint32_t> Features = 0;
103+
while (Cursor && !DE.eof(Cursor)) {
104+
const uint32_t PrType = DE.getU32(Cursor);
105+
const uint32_t PrDataSz = DE.getU32(Cursor);
106+
107+
const uint64_t PrDataStart = Cursor.tell();
108+
const uint64_t PrDataEnd = PrDataStart + PrDataSz;
109+
Cursor.seek(PrDataEnd);
110+
if (!Cursor)
111+
return createStringError(
112+
errc::executable_format_error,
113+
"out of bounds while reading .note.gnu.property section: %s",
114+
toString(Cursor.takeError()).c_str());
115+
116+
if (PrType == llvm::ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
117+
if (PrDataSz != 4) {
118+
return createStringError(
119+
errc::executable_format_error,
120+
"Property descriptor size has to be 4 bytes on AArch64\n");
121+
}
122+
DataExtractor::Cursor Tmp(PrDataStart);
123+
// PrDataSz = 4 -> PrData is uint32_t
124+
const uint32_t FeaturesItem = DE.getU32(Tmp);
125+
if (!Tmp)
126+
return createStringError(
127+
errc::executable_format_error,
128+
"failed to read property from .note.gnu.property section: %s",
129+
toString(Tmp.takeError()).c_str());
130+
Features = Features ? (*Features | FeaturesItem) : FeaturesItem;
131+
}
132+
133+
Cursor.seek(alignTo(PrDataEnd, Align));
134+
if (!Cursor)
135+
return createStringError(errc::executable_format_error,
136+
"out of bounds while reading property array in "
137+
".note.gnu.property section: %s",
138+
toString(Cursor.takeError()).c_str());
139+
}
140+
return Features.value_or(0u);
141+
}
142+
} // namespace
143+
144+
std::unique_ptr<MetadataRewriter>
145+
llvm::bolt::createGNUPropertyRewriter(BinaryContext &BC) {
146+
return std::make_unique<GNUPropertyRewriter>("gnu-property-rewriter", BC);
147+
}

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,13 @@ void RewriteInstance::adjustCommandLineOptions() {
21152115
opts::SplitEH = false;
21162116
}
21172117

2118+
if (BC->isAArch64() && !opts::CompactCodeModel &&
2119+
opts::SplitStrategy == opts::SplitFunctionsStrategy::CDSplit) {
2120+
BC->errs() << "BOLT-ERROR: CDSplit is not supported with LongJmp. Try with "
2121+
"'--compact-code-model'\n";
2122+
exit(1);
2123+
}
2124+
21182125
if (opts::StrictMode && !BC->HasRelocations) {
21192126
BC->errs()
21202127
<< "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
@@ -3331,6 +3338,8 @@ void RewriteInstance::initializeMetadataManager() {
33313338
MetadataManager.registerRewriter(createPseudoProbeRewriter(*BC));
33323339

33333340
MetadataManager.registerRewriter(createSDTRewriter(*BC));
3341+
3342+
MetadataManager.registerRewriter(createGNUPropertyRewriter(*BC));
33343343
}
33353344

33363345
void RewriteInstance::processSectionMetadata() {

bolt/lib/Utils/CommandLineOpts.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,29 @@ ExecutionCountThreshold("execution-count-threshold",
104104
cl::Hidden,
105105
cl::cat(BoltOptCategory));
106106

107+
cl::opt<SplitFunctionsStrategy> SplitStrategy(
108+
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
109+
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
110+
"split each function into a hot and cold fragment "
111+
"using profiling information")),
112+
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
113+
"split each function into a hot, warm, and cold "
114+
"fragment using profiling information")),
115+
cl::values(clEnumValN(
116+
SplitFunctionsStrategy::Random2, "random2",
117+
"split each function into a hot and cold fragment at a randomly chosen "
118+
"split point (ignoring any available profiling information)")),
119+
cl::values(clEnumValN(
120+
SplitFunctionsStrategy::RandomN, "randomN",
121+
"split each function into N fragments at a randomly chosen split "
122+
"points (ignoring any available profiling information)")),
123+
cl::values(clEnumValN(
124+
SplitFunctionsStrategy::All, "all",
125+
"split all basic blocks of each function into fragments such that each "
126+
"fragment contains exactly a single basic block")),
127+
cl::desc("strategy used to partition blocks into fragments"),
128+
cl::cat(BoltOptCategory));
129+
107130
bool HeatmapBlockSpecParser::parse(cl::Option &O, StringRef ArgName,
108131
StringRef Arg, HeatmapBlockSizes &Val) {
109132
// Parses a human-readable suffix into a shift amount or nullopt on error.

0 commit comments

Comments
 (0)