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 <bochkarevars...@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.filipchenko0...@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.bochka...@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 <codemi...@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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits