[clang] [llvm] BPU Machine basic block placement fuzz (PR #116492)
Dmitriy Sokolov via cfe-commits
cfe-commits at lists.llvm.org
Sat Nov 16 09:02:02 PST 2024
https://github.com/dee-tree created https://github.com/llvm/llvm-project/pull/116492
- Non-optimal machine basic block placement via fuzz option
- machine block frequency inversion under the special option
>From 8376db35a7a7736d78bb7f0febf38203e415b489 Mon Sep 17 00:00:00 2001
From: Arseny Bochkarev <bochkarevarseny at gmail.com>
Date: Wed, 25 Sep 2024 19:59:26 +0300
Subject: [PATCH 1/4] [Fuzz] Add compiler-assisted fuzzer prototype
---
.../clang/Basic/DiagnosticDriverKinds.td | 6 ++
clang/include/clang/Driver/Options.td | 27 +++++++
clang/lib/Driver/ToolChains/Clang.cpp | 71 ++++++++++++++--
llvm/CMakeLists.txt | 1 +
.../llvm/CompilerAssistedFuzzing/FuzzInfo.h | 43 ++++++++++
llvm/lib/CMakeLists.txt | 2 +-
llvm/lib/CodeGen/CMakeLists.txt | 1 +
.../CompilerAssistedFuzzing/CMakeLists.txt | 9 +++
llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp | 81 +++++++++++++++++++
llvm/lib/Support/CMakeLists.txt | 1 +
llvm/lib/Support/Statistic.cpp | 20 ++++-
11 files changed, 255 insertions(+), 7 deletions(-)
create mode 100644 llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
create mode 100644 llvm/lib/CompilerAssistedFuzzing/CMakeLists.txt
create mode 100644 llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 97573fcf20c1fb..f59c0e286e49e9 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -826,6 +826,12 @@ def warn_android_unversioned_fallback : Warning<
def err_drv_triple_version_invalid : Error<
"version '%0' in target triple '%1' is invalid">;
+def err_empty_option_value : Error<
+ "empty value for %0 option">;
+
+def warn_use_fseed : Warning<"Fuzzing with seed: %0">,
+ InGroup<DiagGroup<"fuzzing">>;
+
def warn_missing_include_dirs : Warning<
"no such include directory: '%0'">, InGroup<MissingIncludeDirs>, DefaultIgnore;
}
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 23bd686a85f526..264ebd3541de15 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6730,6 +6730,33 @@ let Flags = [TargetSpecific] in {
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
} // let Flags = [TargetSpecific]
+// Compiler-assisted fuzzing options
+def fuzz_EQ : Joined<["--"], "fuzz=">,
+ Flags<[NoXarchOption, HelpHidden]>, Group<f_Group>,
+ HelpText<"Fuzz selected compiler components, RISC-V only."
+ "Usage: --fuzz=\"<component1>[|<component2>...]\"">,
+ Values<"all, scheduler, mbb-placement, regalloc, isel, alloca">;
+
+def fseed_EQ : Joined<["--"], "fseed=">,
+ Flags<[NoXarchOption, HelpHidden]>, Group<f_Group>,
+ HelpText<"Specify fuzzing seed. (RISC-V only)">;
+
+def fseed_dump : Flag<["-"], "fseed-dump">,
+ Visibility<[ClangOption, CLOption]>,
+ Group<sycl_Group>, HelpText<"Dump fuzz seed. (RISC-V only)">;
+
+def fno_fseed_dump : Flag<["-"], "fno-fseed-dump">,
+ Visibility<[ClangOption, CLOption]>,
+ Group<sycl_Group>, HelpText<"Disable fuzz seed dump. (RISC-V only)">;
+
+def fuzz_stats_dump : Flag<["-"], "fuzz-stats-dump">,
+ Visibility<[ClangOption, CLOption]>,
+ Group<sycl_Group>, HelpText<"Dump only fuzz statistics.">;
+
+def fno_fuzz_stats_dump : Flag<["-"], "fno-fuzz-stats-dump">,
+ Visibility<[ClangOption, CLOption]>,
+ Group<sycl_Group>, HelpText<"Dump not only fuzz statistics.">;
+
//===----------------------------------------------------------------------===//
// FLangOption + NoXarchOption
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 0bab48caf1a5e2..c10cd539942040 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7646,11 +7646,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
- if (!StatsFile.empty()) {
- CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile));
- if (D.CCPrintInternalStats)
- CmdArgs.push_back("-stats-file-append");
- }
+ auto FuzzStatsDump = Args.hasFlag(options::OPT_fuzz_stats_dump,
+ options::OPT_fno_fuzz_stats_dump, false);
+ if (!StatsFile.empty() || FuzzStatsDump) {
+ if (FuzzStatsDump) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-fuzz-only-stats");
+ }
+ if (StatsFile.empty()) {
+ StatsFile.assign(Output.getFilename());
+ llvm::sys::path::replace_extension(StatsFile, "stats");
+ }
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
@@ -8050,6 +8056,61 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Input.getInputArg().renderAsInput(Args, CmdArgs);
}
+ // Handle --fuzz=<fuzz options>
+ StringRef FuzzOptions = Args.getLastArgValue(options::OPT_fuzz_EQ).trim();
+ if (!FuzzOptions.empty()) {
+ auto Tail = FuzzOptions;
+ llvm::SmallVector<StringRef> ActualOpts;
+
+ do {
+ auto Pair = Tail.split('|');
+
+ StringRef Fst = Pair.first.trim();
+ Tail = Pair.second.trim();
+
+ if (!Fst.empty()) {
+ ActualOpts.push_back(Fst);
+ }
+ } while (!Tail.empty());
+
+ if (ActualOpts.empty()) {
+ D.Diag(diag::err_empty_option_value) << "fuzz";
+ }
+
+ llvm::SmallVector<StringRef> CorrectOpts = {
+ "all", "scheduler", "mbb-placement", "regalloc", "isel", "alloca"};
+
+ for (const auto &ActualOpt : ActualOpts)
+ if (llvm::find(CorrectOpts, ActualOpt) == CorrectOpts.end())
+ D.Diag(diag::err_analyzer_checker_option_unknown)
+ << "fuzzer" << ActualOpt;
+
+ // Pass correct arguments to LLVM
+ CmdArgs.push_back("-mllvm");
+ std::string FuzzComponentsArgStr = "-fuzz-components=";
+ const char *FuzzComponentsArg =
+ Args.MakeArgStringRef(FuzzComponentsArgStr + FuzzOptions.data());
+ CmdArgs.push_back(FuzzComponentsArg);
+
+ StringRef FuzzSeedStr = Args.getLastArgValue(options::OPT_fseed_EQ).trim();
+ int64_t SeedValue;
+ if (FuzzSeedStr.empty() ||
+ FuzzSeedStr.getAsInteger<int64_t>(0, SeedValue)) {
+ SeedValue = std::chrono::system_clock::now().time_since_epoch().count();
+ }
+
+ auto StrSeed = std::to_string(SeedValue);
+
+ if (Args.hasFlag(options::OPT_fseed_dump, options::OPT_fno_fseed_dump,
+ false))
+ D.Diag(diag::warn_use_fseed) << StrSeed;
+
+ CmdArgs.push_back("-mllvm");
+ std::string FuzzSeedArgStr = "-fuzz-seed=";
+ const char *FuzzSeedArg = Args.MakeArgStringRef(FuzzSeedArgStr + StrSeed);
+ CmdArgs.push_back(FuzzSeedArg);
+ }
+
if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke the CC1 directly in this process
C.addCommand(std::make_unique<CC1Command>(
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 330db65e85cabb..5bcfc6cac475f4 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -1242,6 +1242,7 @@ endif()
# Put this before tblgen. Else we have a circular dependence.
add_subdirectory(lib/Demangle)
add_subdirectory(lib/Support)
+add_subdirectory(lib/CompilerAssistedFuzzing)
add_subdirectory(lib/TableGen)
add_subdirectory(utils/TableGen)
diff --git a/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h b/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
new file mode 100644
index 00000000000000..9f908d0f64ed86
--- /dev/null
+++ b/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
@@ -0,0 +1,43 @@
+#ifndef LLVM_FUZZINFO_H
+#define LLVM_FUZZINFO_H
+
+#include "llvm/ADT/Statistic.h"
+#include <functional>
+#include <string>
+#include <vector>
+
+namespace fuzz {
+using StatRefWrapper = std::reference_wrapper<llvm::TrackingStatistic>;
+
+class Component final {
+ std::string Name;
+ std::vector<StatRefWrapper> Stats;
+
+public:
+ Component(std::string &&n) noexcept : Name(std::move(n)) {}
+
+ Component &operator=(const Component &) = delete;
+ Component(const Component &) = delete;
+
+ Component &operator=(Component &&) = delete;
+ Component(Component &&) = delete;
+
+ const Component &operator+=(llvm::TrackingStatistic &Stat);
+ const std::string &GetName() const { return Name; }
+ const std::vector<StatRefWrapper> &GetStats() const { return Stats; }
+};
+
+extern Component Scheduler;
+extern Component MBBPlacement;
+extern Component RegAlloc;
+extern Component ISel;
+extern Component Alloca;
+
+bool isFuzzed(fuzz::Component &Comp, llvm::TrackingStatistic &Stat);
+int64_t fuzzedIntRange(fuzz::Component &Comp, llvm::TrackingStatistic &Stat,
+ int64_t Start, int64_t End, int64_t Default);
+
+bool CheckStat(const llvm::TrackingStatistic &Stat);
+} // namespace fuzz
+
+#endif // LLVM_FUZZINFO_H
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index 503c77cb13bd07..f8bbec50153c5e 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
include(LLVM-Build)
-# `Demangle', `Support' and `TableGen' libraries are added on the top-level
+# `CompilerAssistedFuzzing`, `Demangle', `Support' and `TableGen' libraries are added on the top-level
# CMakeLists.txt
add_subdirectory(IR)
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 5a17944db0ae03..ba573578a68887 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -270,6 +270,7 @@ add_llvm_component_library(LLVMCodeGen
BitWriter
CGData
CodeGenTypes
+ CompilerAssistedFuzzing
Core
MC
ObjCARC
diff --git a/llvm/lib/CompilerAssistedFuzzing/CMakeLists.txt b/llvm/lib/CompilerAssistedFuzzing/CMakeLists.txt
new file mode 100644
index 00000000000000..25e8eba2eeb871
--- /dev/null
+++ b/llvm/lib/CompilerAssistedFuzzing/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_llvm_component_library(LLVMCompilerAssistedFuzzing
+ FuzzInfo.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ "${LLVM_MAIN_INCLUDE_DIR}/llvm/CompilerAssistedFuzzing"
+
+ LINK_COMPONENTS
+ Support
+)
diff --git a/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp b/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
new file mode 100644
index 00000000000000..4d3d1eb4cf31ce
--- /dev/null
+++ b/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
@@ -0,0 +1,81 @@
+#include "llvm/CompilerAssistedFuzzing/FuzzInfo.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <cassert>
+#include <cmath>
+
+#define DEBUG_TYPE "fuzz"
+
+using namespace llvm;
+
+std::string FuzzComponents;
+static cl::opt<std::string, true>
+ FuzzingComponents("fuzz-components",
+ cl::desc("Compiler components to fuzz."),
+ cl::location(FuzzComponents), cl::init(""));
+
+int64_t FuzzSeed;
+static cl::opt<int64_t, true> FuzzingSeed("fuzz-seed",
+ cl::desc("Compiler fuzzing seed."),
+ cl::location(FuzzSeed), cl::init(0));
+
+using fuzz::Component;
+
+Component fuzz::Scheduler("scheduler");
+Component fuzz::MBBPlacement("mbb-placement");
+Component fuzz::RegAlloc("regalloc");
+Component fuzz::ISel("isel");
+Component fuzz::Alloca("alloca");
+std::array<std::reference_wrapper<Component>, 5> Components{
+ fuzz::Scheduler, fuzz::MBBPlacement, fuzz::RegAlloc, fuzz::ISel,
+ fuzz::Alloca};
+
+inline bool isCompUsed(const Component &Comp) {
+ if (FuzzComponents.find("all") != std::string::npos)
+ return true;
+
+ return FuzzComponents.find(Comp.GetName()) != std::string::npos;
+}
+
+const Component &Component::operator+=(llvm::TrackingStatistic &Stat) {
+ if (llvm::find_if(Stats, [&Stat](const fuzz::StatRefWrapper &St) -> bool {
+ return St.get().getName() == Stat.getName();
+ }) == Stats.end()) {
+ Stats.emplace_back(Stat);
+ }
+ Stat++;
+ return *this;
+}
+
+bool fuzz::isFuzzed(Component &Comp, llvm::TrackingStatistic &Stat) {
+ if (isCompUsed(Comp)) {
+ Comp += Stat;
+ return true;
+ }
+
+ return false;
+}
+
+int64_t fuzz::fuzzedIntRange(Component &Comp, llvm::TrackingStatistic &Stat,
+ int64_t Start, int64_t End, int64_t Default) {
+ if (!isFuzzed(Comp, Stat)) {
+ return Default;
+ }
+
+ int64_t Length = End - Start;
+ assert(Length > 0 && "Length must be non negative");
+
+ return (std::abs(FuzzSeed) % Length) + Start;
+}
+
+bool fuzz::CheckStat(const llvm::TrackingStatistic &Stat) {
+ for (const auto &C : Components) {
+ for (const auto &St : C.get().GetStats()) {
+ if (Stat.getName() == St.get().getName())
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 97188b0672f032..ee7df40ba1de5c 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -299,6 +299,7 @@ add_llvm_component_library(LLVMSupport
LINK_COMPONENTS
Demangle
+ CompilerAssistedFuzzing
)
set(llvm_system_libs ${system_libs})
diff --git a/llvm/lib/Support/Statistic.cpp b/llvm/lib/Support/Statistic.cpp
index 24ef3e9abaebce..7961a68adc0c56 100644
--- a/llvm/lib/Support/Statistic.cpp
+++ b/llvm/lib/Support/Statistic.cpp
@@ -25,6 +25,7 @@
#include "DebugOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/CompilerAssistedFuzzing/FuzzInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
@@ -45,6 +46,7 @@ static bool EnableStats;
static bool StatsAsJSON;
static bool Enabled;
static bool PrintOnExit;
+static bool FuzzOnlyStats;
void llvm::initStatisticOptions() {
static cl::opt<bool, true> registerEnableStats{
@@ -55,6 +57,9 @@ void llvm::initStatisticOptions() {
static cl::opt<bool, true> registerStatsAsJson{
"stats-json", cl::desc("Display statistics as json data"),
cl::location(StatsAsJSON), cl::Hidden};
+ static cl::opt<bool, true> registerFuzzOnlyStats{
+ "fuzz-only-stats", cl::desc("Dump only fuzz stats."),
+ cl::location(FuzzOnlyStats), cl::Hidden};
}
namespace {
@@ -173,6 +178,14 @@ void StatisticInfo::reset() {
Stats.clear();
}
+static bool isPrintValid(const TrackingStatistic *Stat) {
+ if (!FuzzOnlyStats) {
+ return true;
+ }
+
+ return fuzz::CheckStat(*Stat);
+}
+
void llvm::PrintStatistics(raw_ostream &OS) {
StatisticInfo &Stats = *StatInfo;
@@ -192,9 +205,12 @@ void llvm::PrintStatistics(raw_ostream &OS) {
<< "===" << std::string(73, '-') << "===\n\n";
// Print all of the statistics.
- for (TrackingStatistic *Stat : Stats.Stats)
+ for (TrackingStatistic *Stat : Stats.Stats) {
+ if (!isPrintValid(Stat))
+ continue;
OS << format("%*" PRIu64 " %-*s - %s\n", MaxValLen, Stat->getValue(),
MaxDebugTypeLen, Stat->getDebugType(), Stat->getDesc());
+ }
OS << '\n'; // Flush the output stream.
OS.flush();
@@ -210,6 +226,8 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) {
OS << "{\n";
const char *delim = "";
for (const TrackingStatistic *Stat : Stats.Stats) {
+ if (!isPrintValid(Stat))
+ continue;
OS << delim;
assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
"Statistic group/type name is simple.");
>From a0255d0935d19446a6e52660c6b4585fd370d140 Mon Sep 17 00:00:00 2001
From: d-tolmachev <den.filipchenko0000 at gmail.com>
Date: Mon, 7 Oct 2024 14:08:05 +0300
Subject: [PATCH 2/4] Bug fixes
---
clang/include/clang/Basic/DiagnosticDriverKinds.td | 2 +-
clang/lib/Driver/ToolChains/Clang.cpp | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index f59c0e286e49e9..73766d45c29a58 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -829,7 +829,7 @@ def err_drv_triple_version_invalid : Error<
def err_empty_option_value : Error<
"empty value for %0 option">;
-def warn_use_fseed : Warning<"Fuzzing with seed: %0">,
+def warn_use_fseed : Warning<"fuzzing with seed: %0">,
InGroup<DiagGroup<"fuzzing">>;
def warn_missing_include_dirs : Warning<
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index c10cd539942040..82232856324078 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7657,6 +7657,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StatsFile.assign(Output.getFilename());
llvm::sys::path::replace_extension(StatsFile, "stats");
}
+ }
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
>From 5ab8f99993dcdd755b22f44cdbda2360f6db8b0b Mon Sep 17 00:00:00 2001
From: Arseny Bochkarev <arseny.bochkarev at syntacore.com>
Date: Sun, 13 Oct 2024 18:49:46 +0300
Subject: [PATCH 3/4] [Options] Add a BPU component to fuzz
---
clang/include/clang/Driver/Options.td | 2 +-
clang/lib/Driver/ToolChains/Clang.cpp | 2 +-
llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h | 1 +
llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp | 5 +++--
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 264ebd3541de15..502826ff325524 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6735,7 +6735,7 @@ def fuzz_EQ : Joined<["--"], "fuzz=">,
Flags<[NoXarchOption, HelpHidden]>, Group<f_Group>,
HelpText<"Fuzz selected compiler components, RISC-V only."
"Usage: --fuzz=\"<component1>[|<component2>...]\"">,
- Values<"all, scheduler, mbb-placement, regalloc, isel, alloca">;
+ Values<"all, scheduler, mbb-placement, regalloc, isel, alloca, bpu">;
def fseed_EQ : Joined<["--"], "fseed=">,
Flags<[NoXarchOption, HelpHidden]>, Group<f_Group>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 82232856324078..563adaa813eb09 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -8079,7 +8079,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
llvm::SmallVector<StringRef> CorrectOpts = {
- "all", "scheduler", "mbb-placement", "regalloc", "isel", "alloca"};
+ "all", "scheduler", "mbb-placement", "regalloc", "isel", "alloca", "bpu"};
for (const auto &ActualOpt : ActualOpts)
if (llvm::find(CorrectOpts, ActualOpt) == CorrectOpts.end())
diff --git a/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h b/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
index 9f908d0f64ed86..1d2cf45103ba3a 100644
--- a/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
+++ b/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
@@ -32,6 +32,7 @@ extern Component MBBPlacement;
extern Component RegAlloc;
extern Component ISel;
extern Component Alloca;
+extern Component BPU;
bool isFuzzed(fuzz::Component &Comp, llvm::TrackingStatistic &Stat);
int64_t fuzzedIntRange(fuzz::Component &Comp, llvm::TrackingStatistic &Stat,
diff --git a/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp b/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
index 4d3d1eb4cf31ce..17df4e399299ce 100644
--- a/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
+++ b/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
@@ -24,12 +24,13 @@ using fuzz::Component;
Component fuzz::Scheduler("scheduler");
Component fuzz::MBBPlacement("mbb-placement");
+Component fuzz::BPU("bpu");
Component fuzz::RegAlloc("regalloc");
Component fuzz::ISel("isel");
Component fuzz::Alloca("alloca");
-std::array<std::reference_wrapper<Component>, 5> Components{
+std::array<std::reference_wrapper<Component>, 6> Components{
fuzz::Scheduler, fuzz::MBBPlacement, fuzz::RegAlloc, fuzz::ISel,
- fuzz::Alloca};
+ fuzz::Alloca, fuzz::BPU};
inline bool isCompUsed(const Component &Comp) {
if (FuzzComponents.find("all") != std::string::npos)
>From 095597422083749054462fae3b58f81f162ea314 Mon Sep 17 00:00:00 2001
From: dmitriy sokolov <codemitry at gmail.com>
Date: Sat, 16 Nov 2024 19:58:21 +0300
Subject: [PATCH 4/4] bpu: machine basic block placement fuzzing (unoptimal
placement)
block frequency inversion added under special flag
---
llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp | 16 ++++++
llvm/lib/CodeGen/MachineBlockPlacement.cpp | 57 +++++++++++++++-----
2 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
index 9f6e53ba15b6a6..40b028ca225125 100644
--- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
+++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/BlockFrequency.h"
@@ -62,6 +63,13 @@ cl::opt<double> IterativeBFIPrecision(
"typically lead to better results at the cost of worsen runtime"));
} // namespace llvm
+static cl::opt<bool> BFIInverse("bfi-invert",
+ cl::desc("Force inverting of BFI values during computation."),
+ cl::init(false), cl::Hidden);
+
+ALWAYS_ENABLED_STATISTIC(NumInvertedBFI, "BFI: inverted frequences amount");
+
+
ScaledNumber<uint64_t> BlockMass::toScaled() const {
if (isFull())
return ScaledNumber<uint64_t>(1, 0);
@@ -554,6 +562,14 @@ void BlockFrequencyInfoImplBase::finalizeMetrics() {
Max = std::max(Max, Freqs[Index].Scaled);
}
+ if (BFIInverse) {
+ for (size_t Index = 0; Index < Working.size(); ++Index) {
+ Freqs[Index].Scaled = Max + Min - Freqs[Index].Scaled;
+ NumInvertedBFI++;
+ }
+ }
+
+
// Convert to integers.
convertFloatingToInteger(*this, Min, Max);
diff --git a/llvm/lib/CodeGen/MachineBlockPlacement.cpp b/llvm/lib/CodeGen/MachineBlockPlacement.cpp
index a52c82d77ca644..0a9316ffeae0ce 100644
--- a/llvm/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/llvm/lib/CodeGen/MachineBlockPlacement.cpp
@@ -48,6 +48,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/CompilerAssistedFuzzing/FuzzInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PrintPasses.h"
@@ -84,6 +85,14 @@ STATISTIC(CondBranchTakenFreq,
STATISTIC(UncondBranchTakenFreq,
"Potential frequency of taking unconditional branches");
+ALWAYS_ENABLED_STATISTIC(NumHasBadCfgConflict, "Machine Basic Block Placement num of bad layout predecessors found");
+ALWAYS_ENABLED_STATISTIC(NumSingleSuccessorTailDup, "Machine Basic Block Placement: tail duplication if BB has a single successor");
+ALWAYS_ENABLED_STATISTIC(NumBestNonConflictingEdgesComparatorGet, "Machine Basic Block Placement: best non-conflicting edges comparator get");
+ALWAYS_ENABLED_STATISTIC(NumBestNonConflictingEdgesExchange, "Machine Basic Block Placement: best non-conflicting edges exchange");
+ALWAYS_ENABLED_STATISTIC(NumBestSuccessorCheck, "Machine Basic Block Placement: best successor search");
+ALWAYS_ENABLED_STATISTIC(NumSuitableTailDupCheck, "Machine Basic Block Placement: best candidate for tail dup check");
+ALWAYS_ENABLED_STATISTIC(NumSelectBestCandidateBlock, "Machine Basic Block Placement: best candidate block selection");
+
static cl::opt<unsigned> AlignAllBlock(
"align-all-blocks",
cl::desc("Force the alignment of all blocks in the function in log2 format "
@@ -799,7 +808,7 @@ bool MachineBlockPlacement::shouldTailDuplicate(MachineBasicBlock *BB) {
bool IsSimple = TailDup.isSimpleBB(BB);
if (BB->succ_size() == 1)
- return false;
+ return isFuzzed(fuzz::BPU, NumSingleSuccessorTailDup); // return false;
return TailDup.shouldTailDuplicate(IsSimple, *BB);
}
@@ -1037,7 +1046,7 @@ MachineBlockPlacement::getBestNonConflictingEdges(
// compare which combination is better overall.
// Sort for highest frequency.
- auto Cmp = [](WeightedEdge A, WeightedEdge B) { return A.Weight > B.Weight; };
+ auto Cmp = isFuzzed(fuzz::BPU, NumBestNonConflictingEdgesComparatorGet) ? [](WeightedEdge A, WeightedEdge B) { return A.Weight < B.Weight; } : [](WeightedEdge A, WeightedEdge B) { return A.Weight > B.Weight; };
llvm::stable_sort(Edges[0], Cmp);
llvm::stable_sort(Edges[1], Cmp);
@@ -1051,10 +1060,18 @@ MachineBlockPlacement::getBestNonConflictingEdges(
auto SecondBestB = std::next(BestB);
BlockFrequency BestAScore = BestA->Weight + SecondBestB->Weight;
BlockFrequency BestBScore = BestB->Weight + SecondBestA->Weight;
- if (BestAScore < BestBScore)
- BestA = SecondBestA;
- else
- BestB = SecondBestB;
+
+ if (isFuzzed(fuzz::BPU, NumBestNonConflictingEdgesExchange)) {
+ if (BestAScore > BestBScore)
+ BestA = SecondBestA;
+ else
+ BestB = SecondBestB;
+ } else {
+ if (BestAScore < BestBScore)
+ BestA = SecondBestA;
+ else
+ BestB = SecondBestB;
+ }
}
// Arrange for the BB edge to be in BestA if it exists.
if (BestB->Src == BB)
@@ -1576,7 +1593,9 @@ bool MachineBlockPlacement::hasBetterLayoutPredecessor(
BlockFrequency PredEdgeFreq =
MBFI->getBlockFreq(Pred) * MBPI->getEdgeProbability(Pred, Succ);
if (PredEdgeFreq * HotProb >= CandidateEdgeFreq * HotProb.getCompl()) {
- BadCFGConflict = true;
+ if (!isFuzzed(fuzz::BPU, NumHasBadCfgConflict)) {
+ BadCFGConflict = true;
+ }
break;
}
}
@@ -1661,9 +1680,16 @@ MachineBlockPlacement::selectBestSuccessor(const MachineBasicBlock *BB,
<< (SuccChain.UnscheduledPredecessors != 0 ? " (CFG break)" : "")
<< "\n");
- if (BestSucc.BB && BestProb >= SuccProb) {
- LLVM_DEBUG(dbgs() << " Not the best candidate, continuing\n");
- continue;
+ if (isFuzzed(fuzz::BPU, NumBestSuccessorCheck)) {
+ if (BestSucc.BB && BestProb <= SuccProb) {
+ LLVM_DEBUG(dbgs() << " Not the worst candidate, continuing\n");
+ continue;
+ }
+ } else {
+ if (BestSucc.BB && BestProb >= SuccProb) {
+ LLVM_DEBUG(dbgs() << " Not the best candidate, continuing\n");
+ continue;
+ }
}
LLVM_DEBUG(dbgs() << " Setting it as best candidate\n");
@@ -1684,7 +1710,7 @@ MachineBlockPlacement::selectBestSuccessor(const MachineBasicBlock *BB,
BranchProbability DupProb;
MachineBasicBlock *Succ;
std::tie(DupProb, Succ) = Tup;
- if (DupProb < BestProb)
+ if (DupProb < BestProb && !isFuzzed(fuzz::BPU, NumSuitableTailDupCheck))
break;
if (canTailDuplicateUnplacedPreds(BB, Succ, Chain, BlockFilter) &&
(isProfitableToTailDup(BB, Succ, BestProb, Chain, BlockFilter))) {
@@ -1764,8 +1790,13 @@ MachineBasicBlock *MachineBlockPlacement::selectBestCandidateBlock(
// +-------------------------------------+
// V |
// OuterLp -> OuterCleanup -> Resume InnerLp -> InnerCleanup
- if (BestBlock && (IsEHPad ^ (BestFreq >= CandidateFreq)))
- continue;
+ if (isFuzzed(fuzz::BPU, NumSelectBestCandidateBlock)) {
+ if (BestBlock && (IsEHPad ^ (BestFreq <= CandidateFreq)))
+ continue;
+ } else {
+ if (BestBlock && (IsEHPad ^ (BestFreq >= CandidateFreq)))
+ continue;
+ }
BestBlock = MBB;
BestFreq = CandidateFreq;
More information about the cfe-commits
mailing list