@@ -940,10 +940,11 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %new1, i8 %new2) {
940940
941941TEST_F (DependencyGraphTest, EraseInstrCallback) {
942942 parseIR (C, R"IR(
943- define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %arg) {
943+ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 % arg) {
944944 store i8 %v1, ptr %ptr
945945 store i8 %v2, ptr %ptr
946946 store i8 %v3, ptr %ptr
947+ store i8 %v4, ptr %ptr
947948 ret void
948949}
949950)IR" );
@@ -955,25 +956,67 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %arg) {
955956 auto *S1 = cast<sandboxir::StoreInst>(&*It++);
956957 auto *S2 = cast<sandboxir::StoreInst>(&*It++);
957958 auto *S3 = cast<sandboxir::StoreInst>(&*It++);
959+ auto *S4NotInDAG = cast<sandboxir::StoreInst>(&*It++);
958960
959961 // Check erase instruction callback.
960962 sandboxir::DependencyGraph DAG (getAA (*LLVMF), Ctx);
961963 DAG.extend ({S1, S3});
964+ auto *S1MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S1));
965+ auto *S2MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S2));
966+ auto *S3MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S3));
967+ EXPECT_EQ (S1MemN->getNumUnscheduledSuccs (), 2u );
968+ EXPECT_EQ (S2MemN->getNumUnscheduledSuccs (), 1u );
969+ EXPECT_EQ (S3MemN->getNumUnscheduledSuccs (), 0u );
962970 S2->eraseFromParent ();
963- auto *DeletedN = DAG.getNodeOrNull (S2);
971+ // Check that the DAG Node for S2 no longer exists.
972+ auto *DeletedN = DAG.getNode (S2);
964973 EXPECT_TRUE (DeletedN == nullptr );
974+ // Check that dependencies are maintained.
975+ EXPECT_THAT (S3MemN->preds (DAG), testing::UnorderedElementsAre (S1MemN));
976+ // Also check that UnscheduledSuccs was updated for S1.
977+ EXPECT_EQ (S1MemN->getNumUnscheduledSuccs (), 1u );
965978
966979 // Check the MemDGNode chain.
967- auto *S1MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S1));
968- auto *S3MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S3));
969980 EXPECT_EQ (S1MemN->getNextNode (), S3MemN);
970981 EXPECT_EQ (S3MemN->getPrevNode (), S1MemN);
971982
972983 // Check the chain when we erase the top node.
973984 S1->eraseFromParent ();
974985 EXPECT_EQ (S3MemN->getPrevNode (), nullptr );
975986
976- // TODO: Check the dependencies to/from NewSN after they land.
987+ // Check that we don't crash if we erase a node not in the DAG.
988+ S4NotInDAG->eraseFromParent ();
989+ }
990+
991+ // Same but check that we don't update UnscheduledSuccs when Node is scheduled.
992+ TEST_F (DependencyGraphTest, EraseInstrCallbackScheduled) {
993+ parseIR (C, R"IR(
994+ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %arg) {
995+ store i8 %v1, ptr %ptr
996+ store i8 %v2, ptr %ptr
997+ ret void
998+ }
999+ )IR" );
1000+ llvm::Function *LLVMF = &*M->getFunction (" foo" );
1001+ sandboxir::Context Ctx (C);
1002+ auto *F = Ctx.createFunction (LLVMF);
1003+ auto *BB = &*F->begin ();
1004+ auto It = BB->begin ();
1005+ auto *S1 = cast<sandboxir::StoreInst>(&*It++);
1006+ auto *S2 = cast<sandboxir::StoreInst>(&*It++);
1007+
1008+ sandboxir::DependencyGraph DAG (getAA (*LLVMF), Ctx);
1009+ DAG.extend ({S1, S2});
1010+ auto *S1MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S1));
1011+ auto *S2MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S2));
1012+ EXPECT_EQ (S1MemN->getNumUnscheduledSuccs (), 1u );
1013+ EXPECT_EQ (S2MemN->getNumUnscheduledSuccs (), 0u );
1014+ // Mark S2 as scheduled and erase it.
1015+ S2MemN->setScheduled (true );
1016+ S2->eraseFromParent ();
1017+ EXPECT_EQ (DAG.getNode (S2), nullptr );
1018+ // Check that we did not update S1's UnscheduledSuccs
1019+ EXPECT_EQ (S1MemN->getNumUnscheduledSuccs (), 1u );
9771020}
9781021
9791022TEST_F (DependencyGraphTest, MoveInstrCallback) {
0 commit comments