Skip to content

Commit 07600f8

Browse files
authored
[SandboxVec][Scheduler] Update ready list comparator (#126160)
This patch implements a hierarchical comparator for the ready list. PHIs have higher priority than non-phis and terminators are always last.
1 parent ad905f1 commit 07600f8

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,23 @@ namespace llvm::sandboxir {
3030
class PriorityCmp {
3131
public:
3232
bool operator()(const DGNode *N1, const DGNode *N2) {
33-
// TODO: This should be a hierarchical comparator.
34-
return N1->getInstruction()->comesBefore(N2->getInstruction());
33+
// Given that the DAG does not model dependencies such that PHIs are always
34+
// at the top, or terminators always at the bottom, we need to force the
35+
// priority here in the comparator of the ready list container.
36+
auto *I1 = N1->getInstruction();
37+
auto *I2 = N2->getInstruction();
38+
bool IsTerm1 = I1->isTerminator();
39+
bool IsTerm2 = I2->isTerminator();
40+
if (IsTerm1 != IsTerm2)
41+
// Terminators have the lowest priority.
42+
return IsTerm1 > IsTerm2;
43+
bool IsPHI1 = isa<PHINode>(I1);
44+
bool IsPHI2 = isa<PHINode>(I2);
45+
if (IsPHI1 != IsPHI2)
46+
// PHIs have the highest priority.
47+
return IsPHI1 < IsPHI2;
48+
// Otherwise rely on the instruction order.
49+
return I2->comesBefore(I1);
3550
}
3651
};
3752

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

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ define void @foo(ptr noalias %ptr0, ptr noalias %ptr1, i8 %v0, i8 %v1) {
253253
%add0 = add i8 %v0, 0
254254
%add1 = add i8 %v1, 1
255255
br label %bb1
256+
256257
bb1:
257258
store i8 %add0, ptr %ptr0
258259
store i8 %add1, ptr %ptr1
@@ -392,3 +393,77 @@ define void @foo(ptr %ptr) {
392393
EXPECT_TRUE(ReadyList.empty());
393394
EXPECT_THAT(Nodes, testing::UnorderedElementsAre(L0N, RetN));
394395
}
396+
397+
TEST_F(SchedulerTest, ReadyListPriorities) {
398+
parseIR(C, R"IR(
399+
define void @foo(ptr %ptr) {
400+
bb0:
401+
br label %bb1
402+
403+
bb1:
404+
%phi0 = phi i8 [0, %bb0], [1, %bb1]
405+
%phi1 = phi i8 [0, %bb0], [1, %bb1]
406+
%ld0 = load i8, ptr %ptr
407+
store i8 %ld0, ptr %ptr
408+
ret void
409+
}
410+
)IR");
411+
llvm::Function *LLVMF = &*M->getFunction("foo");
412+
sandboxir::Context Ctx(C);
413+
auto *F = Ctx.createFunction(LLVMF);
414+
auto *BB1 = getBasicBlockByName(F, "bb1");
415+
auto It = BB1->begin();
416+
auto *Phi0 = cast<sandboxir::PHINode>(&*It++);
417+
auto *Phi1 = cast<sandboxir::PHINode>(&*It++);
418+
auto *L0 = cast<sandboxir::LoadInst>(&*It++);
419+
auto *S0 = cast<sandboxir::StoreInst>(&*It++);
420+
auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
421+
422+
sandboxir::DependencyGraph DAG(getAA(*LLVMF), Ctx);
423+
DAG.extend({&*BB1->begin(), BB1->getTerminator()});
424+
auto *Phi0N = DAG.getNode(Phi0);
425+
auto *Phi1N = DAG.getNode(Phi1);
426+
auto *L0N = DAG.getNode(L0);
427+
auto *S0N = DAG.getNode(S0);
428+
auto *RetN = DAG.getNode(Ret);
429+
430+
sandboxir::ReadyListContainer ReadyList;
431+
// Check PHI vs non-PHI.
432+
ReadyList.insert(S0N);
433+
ReadyList.insert(Phi0N);
434+
EXPECT_EQ(ReadyList.pop(), Phi0N);
435+
EXPECT_EQ(ReadyList.pop(), S0N);
436+
ReadyList.insert(Phi0N);
437+
ReadyList.insert(S0N);
438+
EXPECT_EQ(ReadyList.pop(), Phi0N);
439+
EXPECT_EQ(ReadyList.pop(), S0N);
440+
// Check PHI vs terminator.
441+
ReadyList.insert(RetN);
442+
ReadyList.insert(Phi1N);
443+
EXPECT_EQ(ReadyList.pop(), Phi1N);
444+
EXPECT_EQ(ReadyList.pop(), RetN);
445+
ReadyList.insert(Phi1N);
446+
ReadyList.insert(RetN);
447+
EXPECT_EQ(ReadyList.pop(), Phi1N);
448+
EXPECT_EQ(ReadyList.pop(), RetN);
449+
// Check terminator vs non-terminator.
450+
ReadyList.insert(RetN);
451+
ReadyList.insert(L0N);
452+
EXPECT_EQ(ReadyList.pop(), L0N);
453+
EXPECT_EQ(ReadyList.pop(), RetN);
454+
ReadyList.insert(L0N);
455+
ReadyList.insert(RetN);
456+
EXPECT_EQ(ReadyList.pop(), L0N);
457+
EXPECT_EQ(ReadyList.pop(), RetN);
458+
// Check all, program order.
459+
ReadyList.insert(RetN);
460+
ReadyList.insert(L0N);
461+
ReadyList.insert(Phi1N);
462+
ReadyList.insert(S0N);
463+
ReadyList.insert(Phi0N);
464+
EXPECT_EQ(ReadyList.pop(), Phi0N);
465+
EXPECT_EQ(ReadyList.pop(), Phi1N);
466+
EXPECT_EQ(ReadyList.pop(), L0N);
467+
EXPECT_EQ(ReadyList.pop(), S0N);
468+
EXPECT_EQ(ReadyList.pop(), RetN);
469+
}

0 commit comments

Comments
 (0)