-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[BOLT][AArch64] Refuse to run CDSplit pass #159351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BOLT][AArch64] Refuse to run CDSplit pass #159351
Conversation
LongJmp does not support warm blocks. On builds without assertions, this may lead to unexpected crashes. This patch exits with a clear message.
@llvm/pr-subscribers-bolt Author: Paschalis Mpeis (paschalis-mpeis) ChangesLongJmp does not support warm blocks. This patch exits with a clear message. Full diff: https://github.com/llvm/llvm-project/pull/159351.diff 6 Files Affected:
diff --git a/bolt/include/bolt/Passes/SplitFunctions.h b/bolt/include/bolt/Passes/SplitFunctions.h
index 8bdc48b68eb7a..2c1bf1890cd97 100644
--- a/bolt/include/bolt/Passes/SplitFunctions.h
+++ b/bolt/include/bolt/Passes/SplitFunctions.h
@@ -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;
diff --git a/bolt/include/bolt/Utils/CommandLineOpts.h b/bolt/include/bolt/Utils/CommandLineOpts.h
index 859d6f3bf6774..0964c2c9d8473 100644
--- a/bolt/include/bolt/Utils/CommandLineOpts.h
+++ b/bolt/include/bolt/Utils/CommandLineOpts.h
@@ -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)
@@ -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 };
diff --git a/bolt/lib/Passes/LongJmp.cpp b/bolt/lib/Passes/LongJmp.cpp
index 4dade161cc232..e62cbe4e6d9d5 100644
--- a/bolt/lib/Passes/LongJmp.cpp
+++ b/bolt/lib/Passes/LongJmp.cpp
@@ -894,6 +894,10 @@ void LongJmpPass::relaxLocalBranches(BinaryFunction &BF) {
}
Error LongJmpPass::runOnFunctions(BinaryContext &BC) {
+ if (opts::SplitStrategy == opts::SplitFunctionsStrategy::CDSplit) {
+ BC.errs() << "BOLT-ERROR: CDSplit is not supported on AArch64\n";
+ exit(1);
+ }
if (opts::CompactCodeModel) {
BC.outs()
diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp
index b21401e069bfa..37243c5f3c7a1 100644
--- a/bolt/lib/Passes/SplitFunctions.cpp
+++ b/bolt/lib/Passes/SplitFunctions.cpp
@@ -85,29 +85,7 @@ static cl::opt<unsigned> SplitThreshold(
"size is reduced. Note that on some architectures the size can "
"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",
@@ -724,14 +702,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.
@@ -742,21 +720,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;
}
diff --git a/bolt/lib/Utils/CommandLineOpts.cpp b/bolt/lib/Utils/CommandLineOpts.cpp
index 5635da476451d..095612ac3a4ac 100644
--- a/bolt/lib/Utils/CommandLineOpts.cpp
+++ b/bolt/lib/Utils/CommandLineOpts.cpp
@@ -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.
diff --git a/bolt/test/AArch64/unsupported-passes.test b/bolt/test/AArch64/unsupported-passes.test
index 886fc1c574dcf..f70c4d42e2929 100644
--- a/bolt/test/AArch64/unsupported-passes.test
+++ b/bolt/test/AArch64/unsupported-passes.test
@@ -3,6 +3,10 @@
// REQUIRES: system-linux,asserts,target=aarch64{{.*}}
RUN: %clang %cflags %p/../Inputs/hello.c -o %t -Wl,-q
-RUN: not llvm-bolt %t -o %t.bolt --frame-opt=all 2>&1 | FileCheck %s
+RUN: not llvm-bolt %t -o %t.bolt --frame-opt=all 2>&1 | FileCheck %s --check-prefix=CHECK-FRAME-OPT
-CHECK: BOLT-ERROR: frame-optimizer is supported only on X86
+CHECK-FRAME-OPT: BOLT-ERROR: frame-optimizer is supported only on X86
+
+RUN: not llvm-bolt %t -o %t.bolt split-functions --split-strategy=cdsplit 2>&1 | FileCheck %s --check-prefix=CHECK-CDSPLIT
+
+CHECK-CDSPLIT: BOLT-ERROR: CDSplit is not supported on AArch64
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Hey folks, LongJmp does not work with CDSplit. To support it we need to extend the stub groups. If preferable, I could split the refactoring, moving SplitStrategy flags to another PR. There are more passes/functions unsupported, but at least on AArch64 it would prevent some unexpected errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@paschalis-mpeis, we should allow to run CDSplit under --compact-code-model
, right?
Yeap, thanks for noticing this. Sent a new patch.
|
Thinking more about it: since it's just the option verification, it makes sense to run it (and report to the user) as early as possible. I'd say either in |
That's even better, thanks for the suggsetion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
LongJmp does not support warm blocks. On builds without assertions, this may lead to unexpected crashes. This patch exits with a clear message.
LongJmp does not support warm blocks.
On builds without assertions, this may lead to unexpected crashes.
This patch exits with a clear message.