Skip to content

Commit 48c92dd

Browse files
authored
[SandboxVec][DAG] Update DAG whenever a Use is set (#127247)
This patch implements automatic DAG updating whenever a Use is set. This maintains the UnscheduledSuccs counter that the scheduler relies on.
1 parent 9ad83f7 commit 48c92dd

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ class DependencyGraph {
313313
std::optional<Context::CallbackID> CreateInstrCB;
314314
std::optional<Context::CallbackID> EraseInstrCB;
315315
std::optional<Context::CallbackID> MoveInstrCB;
316+
std::optional<Context::CallbackID> SetUseCB;
316317

317318
std::unique_ptr<BatchAAResults> BatchAA;
318319

@@ -368,6 +369,8 @@ class DependencyGraph {
368369
/// Called by the callbacks when instruction \p I is about to be moved to
369370
/// \p To.
370371
void notifyMoveInstr(Instruction *I, const BBIterator &To);
372+
/// Called by the callbacks when \p U's source is about to be set to \p NewSrc
373+
void notifySetUse(const Use &U, Value *NewSrc);
371374

372375
public:
373376
/// This constructor also registers callbacks.
@@ -381,6 +384,8 @@ class DependencyGraph {
381384
[this](Instruction *I, const BBIterator &To) {
382385
notifyMoveInstr(I, To);
383386
});
387+
SetUseCB = Ctx.registerSetUseCallback(
388+
[this](const Use &U, Value *NewSrc) { notifySetUse(U, NewSrc); });
384389
}
385390
~DependencyGraph() {
386391
if (CreateInstrCB)
@@ -389,6 +394,8 @@ class DependencyGraph {
389394
Ctx->unregisterEraseInstrCallback(*EraseInstrCB);
390395
if (MoveInstrCB)
391396
Ctx->unregisterMoveInstrCallback(*MoveInstrCB);
397+
if (SetUseCB)
398+
Ctx->unregisterSetUseCallback(*SetUseCB);
392399
}
393400

394401
DGNode *getNode(Instruction *I) const {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,21 @@ void DependencyGraph::notifyEraseInstr(Instruction *I) {
498498
// TODO: Update the dependencies.
499499
}
500500

501+
void DependencyGraph::notifySetUse(const Use &U, Value *NewSrc) {
502+
// Update the UnscheduledSuccs counter for both the current source and NewSrc
503+
// if needed.
504+
if (auto *CurrSrcI = dyn_cast<Instruction>(U.get())) {
505+
if (auto *CurrSrcN = getNode(CurrSrcI)) {
506+
CurrSrcN->decrUnscheduledSuccs();
507+
}
508+
}
509+
if (auto *NewSrcI = dyn_cast<Instruction>(NewSrc)) {
510+
if (auto *NewSrcN = getNode(NewSrcI)) {
511+
++NewSrcN->UnscheduledSuccs;
512+
}
513+
}
514+
}
515+
501516
Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
502517
if (Instrs.empty())
503518
return {};

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,3 +1052,55 @@ define void @foo(ptr %ptr, i8 %v, i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
10521052
DAG.extend({S0, S1});
10531053
EXPECT_TRUE(memDependency(DAG.getNode(S0), DAG.getNode(S1)));
10541054
}
1055+
1056+
// Setting a Use with a setOperand(), RUW, RAUW etc. can add/remove use-def
1057+
// edges. This needs to maintain the UnscheduledSuccs counter.
1058+
TEST_F(DependencyGraphTest, MaintainUnscheduledSuccsOnUseSet) {
1059+
parseIR(C, R"IR(
1060+
define void @foo(i8 %v0, i8 %v1) {
1061+
%add0 = add i8 %v0, %v1
1062+
%add1 = add i8 %add0, %v1
1063+
ret void
1064+
}
1065+
)IR");
1066+
llvm::Function *LLVMF = &*M->getFunction("foo");
1067+
sandboxir::Context Ctx(C);
1068+
auto *F = Ctx.createFunction(LLVMF);
1069+
auto *Arg0 = F->getArg(0);
1070+
auto *BB = &*F->begin();
1071+
auto It = BB->begin();
1072+
auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++);
1073+
auto *Add1 = cast<sandboxir::BinaryOperator>(&*It++);
1074+
sandboxir::DependencyGraph DAG(getAA(*LLVMF), Ctx);
1075+
DAG.extend({Add0, Add1});
1076+
auto *N0 = DAG.getNode(Add0);
1077+
1078+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u);
1079+
// Now change %add1 operand to not use %add0.
1080+
Add1->setOperand(0, Arg0);
1081+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 0u);
1082+
// Restore it: %add0 is now used by %add1.
1083+
Add1->setOperand(0, Add0);
1084+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u);
1085+
1086+
// RAUW
1087+
Add0->replaceAllUsesWith(Arg0);
1088+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 0u);
1089+
// Restore it: %add0 is now used by %add1.
1090+
Add1->setOperand(0, Add0);
1091+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u);
1092+
1093+
// RUWIf
1094+
Add0->replaceUsesWithIf(Arg0, [](const auto &U) { return true; });
1095+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 0u);
1096+
// Restore it: %add0 is now used by %add1.
1097+
Add1->setOperand(0, Add0);
1098+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u);
1099+
1100+
// RUOW
1101+
Add1->replaceUsesOfWith(Add0, Arg0);
1102+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 0u);
1103+
// Restore it: %add0 is now used by %add1.
1104+
Add1->setOperand(0, Add0);
1105+
EXPECT_EQ(N0->getNumUnscheduledSuccs(), 1u);
1106+
}

0 commit comments

Comments
 (0)