[llvm] fec54af - [SandboxIR][SandboxVec] Remove score tracking from Region, add RegionWithScore (#190293)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 10:04:48 PDT 2026


Author: vporpo
Date: 2026-05-04T10:04:42-07:00
New Revision: fec54af42099a3ef2c736a4e158e3346f9843c59

URL: https://github.com/llvm/llvm-project/commit/fec54af42099a3ef2c736a4e158e3346f9843c59
DIFF: https://github.com/llvm/llvm-project/commit/fec54af42099a3ef2c736a4e158e3346f9843c59.diff

LOG: [SandboxIR][SandboxVec] Remove score tracking from Region, add RegionWithScore (#190293)

Up until now the `Region` class contained a `ScoreBoard` and was
tracking instruction costs by default. However, design-wise the Region
is a generic IR-level structure and should be independent from score
tracking.

So this patch removes the score tracking capability from the base
`Region` class and creates a separate `RegionWithScore` derived class
for that. The new class is placed in the vectorizer directory because
the score tracking is meant for the vectorizer.

Should be NFC.

Added: 
    llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.cpp
    llvm/unittests/Transforms/Vectorize/SandboxVectorizer/RegionWithScoreTest.cpp

Modified: 
    llvm/include/llvm/SandboxIR/Region.h
    llvm/lib/SandboxIR/Region.cpp
    llvm/lib/Transforms/Vectorize/CMakeLists.txt
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp
    llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
    llvm/unittests/SandboxIR/PassTest.cpp
    llvm/unittests/SandboxIR/RegionTest.cpp
    llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/SandboxIR/Region.h b/llvm/include/llvm/SandboxIR/Region.h
index ef0de59aa7581..f61ae9619dc2c 100644
--- a/llvm/include/llvm/SandboxIR/Region.h
+++ b/llvm/include/llvm/SandboxIR/Region.h
@@ -14,48 +14,11 @@
 
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/iterator_range.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/SandboxIR/Instruction.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace llvm::sandboxir {
 
-class Region;
-
-class ScoreBoard {
-  const Region &Rgn;
-  TargetTransformInfo &TTI;
-  constexpr static TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
-  /// The cost of all instructions added to the region.
-  InstructionCost AfterCost = 0;
-  /// The cost of all instructions that got removed and replaced by new ones.
-  InstructionCost BeforeCost = 0;
-  /// Helper for both add() and remove(). \Returns the TTI cost of \p I.
-  LLVM_ABI InstructionCost getCost(Instruction *I) const;
-  /// No need to allow copies.
-  ScoreBoard(const ScoreBoard &) = delete;
-  const ScoreBoard &operator=(const ScoreBoard &) = delete;
-
-public:
-  ScoreBoard(Region &Rgn, TargetTransformInfo &TTI) : Rgn(Rgn), TTI(TTI) {}
-  /// Mark \p I as a newly added instruction to the region.
-  void add(Instruction *I) { AfterCost += getCost(I); }
-  /// Mark \p I as a deleted instruction from the region.
-  LLVM_ABI void remove(Instruction *I);
-  /// \Returns the cost of the newly added instructions.
-  InstructionCost getAfterCost() const { return AfterCost; }
-  /// \Returns the cost of the Removed instructions.
-  InstructionCost getBeforeCost() const { return BeforeCost; }
-
-#ifndef NDEBUG
-  void dump(raw_ostream &OS) const {
-    OS << "BeforeCost: " << BeforeCost << "\n";
-    OS << "AfterCost:  " << AfterCost << "\n";
-  }
-  LLVM_DUMP_METHOD void dump() const;
-#endif // NDEBUG
-};
-
 /// The main job of the Region is to point to new instructions generated by
 /// vectorization passes. It is the unit that RegionPasses operate on with their
 /// runOnRegion() function.
@@ -93,7 +56,13 @@ class ScoreBoard {
 // This can be used to pass auxiliary information across region passes, like for
 // example the initial seed slice used by the bottom-up vectorizer.
 
+enum RegionClassID {
+  RegionID,
+  RegionWithScoreID,
+};
+
 class Region {
+protected:
   /// All the instructions in the Region. Only new instructions generated during
   /// vectorization are part of the Region.
   SetVector<Instruction *> Insts;
@@ -107,31 +76,34 @@ class Region {
   static constexpr const char *AuxMDKind = "sandboxaux";
 
   Context &Ctx;
-  /// Keeps track of cost of instructions added and removed.
-  ScoreBoard Scoreboard;
+
+  RegionClassID ID;
 
   /// ID (for later deregistration) of the "create instruction" callback.
   Context::CallbackID CreateInstCB;
   /// ID (for later deregistration) of the "erase instruction" callback.
   Context::CallbackID EraseInstCB;
 
-  /// Adds \p I to the set but also don't track the instruction's score if \p
-  /// IgnoreCost is true. Only to be used when adding an instruction to the
-  /// auxiliary vector.
+  /// Adds \p I to the set. Only to be used when we want to avoid the additional
+  /// functionality provided by the subclass, e.g., to avoid score counting when
+  /// adding instrs to the aux vector.
   /// NOTE: When an instruction is added to the region we track it cost in the
   /// scoreboard, which currently resides in the region class. However, when we
   /// add an instruction to the auxiliary vector it does get tagged as being a
   /// member of the region (for ownership reasons), but its cost does not get
   /// counted because the instruction hasn't been added in the "normal" way.
-  LLVM_ABI void addImpl(Instruction *I, bool IgnoreCost);
+  void addRaw(Instruction *I) {
+    Insts.insert(I);
+    // TODO: Consider tagging instructions lazily.
+    cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, RegionMDN);
+  }
   /// Adds I to the set. This is the main API for adding an instruction to the
   /// region.
-  void add(Instruction *I) { addImpl(I, /*IgnoreCost=*/false); }
+  virtual void add(Instruction *I) { addRaw(I); }
   /// Removes I from the set.
-  LLVM_ABI void remove(Instruction *I);
+  LLVM_ABI virtual void remove(Instruction *I);
   friend class Context; // The callbacks need to call add() and remove().
   friend class RegionInternalsAttorney; // For unit tests.
-  friend class RegionsFromBBs;          // For add().
 
   /// Set \p I as the \p Idx'th element in the auxiliary vector.
   /// NOTE: This is for internal use, it does not set the metadata.
@@ -141,9 +113,15 @@ class Region {
   /// Remove instruction \p I from Aux and drop metadata.
   void removeFromAux(Instruction *I);
 
+  LLVM_ABI Region(Context &Ctx, RegionClassID ID);
+
 public:
-  LLVM_ABI Region(Context &Ctx, TargetTransformInfo &TTI);
-  LLVM_ABI ~Region();
+  LLVM_ABI Region(Context &Ctx) : Region(Ctx, RegionClassID::RegionID) {}
+  LLVM_ABI virtual ~Region();
+  // Disable copies to avoid unregistering the callback more than once.
+  Region(const Region &) = delete;
+  // Moves are allowed.
+  Region(Region &&) = default;
 
   Context &getContext() const { return Ctx; }
   /// Returns true if I is in the Region.
@@ -163,9 +141,9 @@ class Region {
   iterator_range<iterator> insts() { return make_range(begin(), end()); }
 
   LLVM_ABI static SmallVector<std::unique_ptr<Region>>
-  createRegionsFromMD(Function &F, TargetTransformInfo &TTI);
-  /// \Returns the ScoreBoard data structure that keeps track of instr costs.
-  const ScoreBoard &getScoreboard() const { return Scoreboard; }
+  createRegionsFromMD(Function &F);
+
+  RegionClassID getSubclassID() const { return ID; }
 
 #ifndef NDEBUG
   /// This is an expensive check, meant for testing.

diff  --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h
new file mode 100644
index 0000000000000..4f7ccee5a9f68
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h
@@ -0,0 +1,102 @@
+//===- RegionWithScore.h ----------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// A region with score tracking for added/removed instructions.
+//
+
+#ifndef LLVM_SANDBOXIR_REGIONWITHSCORE_H
+#define LLVM_SANDBOXIR_REGIONWITHSCORE_H
+
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/SandboxIR/Region.h"
+
+namespace llvm::sandboxir {
+
+/// Vectorization Score (cost) tracking class.
+class ScoreBoard {
+  const Region &Rgn;
+  const TargetTransformInfo &TTI;
+  constexpr static TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
+  /// The cost of all instructions added to the region.
+  InstructionCost AfterCost = 0;
+  /// The cost of all instructions that got removed and replaced by new ones.
+  InstructionCost BeforeCost = 0;
+  /// Helper for both add() and remove(). \Returns the TTI cost of \p I.
+  LLVM_ABI InstructionCost getCost(Instruction *I) const;
+  /// No need to allow copies.
+  ScoreBoard(const ScoreBoard &) = delete;
+  const ScoreBoard &operator=(const ScoreBoard &) = delete;
+
+public:
+  ScoreBoard(Region &Rgn, const TargetTransformInfo &TTI)
+      : Rgn(Rgn), TTI(TTI) {}
+  /// Mark \p I as a newly added instruction to the region.
+  void add(Instruction *I) { AfterCost += getCost(I); }
+  /// Mark \p I as a deleted instruction from the region.
+  LLVM_ABI void remove(Instruction *I);
+  /// \Returns the cost of the newly added instructions.
+  InstructionCost getAfterCost() const { return AfterCost; }
+  /// \Returns the cost of the Removed instructions.
+  InstructionCost getBeforeCost() const { return BeforeCost; }
+
+#ifndef NDEBUG
+  void dump(raw_ostream &OS) const {
+    OS << "BeforeCost: " << BeforeCost << "\n";
+    OS << "AfterCost:  " << AfterCost << "\n";
+  }
+  LLVM_DUMP_METHOD void dump() const;
+#endif // NDEBUG
+};
+
+/// A Region class that tracks its instructions score.
+class RegionWithScore final : public Region {
+  /// Keeps track of cost of instructions added and removed.
+  ScoreBoard Scoreboard;
+
+  void add(Instruction *I) override {
+    addRaw(I);
+    // Keep track of the instruction cost.
+    Scoreboard.add(I);
+  }
+  friend class RegionsFromBBs; // For add().
+
+  void remove(Instruction *I) override {
+    // Keep track of the instruction cost. This need to be done *before* we
+    // remove `I` from the region.
+    Scoreboard.remove(I);
+    Region::remove(I);
+  }
+
+public:
+  RegionWithScore(Context &Ctx, const TargetTransformInfo &TTI)
+      : Region(Ctx, RegionClassID::RegionWithScoreID), Scoreboard(*this, TTI) {}
+  RegionWithScore(Region &&Rgn, const TargetTransformInfo &TTI)
+      : Region(std::move(Rgn)), Scoreboard(*this, TTI) {}
+  // For isa<> cast<> etc.
+  static bool classof(const Region *From) {
+    return From->getSubclassID() == RegionClassID::RegionWithScoreID;
+  }
+
+  /// \Returns the ScoreBoard data structure that keeps track of instr costs.
+  const ScoreBoard &getScoreboard() const { return Scoreboard; }
+
+  LLVM_ABI static SmallVector<std::unique_ptr<RegionWithScore>>
+  createRegionsFromMD(Function &F, const TargetTransformInfo &TTI) {
+    auto Rgns = Region::createRegionsFromMD(F);
+    SmallVector<std::unique_ptr<RegionWithScore>> NewRgns;
+    NewRgns.reserve(Rgns.size());
+    for (auto &RgnPtr : Rgns)
+      NewRgns.push_back(
+          std::make_unique<RegionWithScore>(std::move(*RgnPtr.release()), TTI));
+    return NewRgns;
+  }
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_REGIONWITHSCORE_H

diff  --git a/llvm/lib/SandboxIR/Region.cpp b/llvm/lib/SandboxIR/Region.cpp
index 7326e57248c1b..1f3c8da482476 100644
--- a/llvm/lib/SandboxIR/Region.cpp
+++ b/llvm/lib/SandboxIR/Region.cpp
@@ -11,35 +11,13 @@
 
 namespace llvm::sandboxir {
 
-InstructionCost ScoreBoard::getCost(Instruction *I) const {
-  auto *LLVMI = cast<llvm::Instruction>(I->Val);
-  SmallVector<const llvm::Value *> Operands(LLVMI->operands());
-  return TTI.getInstructionCost(LLVMI, Operands, CostKind);
-}
-
-void ScoreBoard::remove(Instruction *I) {
-  auto Cost = getCost(I);
-  if (Rgn.contains(I))
-    // If `I` is one the newly added ones, then we should adjust `AfterCost`
-    AfterCost -= Cost;
-  else
-    // If `I` is one of the original instructions (outside the region) then it
-    // is part of the original code, so adjust `BeforeCost`.
-    BeforeCost += Cost;
-}
-
-#ifndef NDEBUG
-void ScoreBoard::dump() const { dump(dbgs()); }
-#endif
-
-Region::Region(Context &Ctx, TargetTransformInfo &TTI)
-    : Ctx(Ctx), Scoreboard(*this, TTI) {
+Region::Region(Context &Ctx, RegionClassID ID) : Ctx(Ctx), ID(ID) {
   LLVMContext &LLVMCtx = Ctx.LLVMCtx;
   auto *RegionStrMD = MDString::get(LLVMCtx, RegionStr);
   RegionMDN = MDNode::getDistinct(LLVMCtx, {RegionStrMD});
 
   CreateInstCB = Ctx.registerCreateInstrCallback(
-      [this](Instruction *NewInst) { add(NewInst); });
+      [this](Instruction *NewInst) { addRaw(NewInst); });
   EraseInstCB = Ctx.registerEraseInstrCallback([this](Instruction *ErasedInst) {
     remove(ErasedInst);
     removeFromAux(ErasedInst);
@@ -51,15 +29,6 @@ Region::~Region() {
   Ctx.unregisterEraseInstrCallback(EraseInstCB);
 }
 
-void Region::addImpl(Instruction *I, bool IgnoreCost) {
-  Insts.insert(I);
-  // TODO: Consider tagging instructions lazily.
-  cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, RegionMDN);
-  if (!IgnoreCost)
-    // Keep track of the instruction cost.
-    Scoreboard.add(I);
-}
-
 void Region::setAux(ArrayRef<Instruction *> Aux) {
   this->Aux = SmallVector<Instruction *>(Aux);
   auto &LLVMCtx = Ctx.LLVMCtx;
@@ -71,7 +40,7 @@ void Region::setAux(ArrayRef<Instruction *> Aux) {
     cast<llvm::Instruction>(I->Val)->setMetadata(
         AuxMDKind, MDNode::get(LLVMCtx, ConstantAsMetadata::get(IdxC)));
     // Aux instrs should always be in a region.
-    addImpl(I, /*DontTrackCost=*/true);
+    addRaw(I);
   }
 }
 
@@ -88,7 +57,7 @@ void Region::setAux(unsigned Idx, Instruction *I) {
   }
   Aux[Idx] = I;
   // Aux instrs should always be in a region.
-  addImpl(I, /*DontTrackCost=*/true);
+  addRaw(I);
 }
 
 void Region::dropAuxMetadata(Instruction *I) {
@@ -111,10 +80,6 @@ void Region::clearAux() {
 }
 
 void Region::remove(Instruction *I) {
-  // Keep track of the instruction cost. This need to be done *before* we remove
-  // `I` from the region.
-  Scoreboard.remove(I);
-
   Insts.remove(I);
   cast<llvm::Instruction>(I->Val)->setMetadata(MDKind, nullptr);
 }
@@ -148,8 +113,7 @@ void Region::dump() const {
 }
 #endif // NDEBUG
 
-SmallVector<std::unique_ptr<Region>>
-Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) {
+SmallVector<std::unique_ptr<Region>> Region::createRegionsFromMD(Function &F) {
   SmallVector<std::unique_ptr<Region>> Regions;
   DenseMap<MDNode *, Region *> MDNToRegion;
   auto &Ctx = F.getContext();
@@ -160,13 +124,13 @@ Region::createRegionsFromMD(Function &F, TargetTransformInfo &TTI) {
       if (auto *MDN = LLVMI->getMetadata(MDKind)) {
         auto [It, Inserted] = MDNToRegion.try_emplace(MDN);
         if (Inserted) {
-          Regions.push_back(std::make_unique<Region>(Ctx, TTI));
+          Regions.push_back(std::make_unique<Region>(Ctx));
           R = Regions.back().get();
           It->second = R;
         } else {
           R = It->second;
         }
-        R->addImpl(&Inst, /*IgnoreCost=*/true);
+        R->addRaw(&Inst);
       }
       if (auto *AuxMDN = LLVMI->getMetadata(AuxMDKind)) {
         llvm::Constant *IdxC =

diff  --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
index 39d4711e11a56..a25b4c0a3b772 100644
--- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
@@ -16,6 +16,7 @@ add_llvm_component_library(LLVMVectorize
   SandboxVectorizer/Passes/SeedCollection.cpp
   SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
   SandboxVectorizer/Passes/TransactionSave.cpp
+  SandboxVectorizer/RegionWithScore.cpp
   SandboxVectorizer/SandboxVectorizer.cpp
   SandboxVectorizer/SandboxVectorizerPassBuilder.cpp
   SandboxVectorizer/Scheduler.cpp

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp
index 85c5b0da20f20..fb7dfeb17fb20 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.cpp
@@ -8,7 +8,7 @@
 
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromBBs.h"
 #include "llvm/SandboxIR/Function.h"
-#include "llvm/SandboxIR/Region.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
 
 namespace llvm::sandboxir {
@@ -18,10 +18,11 @@ RegionsFromBBs::RegionsFromBBs(StringRef Pipeline, StringRef AuxArg)
       RPM("rpm", Pipeline, SandboxVectorizerPassBuilder::createRegionPass) {}
 
 bool RegionsFromBBs::runOnFunction(Function &F, const Analyses &A) {
-  SmallVector<std::unique_ptr<Region>, 16> Regions;
+  SmallVector<std::unique_ptr<RegionWithScore>, 16> Regions;
   // Create a region for each BB.
   for (BasicBlock &BB : F) {
-    Regions.push_back(std::make_unique<Region>(F.getContext(), A.getTTI()));
+    Regions.push_back(
+        std::make_unique<RegionWithScore>(F.getContext(), A.getTTI()));
     auto &RgnPtr = Regions.back();
     for (Instruction &I : BB)
       RgnPtr->add(&I);

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp
index 612d4f11d28c6..74dd5e71bb07f 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.cpp
@@ -8,7 +8,7 @@
 
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.h"
 
-#include "llvm/SandboxIR/Region.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
 
 namespace llvm::sandboxir {
@@ -18,8 +18,8 @@ RegionsFromMetadata::RegionsFromMetadata(StringRef Pipeline, StringRef AuxArg)
       RPM("rpm", Pipeline, SandboxVectorizerPassBuilder::createRegionPass) {}
 
 bool RegionsFromMetadata::runOnFunction(Function &F, const Analyses &A) {
-  SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(F, A.getTTI());
+  SmallVector<std::unique_ptr<sandboxir::RegionWithScore>> Regions =
+      sandboxir::RegionWithScore::createRegionsFromMD(F, A.getTTI());
   bool Change = false;
   for (auto &R : Regions) {
     Change |= RPM.runOnRegion(*R, A);

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp
index 54cda0eaa6a8b..a3bd2dec43277 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.cpp
@@ -9,7 +9,7 @@
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/SeedCollection.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/SandboxIR/Module.h"
-#include "llvm/SandboxIR/Region.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h"
@@ -101,7 +101,7 @@ bool SeedCollection::runOnFunction(Function &F, const Analyses &A) {
 
           // Create a region containing the seed slice.
           auto &Ctx = F.getContext();
-          Region Rgn(Ctx, A.getTTI());
+          RegionWithScore Rgn(Ctx, A.getTTI());
           Rgn.setAux(SeedSlice);
           // Run the region pass pipeline.
           Change |= RPM.runOnRegion(Rgn, A);

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
index 7194529b87404..cf2819ec23a66 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
@@ -10,6 +10,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/InstructionCost.h"
 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Debug.h"
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
 
 namespace llvm {
 
@@ -20,7 +21,7 @@ static cl::opt<int> CostThreshold("sbvec-cost-threshold", cl::init(0),
 namespace sandboxir {
 
 bool TransactionAcceptOrRevert::runOnRegion(Region &Rgn, const Analyses &A) {
-  const auto &SB = Rgn.getScoreboard();
+  const auto &SB = cast<RegionWithScore>(Rgn).getScoreboard();
   [[maybe_unused]] auto CostBefore = SB.getBeforeCost();
   [[maybe_unused]] auto CostAfter = SB.getAfterCost();
   InstructionCost CostAfterMinusBefore = SB.getAfterCost() - SB.getBeforeCost();

diff  --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.cpp
new file mode 100644
index 0000000000000..44b500adf5b73
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.cpp
@@ -0,0 +1,34 @@
+//===- RegionWithScore.cpp - A Region with score tracking -----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
+
+namespace llvm::sandboxir {
+
+InstructionCost ScoreBoard::getCost(Instruction *I) const {
+  auto *LLVMI = cast<llvm::Instruction>(I->Val);
+  SmallVector<const llvm::Value *> Operands(LLVMI->operands());
+  return TTI.getInstructionCost(LLVMI, Operands, CostKind);
+}
+
+void ScoreBoard::remove(Instruction *I) {
+  auto Cost = getCost(I);
+  if (Rgn.contains(I))
+    // If `I` is one the newly added ones, then we should adjust `AfterCost`
+    AfterCost -= Cost;
+  else
+    // If `I` is one of the original instructions (outside the region) then it
+    // is part of the original code, so adjust `BeforeCost`.
+    BeforeCost += Cost;
+}
+
+#ifndef NDEBUG
+void ScoreBoard::dump() const { dump(dbgs()); }
+#endif
+
+} // namespace llvm::sandboxir

diff  --git a/llvm/unittests/SandboxIR/PassTest.cpp b/llvm/unittests/SandboxIR/PassTest.cpp
index 34182cb6d271f..4707137645430 100644
--- a/llvm/unittests/SandboxIR/PassTest.cpp
+++ b/llvm/unittests/SandboxIR/PassTest.cpp
@@ -125,7 +125,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   EXPECT_EQ(TPass.getName(), "test-pass");
   // Check runOnRegion();
   llvm::SmallVector<std::unique_ptr<Region>> Regions =
-      Region::createRegionsFromMD(*F, *TTI);
+      Region::createRegionsFromMD(*F);
   ASSERT_EQ(Regions.size(), 1u);
   TPass.runOnRegion(*Regions[0], Analyses::emptyForTesting());
   EXPECT_EQ(InstCount, 2u);
@@ -248,7 +248,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   RPM.addPass(std::make_unique<TestPass2>(InstCount2));
   // Check runOnRegion().
   llvm::SmallVector<std::unique_ptr<Region>> Regions =
-      Region::createRegionsFromMD(*F, *TTI);
+      Region::createRegionsFromMD(*F);
   ASSERT_EQ(Regions.size(), 1u);
   RPM.runOnRegion(*Regions[0], Analyses::emptyForTesting());
   EXPECT_EQ(InstCount1, 2u);

diff  --git a/llvm/unittests/SandboxIR/RegionTest.cpp b/llvm/unittests/SandboxIR/RegionTest.cpp
index 210d068bbc161..dc48d78e05a9c 100644
--- a/llvm/unittests/SandboxIR/RegionTest.cpp
+++ b/llvm/unittests/SandboxIR/RegionTest.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/SandboxIR/Region.h"
-#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/SandboxIR/Context.h"
 #include "llvm/SandboxIR/Function.h"
@@ -21,12 +20,10 @@ using namespace llvm;
 struct RegionTest : public testing::Test {
   LLVMContext C;
   std::unique_ptr<Module> M;
-  std::unique_ptr<TargetTransformInfo> TTI;
 
   void parseIR(LLVMContext &C, const char *IR) {
     SMDiagnostic Err;
     M = parseAssemblyString(IR, Err, C);
-    TTI = std::make_unique<TargetTransformInfo>(M->getDataLayout());
     if (!M)
       Err.print("RegionTest", errs());
   }
@@ -48,7 +45,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   auto *T0 = cast<sandboxir::Instruction>(&*It++);
   auto *T1 = cast<sandboxir::Instruction>(&*It++);
   auto *Ret = cast<sandboxir::Instruction>(&*It++);
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
 
   // Check getContext.
   EXPECT_EQ(&Ctx, &Rgn.getContext());
@@ -76,7 +73,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
 #ifndef NDEBUG
   // Check equality comparison. Insert in reverse order into `Other` to check
   // that comparison is order-independent.
-  sandboxir::Region Other(Ctx, *TTI);
+  sandboxir::Region Other(Ctx);
   sandboxir::RegionInternalsAttorney::add(Other, Ret);
   EXPECT_NE(Rgn, Other);
   sandboxir::RegionInternalsAttorney::add(Other, T1);
@@ -101,7 +98,7 @@ define i8 @foo(i8 %v0, i8 %v1, ptr %ptr) {
   auto *T0 = cast<sandboxir::Instruction>(&*It++);
   auto *T1 = cast<sandboxir::Instruction>(&*It++);
   auto *Ret = cast<sandboxir::Instruction>(&*It++);
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
   sandboxir::RegionInternalsAttorney::add(Rgn, T0);
   sandboxir::RegionInternalsAttorney::add(Rgn, T1);
 
@@ -137,7 +134,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   auto *T2 = cast<sandboxir::Instruction>(&*It++);
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   EXPECT_THAT(Regions[0]->insts(), testing::UnorderedElementsAre(T0));
   EXPECT_THAT(Regions[1]->insts(), testing::UnorderedElementsAre(T1, T2));
 }
@@ -163,7 +160,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   auto *T2 = cast<sandboxir::Instruction>(&*It++);
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   EXPECT_THAT(Regions[0]->insts(), testing::UnorderedElementsAre(T0, T2));
 }
 
@@ -185,9 +182,9 @@ define i8 @foo(i8 %v0, i8 %v1) {
   [[maybe_unused]] auto *T1 = cast<sandboxir::Instruction>(&*It++);
   auto *T2 = cast<sandboxir::Instruction>(&*It++);
   [[maybe_unused]] auto *Ret = cast<sandboxir::Instruction>(&*It++);
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
   sandboxir::RegionInternalsAttorney::add(Rgn, T0);
-  sandboxir::Region Rgn2(Ctx, *TTI);
+  sandboxir::Region Rgn2(Ctx);
   sandboxir::RegionInternalsAttorney::add(Rgn2, T2);
 
   std::string output;
@@ -229,70 +226,18 @@ define i8 @foo(i8 %v0, i8 %v1) {
   auto *T0 = cast<sandboxir::Instruction>(&*It++);
   auto *T1 = cast<sandboxir::Instruction>(&*It++);
 
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
   sandboxir::RegionInternalsAttorney::add(Rgn, T0);
   sandboxir::RegionInternalsAttorney::add(Rgn, T1);
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   ASSERT_EQ(1U, Regions.size());
 #ifndef NDEBUG
   EXPECT_EQ(Rgn, *Regions[0].get());
 #endif
 }
 
-TEST_F(RegionTest, RegionCost) {
-  parseIR(C, R"IR(
-define void @foo(i8 %v0, i8 %v1, i8 %v2) {
-  %add0 = add i8 %v0, 1
-  %add1 = add i8 %v1, 2
-  %add2 = add i8 %v2, 3
-  ret void
-}
-)IR");
-  llvm::Function *LLVMF = &*M->getFunction("foo");
-  auto *LLVMBB = &*LLVMF->begin();
-  auto LLVMIt = LLVMBB->begin();
-  auto *LLVMAdd0 = &*LLVMIt++;
-  auto *LLVMAdd1 = &*LLVMIt++;
-  auto *LLVMAdd2 = &*LLVMIt++;
-
-  sandboxir::Context Ctx(C);
-  auto *F = Ctx.createFunction(LLVMF);
-  auto *BB = &*F->begin();
-  auto It = BB->begin();
-  auto *Add0 = cast<sandboxir::Instruction>(&*It++);
-  auto *Add1 = cast<sandboxir::Instruction>(&*It++);
-  auto *Add2 = cast<sandboxir::Instruction>(&*It++);
-
-  sandboxir::Region Rgn(Ctx, *TTI);
-  const auto &SB = Rgn.getScoreboard();
-  EXPECT_EQ(SB.getAfterCost(), 0);
-  EXPECT_EQ(SB.getBeforeCost(), 0);
-
-  auto GetCost = [this](llvm::Instruction *LLVMI) {
-    constexpr static TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
-    SmallVector<const llvm::Value *> Operands(LLVMI->operands());
-    return TTI->getInstructionCost(LLVMI, Operands, CostKind);
-  };
-  // Add `Add0` to the region, should be counted in "After".
-  sandboxir::RegionInternalsAttorney::add(Rgn, Add0);
-  EXPECT_EQ(SB.getBeforeCost(), 0);
-  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd0));
-  // Same for `Add1`.
-  sandboxir::RegionInternalsAttorney::add(Rgn, Add1);
-  EXPECT_EQ(SB.getBeforeCost(), 0);
-  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd0) + GetCost(LLVMAdd1));
-  // Remove `Add0`, should be subtracted from "After".
-  sandboxir::RegionInternalsAttorney::remove(Rgn, Add0);
-  EXPECT_EQ(SB.getBeforeCost(), 0);
-  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd1));
-  // Remove `Add2` which was never in the region, should counted in "Before".
-  sandboxir::RegionInternalsAttorney::remove(Rgn, Add2);
-  EXPECT_EQ(SB.getBeforeCost(), GetCost(LLVMAdd2));
-  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd1));
-}
-
 TEST_F(RegionTest, Aux) {
   parseIR(C, R"IR(
 define void @foo(i8 %v) {
@@ -329,7 +274,7 @@ define void @foo(i8 %v) {
   auto *T5 = cast<sandboxir::Instruction>(&*It++);
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   // Check that the regions are correct.
   EXPECT_THAT(Regions[0]->insts(), testing::UnorderedElementsAre(T0, T1));
   EXPECT_THAT(Regions[1]->insts(),
@@ -362,8 +307,7 @@ define void @foo(i8 %v) {
   llvm::Function *LLVMF = &*M->getFunction("foo");
   sandboxir::Context Ctx(C);
   auto *F = Ctx.createFunction(LLVMF);
-  EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI),
-                     ".*Gap*");
+  EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F), ".*Gap*");
 }
 
 // Check that we get an assertion failure if we try to set the same index more
@@ -382,8 +326,7 @@ define void @foo(i8 %v) {
   llvm::Function *LLVMF = &*M->getFunction("foo");
   sandboxir::Context Ctx(C);
   auto *F = Ctx.createFunction(LLVMF);
-  EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI),
-                     ".*already.*");
+  EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F), ".*already.*");
 }
 
 // Check that Aux automatically drops instructions that get deleted.
@@ -413,7 +356,7 @@ define void @foo(i8 %v) {
   auto *Add2 = &*It++;
   auto *Add3 = &*It++;
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   auto &R = *Regions[0];
   EXPECT_THAT(R.getAux(), testing::ElementsAre(Add0, Add1, Add2, Add3));
   // Now delete Add1 and check that Aux contains nullptr instead of Add1.
@@ -424,7 +367,7 @@ define void @foo(i8 %v) {
     // But first drop Add3 to create a legal Aux vector with no gaps.
     Add3->eraseFromParent();
     SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-        sandboxir::Region::createRegionsFromMD(*F, *TTI);
+        sandboxir::Region::createRegionsFromMD(*F);
     EXPECT_THAT(Regions[0]->getAux(), testing::ElementsAre(Add0, Add1));
   }
 }
@@ -441,9 +384,9 @@ define void @foo(i8 %v) {
   sandboxir::Context Ctx(C);
   auto *F = Ctx.createFunction(LLVMF);
 #ifndef NDEBUG
-  EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI), "No region.*");
+  EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F), "No region.*");
 #endif
-  EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI),
+  EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F),
                "No region specified for Aux!");
 }
 
@@ -463,7 +406,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   auto *T0 = cast<sandboxir::Instruction>(&*It++);
   auto *T1 = cast<sandboxir::Instruction>(&*It++);
 
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
 #ifndef NDEBUG
   EXPECT_DEATH(Rgn.setAux({T0, T0}), ".*already.*");
 #endif
@@ -472,7 +415,7 @@ define i8 @foo(i8 %v0, i8 %v1) {
   Rgn.setAux({T1, T0});
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   ASSERT_EQ(1U, Regions.size());
 #ifndef NDEBUG
   EXPECT_EQ(Rgn, *Regions[0].get());
@@ -498,14 +441,14 @@ define void @foo(i8 %v) {
   auto *Add0 = cast<sandboxir::Instruction>(&*It++);
   auto *Add1 = cast<sandboxir::Instruction>(&*It++);
 
-  sandboxir::Region Rgn(Ctx, *TTI);
+  sandboxir::Region Rgn(Ctx);
 #ifndef NDEBUG
   EXPECT_DEATH(Rgn.setAux({Add0, Add0}), ".*already.*");
 #endif
   Rgn.setAux({Add1, Add0});
 
   SmallVector<std::unique_ptr<sandboxir::Region>> Regions =
-      sandboxir::Region::createRegionsFromMD(*F, *TTI);
+      sandboxir::Region::createRegionsFromMD(*F);
   ASSERT_EQ(1U, Regions.size());
 #ifndef NDEBUG
   EXPECT_EQ(Rgn, *Regions[0].get());

diff  --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
index 104a27975cfc0..3a05a2378d68e 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt
@@ -12,6 +12,7 @@ add_llvm_unittest(SandboxVectorizerTests
   InstrMapsTest.cpp
   IntervalTest.cpp
   LegalityTest.cpp
+  RegionWithScoreTest.cpp
   SandboxVectorizerTest.cpp
   SchedulerTest.cpp
   SeedCollectorTest.cpp	

diff  --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/RegionWithScoreTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/RegionWithScoreTest.cpp
new file mode 100644
index 0000000000000..054f6557b600a
--- /dev/null
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/RegionWithScoreTest.cpp
@@ -0,0 +1,84 @@
+//===- RegionWithScoreTest.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/RegionWithScore.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/Function.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct RegionWithScoreTest : public testing::Test {
+  LLVMContext C;
+  std::unique_ptr<Module> M;
+  std::unique_ptr<TargetTransformInfo> TTI;
+
+  void parseIR(LLVMContext &C, const char *IR) {
+    SMDiagnostic Err;
+    M = parseAssemblyString(IR, Err, C);
+    TTI = std::make_unique<TargetTransformInfo>(M->getDataLayout());
+    if (!M)
+      Err.print("RegionTest", errs());
+  }
+};
+
+TEST_F(RegionWithScoreTest, RegionCost) {
+  parseIR(C, R"IR(
+define void @foo(i8 %v0, i8 %v1, i8 %v2) {
+  %add0 = add i8 %v0, 1
+  %add1 = add i8 %v1, 2
+  %add2 = add i8 %v2, 3
+  ret void
+}
+)IR");
+  llvm::Function *LLVMF = &*M->getFunction("foo");
+  auto *LLVMBB = &*LLVMF->begin();
+  auto LLVMIt = LLVMBB->begin();
+  auto *LLVMAdd0 = &*LLVMIt++;
+  auto *LLVMAdd1 = &*LLVMIt++;
+  auto *LLVMAdd2 = &*LLVMIt++;
+
+  sandboxir::Context Ctx(C);
+  auto *F = Ctx.createFunction(LLVMF);
+  auto *BB = &*F->begin();
+  auto It = BB->begin();
+  auto *Add0 = cast<sandboxir::Instruction>(&*It++);
+  auto *Add1 = cast<sandboxir::Instruction>(&*It++);
+  auto *Add2 = cast<sandboxir::Instruction>(&*It++);
+
+  sandboxir::RegionWithScore Rgn(Ctx, *TTI);
+  const auto &SB = Rgn.getScoreboard();
+  EXPECT_EQ(SB.getAfterCost(), 0);
+  EXPECT_EQ(SB.getBeforeCost(), 0);
+
+  auto GetCost = [this](llvm::Instruction *LLVMI) {
+    constexpr static TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
+    SmallVector<const llvm::Value *> Operands(LLVMI->operands());
+    return TTI->getInstructionCost(LLVMI, Operands, CostKind);
+  };
+  // Add `Add0` to the region, should be counted in "After".
+  sandboxir::RegionInternalsAttorney::add(Rgn, Add0);
+  EXPECT_EQ(SB.getBeforeCost(), 0);
+  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd0));
+  // Same for `Add1`.
+  sandboxir::RegionInternalsAttorney::add(Rgn, Add1);
+  EXPECT_EQ(SB.getBeforeCost(), 0);
+  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd0) + GetCost(LLVMAdd1));
+  // Remove `Add0`, should be subtracted from "After".
+  sandboxir::RegionInternalsAttorney::remove(Rgn, Add0);
+  EXPECT_EQ(SB.getBeforeCost(), 0);
+  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd1));
+  // Remove `Add2` which was never in the region, should counted in "Before".
+  sandboxir::RegionInternalsAttorney::remove(Rgn, Add2);
+  EXPECT_EQ(SB.getBeforeCost(), GetCost(LLVMAdd2));
+  EXPECT_EQ(SB.getAfterCost(), GetCost(LLVMAdd1));
+}


        


More information about the llvm-commits mailing list