@@ -940,10 +940,11 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %new1, i8 %new2) {
940
940
941
941
TEST_F (DependencyGraphTest, EraseInstrCallback) {
942
942
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) {
944
944
store i8 %v1, ptr %ptr
945
945
store i8 %v2, ptr %ptr
946
946
store i8 %v3, ptr %ptr
947
+ store i8 %v4, ptr %ptr
947
948
ret void
948
949
}
949
950
)IR" );
@@ -955,25 +956,67 @@ define void @foo(ptr %ptr, i8 %v1, i8 %v2, i8 %v3, i8 %arg) {
955
956
auto *S1 = cast<sandboxir::StoreInst>(&*It++);
956
957
auto *S2 = cast<sandboxir::StoreInst>(&*It++);
957
958
auto *S3 = cast<sandboxir::StoreInst>(&*It++);
959
+ auto *S4NotInDAG = cast<sandboxir::StoreInst>(&*It++);
958
960
959
961
// Check erase instruction callback.
960
962
sandboxir::DependencyGraph DAG (getAA (*LLVMF), Ctx);
961
963
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 );
962
970
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);
964
973
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 );
965
978
966
979
// Check the MemDGNode chain.
967
- auto *S1MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S1));
968
- auto *S3MemN = cast<sandboxir::MemDGNode>(DAG.getNode (S3));
969
980
EXPECT_EQ (S1MemN->getNextNode (), S3MemN);
970
981
EXPECT_EQ (S3MemN->getPrevNode (), S1MemN);
971
982
972
983
// Check the chain when we erase the top node.
973
984
S1->eraseFromParent ();
974
985
EXPECT_EQ (S3MemN->getPrevNode (), nullptr );
975
986
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 );
977
1020
}
978
1021
979
1022
TEST_F (DependencyGraphTest, MoveInstrCallback) {
0 commit comments