[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