Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f8c34d1
[clang][Driver][HIP] Change OffloadingActionBuilder to respect the --…
MixedMatched Oct 2, 2025
1ddc8ed
[mlir][vector] Simplify op rewrite pattern inheriting constructors. N…
kuhar Oct 2, 2025
dadcbae
[NFC][IR2Vec] Moving `parseVocabSection()` to `VocabStorage` (#161711)
svkeerthy Oct 2, 2025
b5ce27a
[X86][AMX] Combine constant zero vector and AMX cast to tilezero (#92…
phoebewang Oct 3, 2025
d0ffd7b
[orc-rt] Add CallableTraitsHelper, refactor WrapperFunction to use it…
lhames Oct 3, 2025
0e0400b
[orc-rt] Refactor WrapperFunction to simplify Serializer classes. (#1…
lhames Oct 3, 2025
fbb8c01
[clang] fix lambda dependency issue with late parse attributes (#161765)
mizvekov Oct 3, 2025
811c31e
[orc-rt] Add transparent SPS conversion for error/expected types. (#1…
lhames Oct 3, 2025
cce2624
[RISCV][GISel] Use relaxed_load/store in GISel atomic patterns. NFC (…
topperc Oct 3, 2025
cdf6914
[clang] fix #161765 test triple dependency (#161769)
mizvekov Oct 3, 2025
be2e77b
[flang] use specialized scan/verify version for char (#161767)
c8ef Oct 3, 2025
d78d2c8
[JITLink] Add LinkGraph name / triple to debugging output. (#161772)
lhames Oct 3, 2025
fe74f4d
[Clang] Ensure initialized NTTP expressions when building CTAD for ty…
zyn0217 Oct 3, 2025
f403e83
[X86] combineBitcastvxi1 - bail out on soft-float targets (#161704)
RKSimon Oct 3, 2025
4aebd1c
[ARM] shouldFoldMaskToVariableShiftPair should be true for scalars up…
AZero13 Oct 3, 2025
b5519e2
[AMDGPU] Define VS_128*. NFCI (#161798)
rampitec Oct 3, 2025
7fe92b9
[Clang] Normalize constraints before checking for satisfaction (#161671)
cor3ntin Oct 3, 2025
2589f1a
[llvm-jitlink] Use MachOObjectFile::getArchTriple for triple identifi…
lhames Oct 3, 2025
a368bd6
[BOLT] Add GNUPropertyRewriter and warn on AArch64 BTI note (#161206)
bgergely0 Oct 3, 2025
c054155
[gn build] Port 441f0c7c9a5e
llvmgnsyncbot Oct 3, 2025
5bb6fca
[AMDGPU] Account for implicit XCNT insertion (#160812)
easyonaadit Oct 3, 2025
0fafc77
[BOLT][AArch64] Refuse to run CDSplit pass (#159351)
paschalis-mpeis Oct 3, 2025
32982d7
[VPlan] Deref VPlanPtr when passing to transform (NFC) (#161369)
artagnon Oct 3, 2025
f33a6c1
[llvm][ELF]Add Shdr check for getBuildID (#126537)
cabbaken Oct 3, 2025
1d77c39
[AArch64] Refactor and refine cost-model for partial reductions (#158…
sdesmalen-arm Oct 3, 2025
027dca8
[flang][debug] Avoid redundant module info. (#161542)
abidh Oct 3, 2025
76c1d77
[gn build] Port 5cd3db3bed62
llvmgnsyncbot Oct 3, 2025
ebc8759
[X86][GlobalIsel] Enable gisel run for fpclass isel (#160741)
mahesh-attarde Oct 3, 2025
070db94
[X86][GlobalIsel] Adds support for G_UMIN/G_UMAX/G_SMIN/G_SMAX (#161783)
mahesh-attarde Oct 3, 2025
a30662e
[GVN] Teach GVN simple masked load/store forwarding (#157689)
MDevereau Oct 3, 2025
f86f20a
[AArch64][SME] Enable `aarch64-split-sve-objects` with hazard padding…
MacDue Oct 3, 2025
328168e
[MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in Elemen…
joker-eph Aug 21, 2025
12e1ccd
[MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in mlir-r…
joker-eph Aug 21, 2025
baf526b
[MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in PassGe…
joker-eph Aug 21, 2025
c734d4f
[MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in Rewrit…
joker-eph Aug 21, 2025
fcbe7e0
[NFC][AMDGPU] Replace size & set_is_subset by operator== (#161813)
jmmartinez Oct 3, 2025
de9d76a
Revert "[PATCH] offload-tunnel-cmake with proper escape" (#161727)
ronlieb Oct 3, 2025
23f6cbc
[NFC][LLVM][IR] Fix namespace usage in several files (#161756)
jurahul Oct 3, 2025
30dc524
AMDGPU: Remove dead code trying to constrain a physical register (#16…
arsenm Oct 3, 2025
b37f477
AMDGPU: Stop trying to constrain register class of post-RA-pseudos (#…
arsenm Oct 3, 2025
7c9fb95
AMDGPU: Fix trying to constrain physical registers in spill handling …
arsenm Oct 3, 2025
05d92f3
AMDGPU: Fix constrain register logic for physregs (#161794)
arsenm Oct 3, 2025
5254af8
CodeGen: Stop checking for physregs in constrainRegClass (#161795)
arsenm Oct 3, 2025
9d19885
[SPARC] Prevent meta instructions from being inserted into delay slot…
koachan Oct 3, 2025
fbdbfe1
[clang] [Headers] Don't use unreserved names in avx10_2bf16intrin.h (…
mstorsjo Oct 3, 2025
dd1bcab
[OpenACC][CIR] Impl reduction recipe pointer/array bound lowering (#1…
erichkeane Oct 3, 2025
f8af3a5
[flang] Simplify hlfir.index in a few limited cases. (#161558)
valerydmit Oct 3, 2025
15033b7
[mlir][NFC] Remove redundant insertion point changes (#161837)
zero9178 Oct 3, 2025
88d5195
[X86][Clang] VectorExprEvaluator::VisitCallExpr / InterpretBuiltin - …
AdityaC4 Oct 3, 2025
736cd61
[analyzer][NFC] Simplify Analysis/csv2json.py (#161665)
steakhal Oct 3, 2025
dde8f01
[AMDGPU][Disassembler] Use target feature for `.amdhsa_reserve_xnack_…
shiltian Oct 3, 2025
0582216
[LLVM] Add GNU make jobserver support (#145131)
yxsamliu Oct 3, 2025
7a11947
Allow DW_OP_rot, DW_OP_neg, and DW_OP_abs in DIExpression (#160757)
tromey Oct 3, 2025
18308ea
[LAA] Check if Ptr can be freed between Assume and CtxI. (#161725)
fhahn Oct 3, 2025
f63153a
[Flang] Add standalone tile support (#160298)
Meinersbur Oct 3, 2025
0835bed
[X86] Fold ADD(x,x) -> X86ISD::VSHLI(x,1) (#161843)
RKSimon Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bolt/include/bolt/Core/BinaryContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ class BinaryContext {
/// Unique build ID if available for the binary.
std::optional<std::string> FileBuildID;

/// GNU property note indicating AArch64 BTI.
bool UsesBTI{false};

/// Set of all sections.
struct CompareSections {
bool operator()(const BinarySection *A, const BinarySection *B) const {
Expand Down Expand Up @@ -384,6 +387,9 @@ class BinaryContext {
}
void setFileBuildID(StringRef ID) { FileBuildID = std::string(ID); }

bool usesBTI() const { return UsesBTI; }
void setUsesBTI(bool Value) { UsesBTI = Value; }

bool hasSymbolsWithFileName() const { return HasSymbolsWithFileName; }
void setHasSymbolsWithFileName(bool Value) { HasSymbolsWithFileName = Value; }

Expand Down
19 changes: 0 additions & 19 deletions bolt/include/bolt/Passes/SplitFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,6 @@
namespace llvm {
namespace bolt {

/// Strategy used to partition blocks into fragments.
enum SplitFunctionsStrategy : char {
/// Split each function into a hot and cold fragment using profiling
/// information.
Profile2 = 0,
/// Split each function into a hot, warm, and cold fragment using
/// profiling information.
CDSplit,
/// Split each function into a hot and cold fragment at a randomly chosen
/// split point (ignoring any available profiling information).
Random2,
/// Split each function into N fragments at a randomly chosen split points
/// (ignoring any available profiling information).
RandomN,
/// Split all basic blocks of each function into fragments such that each
/// fragment contains exactly a single basic block.
All
};

class SplitStrategy {
public:
using BlockIt = BinaryFunction::BasicBlockOrderType::iterator;
Expand Down
2 changes: 2 additions & 0 deletions bolt/include/bolt/Rewrite/MetadataRewriters.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ std::unique_ptr<MetadataRewriter> createPseudoProbeRewriter(BinaryContext &);

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

std::unique_ptr<MetadataRewriter> createGNUPropertyRewriter(BinaryContext &);

} // namespace bolt
} // namespace llvm

Expand Down
20 changes: 20 additions & 0 deletions bolt/include/bolt/Utils/CommandLineOpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ enum HeatmapModeKind {
HM_Optional // perf2bolt --heatmap
};

/// Strategy used to partition blocks into fragments.
enum SplitFunctionsStrategy : char {
/// Split each function into a hot and cold fragment using profiling
/// information.
Profile2 = 0,
/// Split each function into a hot, warm, and cold fragment using
/// profiling information.
CDSplit,
/// Split each function into a hot and cold fragment at a randomly chosen
/// split point (ignoring any available profiling information).
Random2,
/// Split each function into N fragments at a randomly chosen split points
/// (ignoring any available profiling information).
RandomN,
/// Split all basic blocks of each function into fragments such that each
/// fragment contains exactly a single basic block.
All
};

using HeatmapBlockSizes = std::vector<unsigned>;
struct HeatmapBlockSpecParser : public llvm::cl::parser<HeatmapBlockSizes> {
explicit HeatmapBlockSpecParser(llvm::cl::Option &O)
Expand Down Expand Up @@ -78,6 +97,7 @@ extern llvm::cl::opt<std::string> OutputFilename;
extern llvm::cl::opt<std::string> PerfData;
extern llvm::cl::opt<bool> PrintCacheMetrics;
extern llvm::cl::opt<bool> PrintSections;
extern llvm::cl::opt<SplitFunctionsStrategy> SplitStrategy;

// The format to use with -o in aggregation mode (perf2bolt)
enum ProfileFormatKind { PF_Fdata, PF_YAML };
Expand Down
4 changes: 4 additions & 0 deletions bolt/lib/Passes/LongJmp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,10 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {

Error LongJmpPass::runOnFunctions(BinaryContext &BC) {

assert((opts::CompactCodeModel ||
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit) &&
"LongJmp cannot work with functions split in more than two fragments");

if (opts::CompactCodeModel) {
BC.outs()
<< "BOLT-INFO: relaxing branches for compact code model (<128MB)\n";
Expand Down
35 changes: 6 additions & 29 deletions bolt/lib/Passes/SplitFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,6 @@ static cl::opt<unsigned> SplitThreshold(
"increase after splitting."),
cl::init(0), cl::Hidden, cl::cat(BoltOptCategory));

static cl::opt<SplitFunctionsStrategy> SplitStrategy(
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
"split each function into a hot and cold fragment "
"using profiling information")),
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
"split each function into a hot, warm, and cold "
"fragment using profiling information")),
cl::values(clEnumValN(
SplitFunctionsStrategy::Random2, "random2",
"split each function into a hot and cold fragment at a randomly chosen "
"split point (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::RandomN, "randomN",
"split each function into N fragments at a randomly chosen split "
"points (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::All, "all",
"split all basic blocks of each function into fragments such that each "
"fragment contains exactly a single basic block")),
cl::desc("strategy used to partition blocks into fragments"),
cl::cat(BoltOptCategory));

static cl::opt<double> CallScale(
"call-scale",
cl::desc("Call score scale coefficient (when --split-strategy=cdsplit)"),
Expand Down Expand Up @@ -724,14 +701,14 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
// If split strategy is not CDSplit, then a second run of the pass is not
// needed after function reordering.
if (BC.HasFinalizedFunctionOrder &&
opts::SplitStrategy != SplitFunctionsStrategy::CDSplit)
opts::SplitStrategy != opts::SplitFunctionsStrategy::CDSplit)
return Error::success();

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

switch (opts::SplitStrategy) {
case SplitFunctionsStrategy::CDSplit:
case opts::SplitFunctionsStrategy::CDSplit:
// CDSplit runs two splitting passes: hot-cold splitting (SplitPrfoile2)
// before function reordering and hot-warm-cold splitting
// (SplitCacheDirected) after function reordering.
Expand All @@ -742,21 +719,21 @@ Error SplitFunctions::runOnFunctions(BinaryContext &BC) {
opts::AggressiveSplitting = true;
BC.HasWarmSection = true;
break;
case SplitFunctionsStrategy::Profile2:
case opts::SplitFunctionsStrategy::Profile2:
Strategy = std::make_unique<SplitProfile2>();
break;
case SplitFunctionsStrategy::Random2:
case opts::SplitFunctionsStrategy::Random2:
Strategy = std::make_unique<SplitRandom2>();
// If we split functions randomly, we need to ensure that across runs with
// the same input, we generate random numbers for each function in the same
// order.
ForceSequential = true;
break;
case SplitFunctionsStrategy::RandomN:
case opts::SplitFunctionsStrategy::RandomN:
Strategy = std::make_unique<SplitRandomN>();
ForceSequential = true;
break;
case SplitFunctionsStrategy::All:
case opts::SplitFunctionsStrategy::All:
Strategy = std::make_unique<SplitAll>();
break;
}
Expand Down
1 change: 1 addition & 0 deletions bolt/lib/Rewrite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_llvm_library(LLVMBOLTRewrite
PseudoProbeRewriter.cpp
RewriteInstance.cpp
SDTRewriter.cpp
GNUPropertyRewriter.cpp

NO_EXPORT
DISABLE_LLVM_LINK_LLVM_DYLIB
Expand Down
147 changes: 147 additions & 0 deletions bolt/lib/Rewrite/GNUPropertyRewriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
//===- bolt/Rewrite/GNUPropertyRewriter.cpp -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Read the .note.gnu.property section.
//
//===----------------------------------------------------------------------===//

#include "bolt/Rewrite/MetadataRewriter.h"
#include "bolt/Rewrite/MetadataRewriters.h"
#include "llvm/Support/Errc.h"

using namespace llvm;
using namespace bolt;

namespace {

class GNUPropertyRewriter final : public MetadataRewriter {

Expected<uint32_t> decodeGNUPropertyNote(StringRef Desc);

public:
GNUPropertyRewriter(StringRef Name, BinaryContext &BC)
: MetadataRewriter(Name, BC) {}

Error sectionInitializer() override;
};

Error GNUPropertyRewriter::sectionInitializer() {

ErrorOr<BinarySection &> Sec =
BC.getUniqueSectionByName(".note.gnu.property");
if (!Sec)
return Error::success();

// Accumulate feature bits
uint32_t FeaturesAcc = 0;

StringRef Buf = Sec->getContents();
DataExtractor DE(Buf, BC.AsmInfo->isLittleEndian(),
BC.AsmInfo->getCodePointerSize());
DataExtractor::Cursor Cursor(0);
while (Cursor && !DE.eof(Cursor)) {
const uint32_t NameSz = DE.getU32(Cursor);
const uint32_t DescSz = DE.getU32(Cursor);
const uint32_t Type = DE.getU32(Cursor);

StringRef Name =
NameSz ? Buf.slice(Cursor.tell(), Cursor.tell() + NameSz) : "<empty>";
Cursor.seek(alignTo(Cursor.tell() + NameSz, 4));

const uint64_t DescOffset = Cursor.tell();
StringRef Desc =
DescSz ? Buf.slice(DescOffset, DescOffset + DescSz) : "<empty>";
Cursor.seek(alignTo(DescOffset + DescSz, 4));
if (!Cursor)
return createStringError(
errc::executable_format_error,
"out of bounds while reading .note.gnu.property section: %s",
toString(Cursor.takeError()).c_str());

if (Type == ELF::NT_GNU_PROPERTY_TYPE_0 && Name.starts_with("GNU") &&
DescSz) {
auto Features = decodeGNUPropertyNote(Desc);
if (!Features)
return Features.takeError();
FeaturesAcc |= *Features;
}
}

if (BC.isAArch64()) {
BC.setUsesBTI(FeaturesAcc & llvm::ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
if (BC.usesBTI())
BC.outs() << "BOLT-WARNING: binary is using BTI. Optimized binary may be "
"corrupted\n";
}

return Error::success();
}

/// \p Desc contains an array of property descriptors. Each member has the
/// following structure:
/// typedef struct {
/// Elf_Word pr_type;
/// Elf_Word pr_datasz;
/// unsigned char pr_data[PR_DATASZ];
/// unsigned char pr_padding[PR_PADDING];
/// } Elf_Prop;
///
/// As there is no guarantee that the features are encoded in which element of
/// the array, we have to read all, and OR together the result.
Expected<uint32_t> GNUPropertyRewriter::decodeGNUPropertyNote(StringRef Desc) {
DataExtractor DE(Desc, BC.AsmInfo->isLittleEndian(),
BC.AsmInfo->getCodePointerSize());
DataExtractor::Cursor Cursor(0);
const uint32_t Align = DE.getAddressSize();

std::optional<uint32_t> Features = 0;
while (Cursor && !DE.eof(Cursor)) {
const uint32_t PrType = DE.getU32(Cursor);
const uint32_t PrDataSz = DE.getU32(Cursor);

const uint64_t PrDataStart = Cursor.tell();
const uint64_t PrDataEnd = PrDataStart + PrDataSz;
Cursor.seek(PrDataEnd);
if (!Cursor)
return createStringError(
errc::executable_format_error,
"out of bounds while reading .note.gnu.property section: %s",
toString(Cursor.takeError()).c_str());

if (PrType == llvm::ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
if (PrDataSz != 4) {
return createStringError(
errc::executable_format_error,
"Property descriptor size has to be 4 bytes on AArch64\n");
}
DataExtractor::Cursor Tmp(PrDataStart);
// PrDataSz = 4 -> PrData is uint32_t
const uint32_t FeaturesItem = DE.getU32(Tmp);
if (!Tmp)
return createStringError(
errc::executable_format_error,
"failed to read property from .note.gnu.property section: %s",
toString(Tmp.takeError()).c_str());
Features = Features ? (*Features | FeaturesItem) : FeaturesItem;
}

Cursor.seek(alignTo(PrDataEnd, Align));
if (!Cursor)
return createStringError(errc::executable_format_error,
"out of bounds while reading property array in "
".note.gnu.property section: %s",
toString(Cursor.takeError()).c_str());
}
return Features.value_or(0u);
}
} // namespace

std::unique_ptr<MetadataRewriter>
llvm::bolt::createGNUPropertyRewriter(BinaryContext &BC) {
return std::make_unique<GNUPropertyRewriter>("gnu-property-rewriter", BC);
}
9 changes: 9 additions & 0 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2115,6 +2115,13 @@ void RewriteInstance::adjustCommandLineOptions() {
opts::SplitEH = false;
}

if (BC->isAArch64() && !opts::CompactCodeModel &&
opts::SplitStrategy == opts::SplitFunctionsStrategy::CDSplit) {
BC->errs() << "BOLT-ERROR: CDSplit is not supported with LongJmp. Try with "
"'--compact-code-model'\n";
exit(1);
}

if (opts::StrictMode && !BC->HasRelocations) {
BC->errs()
<< "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
Expand Down Expand Up @@ -3331,6 +3338,8 @@ void RewriteInstance::initializeMetadataManager() {
MetadataManager.registerRewriter(createPseudoProbeRewriter(*BC));

MetadataManager.registerRewriter(createSDTRewriter(*BC));

MetadataManager.registerRewriter(createGNUPropertyRewriter(*BC));
}

void RewriteInstance::processSectionMetadata() {
Expand Down
23 changes: 23 additions & 0 deletions bolt/lib/Utils/CommandLineOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,29 @@ ExecutionCountThreshold("execution-count-threshold",
cl::Hidden,
cl::cat(BoltOptCategory));

cl::opt<SplitFunctionsStrategy> SplitStrategy(
"split-strategy", cl::init(SplitFunctionsStrategy::Profile2),
cl::values(clEnumValN(SplitFunctionsStrategy::Profile2, "profile2",
"split each function into a hot and cold fragment "
"using profiling information")),
cl::values(clEnumValN(SplitFunctionsStrategy::CDSplit, "cdsplit",
"split each function into a hot, warm, and cold "
"fragment using profiling information")),
cl::values(clEnumValN(
SplitFunctionsStrategy::Random2, "random2",
"split each function into a hot and cold fragment at a randomly chosen "
"split point (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::RandomN, "randomN",
"split each function into N fragments at a randomly chosen split "
"points (ignoring any available profiling information)")),
cl::values(clEnumValN(
SplitFunctionsStrategy::All, "all",
"split all basic blocks of each function into fragments such that each "
"fragment contains exactly a single basic block")),
cl::desc("strategy used to partition blocks into fragments"),
cl::cat(BoltOptCategory));

bool HeatmapBlockSpecParser::parse(cl::Option &O, StringRef ArgName,
StringRef Arg, HeatmapBlockSizes &Val) {
// Parses a human-readable suffix into a shift amount or nullopt on error.
Expand Down
Loading