[llvm] [SandboxVec][Scheduler][DAG] Fix the update of DGNode on setOperand (PR #214110)
Anshil Gandhi via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 7 10:54:05 PDT 2026
gandhi56 wrote:
Hey @vporpo, could you try this test:
```
// Rewiring a use while a schedule is live must not leave a stale entry in the
// ready list. `DependencyGraph::notifySetUse()` bumps the UnscheduledSuccs
// counter of the new operand's node, which makes that node un-ready, but
// nothing removes it from the scheduler's ready list. Compare with
// `Scheduler::notifyCreateInstr()`, which calls `ReadyList.remove()` before
// incrementing the counter. `tryScheduleUntil()` then pops the stale node and,
// since it does not belong to a bundle yet, schedules it as a singleton
// without re-checking readiness, placing the definition below its user.
TEST_F(SchedulerTest, StaleReadyListAfterSetUse_BottomUp) {
parseIR(C, R"IR(
define void @foo(ptr %ptr, i8 %arg) {
%t = add i8 %arg, %arg
%p = add i8 %arg, %arg
%u = add i8 %arg, %arg
%x = add i8 %u, %arg
store i8 %arg, ptr %ptr
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
auto *BB = &*F->begin();
auto It = BB->begin();
auto *T = cast<sandboxir::BinaryOperator>(&*It++);
auto *P = cast<sandboxir::BinaryOperator>(&*It++);
auto *U = cast<sandboxir::BinaryOperator>(&*It++);
auto *X = cast<sandboxir::BinaryOperator>(&*It++);
auto *S = cast<sandboxir::StoreInst>(&*It++);
sandboxir::Scheduler Sched(getAA(*LLVMF), Ctx, BottomUp);
auto &DAG = sandboxir::SchedulerInternalsAttorney::getDAG(Sched);
EXPECT_TRUE(Sched.trySchedule({S}));
// This extends the DAG up to %t and puts %t, %p and %x in the ready list (%u
// is not ready because %x uses it). Only %t gets scheduled because it is the
// first one popped, so %p and %x are left in the ready list.
EXPECT_TRUE(Sched.trySchedule({T}));
auto *PN = DAG.getNode(P);
auto *UN = DAG.getNode(U);
ASSERT_FALSE(PN->scheduled());
ASSERT_FALSE(UN->scheduled());
ASSERT_EQ(PN->getNumUnscheduledSuccs(), 0u);
// Add the def-use edge %p->%u. %p is no longer ready, but it is still sitting
// in the ready list.
U->setOperand(0, P);
EXPECT_EQ(PN->getNumUnscheduledSuccs(), 1u);
// Scheduling %x pops the stale %p first and schedules it.
EXPECT_TRUE(Sched.trySchedule({X}));
// %p must not be scheduled while it still has an unscheduled successor, and
// it must not end up below the user we just wired it to.
EXPECT_FALSE(PN->scheduled() && !UN->scheduled());
EXPECT_TRUE(P->comesBefore(U));
}
```
https://github.com/llvm/llvm-project/pull/214110
More information about the llvm-commits
mailing list