[clang] [llvm] BPU Machine basic block placement fuzz (PR #116492)

via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 16 09:02:55 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Dmitriy Sokolov (dee-tree)

<details>
<summary>Changes</summary>

- Non-optimal machine basic block placement via fuzz option
- machine block frequency inversion under the special option

---

Patch is 20.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116492.diff


13 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+6) 
- (modified) clang/include/clang/Driver/Options.td (+27) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+66-4) 
- (modified) llvm/CMakeLists.txt (+1) 
- (added) llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h (+44) 
- (modified) llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp (+16) 
- (modified) llvm/lib/CMakeLists.txt (+1-1) 
- (modified) llvm/lib/CodeGen/CMakeLists.txt (+1) 
- (modified) llvm/lib/CodeGen/MachineBlockPlacement.cpp (+44-13) 
- (added) llvm/lib/CompilerAssistedFuzzing/CMakeLists.txt (+9) 
- (added) llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp (+82) 
- (modified) llvm/lib/Support/CMakeLists.txt (+1) 
- (modified) llvm/lib/Support/Statistic.cpp (+19-1) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 97573fcf20c1fb..73766d45c29a58 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..502826ff325524 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, bpu">;
+
+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..563adaa813eb09 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7646,10 +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
@@ -8050,6 +8057,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", "bpu"};
+
+    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..1d2cf45103ba3a
--- /dev/null
+++ b/llvm/include/llvm/CompilerAssistedFuzzing/FuzzInfo.h
@@ -0,0 +1,44 @@
+#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;
+extern Component BPU;
+
+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/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/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/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;
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..17df4e399299ce
--- /dev/null
+++ b/llvm/lib/CompilerAssistedFuzzing/FuzzInfo.cpp
@@ -0,0 +1,82 @@
+#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::BPU("bpu");
+Component fuzz::RegAlloc("regalloc");
+Component fuzz::ISel("isel");
+Component fuzz::Alloca("alloca");
+std::array<std::reference_wrapper<Component>, 6> Components{
+    fuzz::Scheduler, fuzz::MBBPlacement, fuzz::RegAlloc, fuzz::ISel,
+    fuzz::Alloca, fuzz::BPU};
+
+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;...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/116492


More information about the llvm-commits mailing list