[llvm] [SandboxVec][DAG] Implement UnscheduledSuccs (PR #112255)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 14 13:07:53 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: vporpo (vporpo)
<details>
<summary>Changes</summary>
This patch implements the UnscheduledSuccs counter in DGNode. It counts the number of unscheduled successors and is used by the scheduler to determine when a node is ready.
---
Full diff: https://github.com/llvm/llvm-project/pull/112255.diff
3 Files Affected:
- (modified) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h (+23-3)
- (modified) llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp (+53-10)
- (modified) llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp (+26)
``````````diff
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
index 0da52c4236d77e..f3cd5be513503b 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h
@@ -96,9 +96,14 @@ class DGNode {
// TODO: Use a PointerIntPair for SubclassID and I.
/// For isa/dyn_cast etc.
DGNodeID SubclassID;
+ /// The number of unscheduled successors.
+ unsigned UnscheduledSuccs = 0;
+ /// This is true if this node has been scheduled.
+ bool Scheduled = false;
DGNode(Instruction *I, DGNodeID ID) : I(I), SubclassID(ID) {}
- friend class MemDGNode; // For constructor.
+ friend class MemDGNode; // For constructor.
+ friend class DependencyGraph; // For UnscheduledSuccs
public:
DGNode(Instruction *I) : I(I), SubclassID(DGNodeID::DGNode) {
@@ -106,6 +111,10 @@ class DGNode {
}
DGNode(const DGNode &Other) = delete;
virtual ~DGNode() = default;
+ /// \Returns the number of unscheduled successors.
+ unsigned getNumUnscheduledSuccs() const { return UnscheduledSuccs; }
+ /// \Returns true if this node has been scheduled.
+ bool scheduled() const { return Scheduled; }
/// \Returns true if this is before \p Other in program order.
bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); }
using iterator = PredIterator;
@@ -215,8 +224,15 @@ class MemDGNode final : public DGNode {
MemDGNode *getPrevNode() const { return PrevMemN; }
/// \Returns the next Mem DGNode in instruction order.
MemDGNode *getNextNode() const { return NextMemN; }
- /// Adds the mem dependency edge PredN->this.
- void addMemPred(MemDGNode *PredN) { MemPreds.insert(PredN); }
+ /// Adds the mem dependency edge PredN->this. This also increments the
+ /// UnscheduledSuccs counter of the predecessor if this node has not been
+ /// scheduled.
+ void addMemPred(MemDGNode *PredN) {
+ MemPreds.insert(PredN);
+ if (!Scheduled) {
+ ++PredN->UnscheduledSuccs;
+ }
+ }
/// \Returns true if there is a memory dependency N->this.
bool hasMemPred(DGNode *N) const {
if (auto *MN = dyn_cast<MemDGNode>(N))
@@ -284,6 +300,10 @@ class DependencyGraph {
/// \p DstN.
void scanAndAddDeps(MemDGNode &DstN, const Interval<MemDGNode> &SrcScanRange);
+ /// Sets the UnscheduledSuccs of all DGNodes in \p NewInterval based on
+ /// def-use edges.
+ void setDefUseUnscheduledSuccs(const Interval<Instruction> &NewInterval);
+
/// Create DAG nodes for instrs in \p NewInterval and update the MemNode
/// chain.
void createNewNodes(const Interval<Instruction> &NewInterval);
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
index 01bdd7bbdcefc5..f3371fc78e1a5b 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp
@@ -59,21 +59,17 @@ bool PredIterator::operator==(const PredIterator &Other) const {
}
#ifndef NDEBUG
-void DGNode::print(raw_ostream &OS, bool PrintDeps) const { I->dumpOS(OS); }
-void DGNode::dump() const {
- print(dbgs());
- dbgs() << "\n";
+void DGNode::print(raw_ostream &OS, bool PrintDeps) const {
+ OS << *I << " USuccs:" << UnscheduledSuccs << "\n";
}
+void DGNode::dump() const { print(dbgs()); }
void MemDGNode::print(raw_ostream &OS, bool PrintDeps) const {
- I->dumpOS(OS);
+ DGNode::print(OS, false);
if (PrintDeps) {
// Print memory preds.
static constexpr const unsigned Indent = 4;
- for (auto *Pred : MemPreds) {
- OS.indent(Indent) << "<-";
- Pred->print(OS, false);
- OS << "\n";
- }
+ for (auto *Pred : MemPreds)
+ OS.indent(Indent) << "<-" << *Pred->getInstruction() << "\n";
}
}
#endif // NDEBUG
@@ -215,6 +211,51 @@ void DependencyGraph::scanAndAddDeps(MemDGNode &DstN,
}
}
+void DependencyGraph::setDefUseUnscheduledSuccs(
+ const Interval<Instruction> &NewInterval) {
+ // Set the intra-interval counters in NewInterval.
+ for (Instruction &I : NewInterval) {
+ for (Value *Op : I.operands()) {
+ auto *OpI = dyn_cast<Instruction>(Op);
+ if (OpI == nullptr)
+ continue;
+ // TODO: Check if OpI is in NewInterval to save compile time?
+ auto *OpN = getNode(OpI);
+ if (OpN == nullptr)
+ continue;
+ ++OpN->UnscheduledSuccs;
+ }
+ }
+
+ // Now handle the cross-interval edges.
+ bool NewIsAbove = DAGInterval.empty() || NewInterval.comesBefore(DAGInterval);
+ const auto &TopInterval = NewIsAbove ? NewInterval : DAGInterval;
+ const auto &BotInterval = NewIsAbove ? DAGInterval : NewInterval;
+ // -
+ // | TopInterval
+ // | Def
+ // - |
+ // | v BotInterval
+ // | Use
+ // |
+ // -
+ // Walk over all instructions in "BotInterval" and update the counter
+ // of operands that are in "TopInterval".
+ for (Instruction &BotI : BotInterval) {
+ for (Value *Op : BotI.operands()) {
+ auto *OpI = dyn_cast<Instruction>(Op);
+ if (OpI == nullptr)
+ continue;
+ if (!TopInterval.contains(OpI))
+ continue;
+ auto *OpN = getNode(OpI);
+ if (OpN == nullptr)
+ continue;
+ ++OpN->UnscheduledSuccs;
+ }
+ }
+}
+
void DependencyGraph::createNewNodes(const Interval<Instruction> &NewInterval) {
// Create Nodes only for the new sections of the DAG.
DGNode *LastN = getOrCreateNode(NewInterval.top());
@@ -260,6 +301,8 @@ void DependencyGraph::createNewNodes(const Interval<Instruction> &NewInterval) {
}
#endif // NDEBUG
}
+
+ setDefUseUnscheduledSuccs(NewInterval);
}
Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp
index 3dbf03e4ba44e2..3f84ad1f731de8 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp
@@ -249,6 +249,11 @@ define void @foo(ptr %ptr, i8 %v0, i8 %v1) {
EXPECT_TRUE(N0->memPreds().empty());
EXPECT_THAT(N1->memPreds(), testing::ElementsAre(N0));
EXPECT_TRUE(N2->preds(DAG).empty());
+
+ // Check UnscheduledSuccs.
+ EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u); // N1
+ EXPECT_EQ(N1->getNumUnscheduledSuccs(), 0u);
+ EXPECT_EQ(N2->getNumUnscheduledSuccs(), 0u);
}
TEST_F(DependencyGraphTest, Preds) {
@@ -286,6 +291,14 @@ define i8 @foo(i8 %v0, i8 %v1) {
EXPECT_THAT(StN->preds(DAG),
testing::UnorderedElementsAre(CallN, CallN, AddN2));
EXPECT_THAT(RetN->preds(DAG), testing::ElementsAre(AddN2));
+
+ // Check UnscheduledSuccs.
+ EXPECT_EQ(AddN0->getNumUnscheduledSuccs(), 1u); // AddN2
+ EXPECT_EQ(AddN1->getNumUnscheduledSuccs(), 2u); // AddN2, CallN
+ EXPECT_EQ(AddN2->getNumUnscheduledSuccs(), 2u); // StN, RetN
+ EXPECT_EQ(CallN->getNumUnscheduledSuccs(), 2u); // StN, StN
+ EXPECT_EQ(StN->getNumUnscheduledSuccs(), 0u);
+ EXPECT_EQ(RetN->getNumUnscheduledSuccs(), 0u);
}
TEST_F(DependencyGraphTest, MemDGNode_getPrevNode_getNextNode) {
@@ -711,6 +724,8 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
EXPECT_EQ(DAG.getInterval().top(), S3);
EXPECT_EQ(DAG.getInterval().bottom(), S3);
[[maybe_unused]] auto *S3N = cast<sandboxir::MemDGNode>(DAG.getNode(S3));
+ // Check UnscheduledSuccs.
+ EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 0u);
}
{
// Scenario 2: Extend below
@@ -722,6 +737,10 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
EXPECT_TRUE(S4N->hasMemPred(S3N));
EXPECT_TRUE(S5N->hasMemPred(S4N));
EXPECT_TRUE(S5N->hasMemPred(S3N));
+ // Check UnscheduledSuccs.
+ EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 2u); // S4N, S5N
+ EXPECT_EQ(S4N->getNumUnscheduledSuccs(), 1u); // S5N
+ EXPECT_EQ(S5N->getNumUnscheduledSuccs(), 0u);
}
{
// Scenario 3: Extend above
@@ -746,5 +765,12 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
EXPECT_TRUE(S5N->hasMemPred(S3N));
EXPECT_TRUE(S5N->hasMemPred(S2N));
EXPECT_TRUE(S5N->hasMemPred(S1N));
+
+ // Check UnscheduledSuccs.
+ EXPECT_EQ(S1N->getNumUnscheduledSuccs(), 4u); // S2N, S3N, S4N, S5N
+ EXPECT_EQ(S2N->getNumUnscheduledSuccs(), 3u); // S3N, S4N, S5N
+ EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 2u); // S4N, S5N
+ EXPECT_EQ(S4N->getNumUnscheduledSuccs(), 1u); // S5N
+ EXPECT_EQ(S5N->getNumUnscheduledSuccs(), 0u);
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/112255
More information about the llvm-commits
mailing list