Skip to content

Commit 16a5b6e

Browse files
vporpoDanielCChen
authored andcommitted
[SandboxVec][DAG] Implement UnscheduledSuccs (llvm#112255)
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.
1 parent b4397bc commit 16a5b6e

File tree

3 files changed

+110
-13
lines changed

3 files changed

+110
-13
lines changed

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,25 @@ class DGNode {
9696
// TODO: Use a PointerIntPair for SubclassID and I.
9797
/// For isa/dyn_cast etc.
9898
DGNodeID SubclassID;
99+
/// The number of unscheduled successors.
100+
unsigned UnscheduledSuccs = 0;
101+
/// This is true if this node has been scheduled.
102+
bool Scheduled = false;
99103

100104
DGNode(Instruction *I, DGNodeID ID) : I(I), SubclassID(ID) {}
101-
friend class MemDGNode; // For constructor.
105+
friend class MemDGNode; // For constructor.
106+
friend class DependencyGraph; // For UnscheduledSuccs
102107

103108
public:
104109
DGNode(Instruction *I) : I(I), SubclassID(DGNodeID::DGNode) {
105110
assert(!isMemDepNodeCandidate(I) && "Expected Non-Mem instruction, ");
106111
}
107112
DGNode(const DGNode &Other) = delete;
108113
virtual ~DGNode() = default;
114+
/// \Returns the number of unscheduled successors.
115+
unsigned getNumUnscheduledSuccs() const { return UnscheduledSuccs; }
116+
/// \Returns true if this node has been scheduled.
117+
bool scheduled() const { return Scheduled; }
109118
/// \Returns true if this is before \p Other in program order.
110119
bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); }
111120
using iterator = PredIterator;
@@ -215,8 +224,16 @@ class MemDGNode final : public DGNode {
215224
MemDGNode *getPrevNode() const { return PrevMemN; }
216225
/// \Returns the next Mem DGNode in instruction order.
217226
MemDGNode *getNextNode() const { return NextMemN; }
218-
/// Adds the mem dependency edge PredN->this.
219-
void addMemPred(MemDGNode *PredN) { MemPreds.insert(PredN); }
227+
/// Adds the mem dependency edge PredN->this. This also increments the
228+
/// UnscheduledSuccs counter of the predecessor if this node has not been
229+
/// scheduled.
230+
void addMemPred(MemDGNode *PredN) {
231+
auto Inserted = MemPreds.insert(PredN).second;
232+
assert(Inserted && "PredN already exists!");
233+
if (!Scheduled) {
234+
++PredN->UnscheduledSuccs;
235+
}
236+
}
220237
/// \Returns true if there is a memory dependency N->this.
221238
bool hasMemPred(DGNode *N) const {
222239
if (auto *MN = dyn_cast<MemDGNode>(N))
@@ -284,6 +301,10 @@ class DependencyGraph {
284301
/// \p DstN.
285302
void scanAndAddDeps(MemDGNode &DstN, const Interval<MemDGNode> &SrcScanRange);
286303

304+
/// Sets the UnscheduledSuccs of all DGNodes in \p NewInterval based on
305+
/// def-use edges.
306+
void setDefUseUnscheduledSuccs(const Interval<Instruction> &NewInterval);
307+
287308
/// Create DAG nodes for instrs in \p NewInterval and update the MemNode
288309
/// chain.
289310
void createNewNodes(const Interval<Instruction> &NewInterval);

llvm/lib/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.cpp

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,17 @@ bool PredIterator::operator==(const PredIterator &Other) const {
5959
}
6060

6161
#ifndef NDEBUG
62-
void DGNode::print(raw_ostream &OS, bool PrintDeps) const { I->dumpOS(OS); }
63-
void DGNode::dump() const {
64-
print(dbgs());
65-
dbgs() << "\n";
62+
void DGNode::print(raw_ostream &OS, bool PrintDeps) const {
63+
OS << *I << " USuccs:" << UnscheduledSuccs << "\n";
6664
}
65+
void DGNode::dump() const { print(dbgs()); }
6766
void MemDGNode::print(raw_ostream &OS, bool PrintDeps) const {
68-
I->dumpOS(OS);
67+
DGNode::print(OS, false);
6968
if (PrintDeps) {
7069
// Print memory preds.
7170
static constexpr const unsigned Indent = 4;
72-
for (auto *Pred : MemPreds) {
73-
OS.indent(Indent) << "<-";
74-
Pred->print(OS, false);
75-
OS << "\n";
76-
}
71+
for (auto *Pred : MemPreds)
72+
OS.indent(Indent) << "<-" << *Pred->getInstruction() << "\n";
7773
}
7874
}
7975
#endif // NDEBUG
@@ -215,6 +211,58 @@ void DependencyGraph::scanAndAddDeps(MemDGNode &DstN,
215211
}
216212
}
217213

214+
void DependencyGraph::setDefUseUnscheduledSuccs(
215+
const Interval<Instruction> &NewInterval) {
216+
// +---+
217+
// | | Def
218+
// | | |
219+
// | | v
220+
// | | Use
221+
// +---+
222+
// Set the intra-interval counters in NewInterval.
223+
for (Instruction &I : NewInterval) {
224+
for (Value *Op : I.operands()) {
225+
auto *OpI = dyn_cast<Instruction>(Op);
226+
if (OpI == nullptr)
227+
continue;
228+
if (!NewInterval.contains(OpI))
229+
continue;
230+
auto *OpN = getNode(OpI);
231+
if (OpN == nullptr)
232+
continue;
233+
++OpN->UnscheduledSuccs;
234+
}
235+
}
236+
237+
// Now handle the cross-interval edges.
238+
bool NewIsAbove = DAGInterval.empty() || NewInterval.comesBefore(DAGInterval);
239+
const auto &TopInterval = NewIsAbove ? NewInterval : DAGInterval;
240+
const auto &BotInterval = NewIsAbove ? DAGInterval : NewInterval;
241+
// +---+
242+
// |Top|
243+
// | | Def
244+
// +---+ |
245+
// | | v
246+
// |Bot| Use
247+
// | |
248+
// +---+
249+
// Walk over all instructions in "BotInterval" and update the counter
250+
// of operands that are in "TopInterval".
251+
for (Instruction &BotI : BotInterval) {
252+
for (Value *Op : BotI.operands()) {
253+
auto *OpI = dyn_cast<Instruction>(Op);
254+
if (OpI == nullptr)
255+
continue;
256+
if (!TopInterval.contains(OpI))
257+
continue;
258+
auto *OpN = getNode(OpI);
259+
if (OpN == nullptr)
260+
continue;
261+
++OpN->UnscheduledSuccs;
262+
}
263+
}
264+
}
265+
218266
void DependencyGraph::createNewNodes(const Interval<Instruction> &NewInterval) {
219267
// Create Nodes only for the new sections of the DAG.
220268
DGNode *LastN = getOrCreateNode(NewInterval.top());
@@ -260,6 +308,8 @@ void DependencyGraph::createNewNodes(const Interval<Instruction> &NewInterval) {
260308
}
261309
#endif // NDEBUG
262310
}
311+
312+
setDefUseUnscheduledSuccs(NewInterval);
263313
}
264314

265315
Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@ define void @foo(ptr %ptr, i8 %v0, i8 %v1) {
249249
EXPECT_TRUE(N0->memPreds().empty());
250250
EXPECT_THAT(N1->memPreds(), testing::ElementsAre(N0));
251251
EXPECT_TRUE(N2->preds(DAG).empty());
252+
253+
// Check UnscheduledSuccs.
254+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u); // N1
255+
EXPECT_EQ(N1->getNumUnscheduledSuccs(), 0u);
256+
EXPECT_EQ(N2->getNumUnscheduledSuccs(), 0u);
252257
}
253258

254259
TEST_F(DependencyGraphTest, Preds) {
@@ -286,6 +291,14 @@ define i8 @foo(i8 %v0, i8 %v1) {
286291
EXPECT_THAT(StN->preds(DAG),
287292
testing::UnorderedElementsAre(CallN, CallN, AddN2));
288293
EXPECT_THAT(RetN->preds(DAG), testing::ElementsAre(AddN2));
294+
295+
// Check UnscheduledSuccs.
296+
EXPECT_EQ(AddN0->getNumUnscheduledSuccs(), 1u); // AddN2
297+
EXPECT_EQ(AddN1->getNumUnscheduledSuccs(), 2u); // AddN2, CallN
298+
EXPECT_EQ(AddN2->getNumUnscheduledSuccs(), 2u); // StN, RetN
299+
EXPECT_EQ(CallN->getNumUnscheduledSuccs(), 2u); // StN, StN
300+
EXPECT_EQ(StN->getNumUnscheduledSuccs(), 0u);
301+
EXPECT_EQ(RetN->getNumUnscheduledSuccs(), 0u);
289302
}
290303

291304
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) {
711724
EXPECT_EQ(DAG.getInterval().top(), S3);
712725
EXPECT_EQ(DAG.getInterval().bottom(), S3);
713726
[[maybe_unused]] auto *S3N = cast<sandboxir::MemDGNode>(DAG.getNode(S3));
727+
// Check UnscheduledSuccs.
728+
EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 0u);
714729
}
715730
{
716731
// Scenario 2: Extend below
@@ -722,6 +737,10 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
722737
EXPECT_TRUE(S4N->hasMemPred(S3N));
723738
EXPECT_TRUE(S5N->hasMemPred(S4N));
724739
EXPECT_TRUE(S5N->hasMemPred(S3N));
740+
// Check UnscheduledSuccs.
741+
EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 2u); // S4N, S5N
742+
EXPECT_EQ(S4N->getNumUnscheduledSuccs(), 1u); // S5N
743+
EXPECT_EQ(S5N->getNumUnscheduledSuccs(), 0u);
725744
}
726745
{
727746
// Scenario 3: Extend above
@@ -746,5 +765,12 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
746765
EXPECT_TRUE(S5N->hasMemPred(S3N));
747766
EXPECT_TRUE(S5N->hasMemPred(S2N));
748767
EXPECT_TRUE(S5N->hasMemPred(S1N));
768+
769+
// Check UnscheduledSuccs.
770+
EXPECT_EQ(S1N->getNumUnscheduledSuccs(), 4u); // S2N, S3N, S4N, S5N
771+
EXPECT_EQ(S2N->getNumUnscheduledSuccs(), 3u); // S3N, S4N, S5N
772+
EXPECT_EQ(S3N->getNumUnscheduledSuccs(), 2u); // S4N, S5N
773+
EXPECT_EQ(S4N->getNumUnscheduledSuccs(), 1u); // S5N
774+
EXPECT_EQ(S5N->getNumUnscheduledSuccs(), 0u);
749775
}
750776
}

0 commit comments

Comments
 (0)