diff --git a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp --- a/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CodeMoverUtilsTest.cpp @@ -514,8 +514,8 @@ // Moving instruction to non control flow equivalent places are not // supported. - EXPECT_FALSE(isSafeToMoveBefore(*SI_A5, *Entry->getTerminator(), DT, - &PDT, &DI)); + EXPECT_FALSE( + isSafeToMoveBefore(*SI_A5, *Entry->getTerminator(), DT, &PDT, &DI)); // Moving PHINode is not supported. EXPECT_FALSE(isSafeToMoveBefore(PN, *PN.getNextNode()->getNextNode(), @@ -652,3 +652,198 @@ EXPECT_FALSE(isSafeToMoveBefore(*SubInst, *AddInst, DT, &PDT, &DI)); }); } + +TEST(CodeMoverUtils, IsSafeToMoveTest5) { + LLVMContext C; + + std::unique_ptr M = + parseIR(C, R"(define void @dependence(i32* noalias %A, i32* noalias %B){ +entry: + store i32 0, i32* %A, align 4 ; storeA0 + store i32 2, i32* %A, align 4 ; storeA1 + %tmp0 = load i32, i32* %A, align 4 ; loadA0 + store i32 1, i32* %B, align 4 ; storeB0 + %tmp1 = load i32, i32* %A, align 4 ; loadA1 + store i32 2, i32* %A, align 4 ; storeA2 + store i32 4, i32* %B, align 4 ; StoreB1 + %tmp2 = load i32, i32* %A, align 4 ; loadA2 + %tmp3 = load i32, i32* %A, align 4 ; loadA3 + %tmp4 = load i32, i32* %B, align 4 ; loadB2 + %tmp5 = load i32, i32* %B, align 4 ; loadB3 + ret void +})"); + + run(*M, "dependence", + [&](Function &F, DominatorTree &DT, PostDominatorTree &PDT, + DependenceInfo &DI) { + Instruction *LoadA0 = getInstructionByName(F, "tmp0"); + Instruction *StoreA1 = LoadA0->getPrevNode(); + Instruction *StoreA0 = StoreA1->getPrevNode(); + // Output forward dependency + EXPECT_FALSE(isSafeToMoveBefore(*StoreA0, *LoadA0, DT, &PDT, &DI)); + // Output backward dependency + EXPECT_FALSE(isSafeToMoveBefore(*StoreA1, *StoreA0, DT, &PDT, &DI)); + + Instruction *LoadA2 = getInstructionByName(F, "tmp2"); + Instruction *StoreB1 = LoadA2->getPrevNode(); + Instruction *StoreA2 = StoreB1->getPrevNode(); + // No Output forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*StoreA2, *LoadA2, DT, &PDT, &DI)); + // No Output backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*StoreB1, *StoreA2, DT, &PDT, &DI)); + + Instruction *StoreB0 = LoadA0->getNextNode(); + // Flow backward dependency + EXPECT_FALSE(isSafeToMoveBefore(*LoadA0, *StoreA1, DT, &PDT, &DI)); + // Flow forward dependency + EXPECT_FALSE(isSafeToMoveBefore(*StoreA1, *StoreB0, DT, &PDT, &DI)); + + Instruction *LoadA1 = getInstructionByName(F, "tmp1"); + // Anti backward dependency + EXPECT_FALSE(isSafeToMoveBefore(*StoreA2, *LoadA1, DT, &PDT, &DI)); + // Anti forward dependency + EXPECT_FALSE(isSafeToMoveBefore(*LoadA1, *StoreB1, DT, &PDT, &DI)); + // No flow forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*StoreB0, *StoreA2, DT, &PDT, &DI)); + // No flow backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA1, *StoreB0, DT, &PDT, &DI)); + // No anti backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*StoreB0, *LoadA0, DT, &PDT, &DI)); + // No anti forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA0, *LoadA1, DT, &PDT, &DI)); + + Instruction *LoadA3 = getInstructionByName(F, "tmp3"); + Instruction *LoadB2 = getInstructionByName(F, "tmp4"); + Instruction *LoadB3 = getInstructionByName(F, "tmp5"); + // Input forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA2, *LoadB2, DT, &PDT, &DI)); + // Input backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA3, *LoadA2, DT, &PDT, &DI)); + // No input backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadB2, *LoadA3, DT, &PDT, &DI)); + // No input forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA3, *LoadB3, DT, &PDT, &DI)); + }); +} + +TEST(CodeMoverUtils, IsSafeToMoveTest6) { + LLVMContext C; + + std::unique_ptr M = parseIR( + C, R"(define void @dependence(i1 %cond, i32* noalias %A, i32* noalias %B){ + entry: + br i1 %cond, label %bb0, label %bb1 + bb0: + store i32 0, i32* %A, align 4 ; storeA0 + br label %bb1 + bb1: + br i1 %cond, label %bb2, label %bb3 + bb2: + store i32 2, i32* %A, align 4 ; storeA1 + br label %bb3 + bb3: + br i1 %cond, label %bb4, label %bb5 + bb4: + %tmp0 = load i32, i32* %A, align 4 ; loadA0 + br label %bb5 + bb5: + br i1 %cond, label %bb6, label %bb7 + bb6: + store i32 1, i32* %B, align 4 ; storeB0 + br label %bb7 + bb7: + br i1 %cond, label %bb8, label %bb9 + bb8: + %tmp1 = load i32, i32* %A, align 4 ; loadA1 + br label %bb8 + bb9: + br i1 %cond, label %bb10, label %bb11 + bb10: + store i32 2, i32* %A, align 4 ; storeA2 + br label %bb11 + bb11: + br i1 %cond, label %bb12, label %bb13 + bb12: + store i32 4, i32* %B, align 4 ; StoreB1 + br label %bb13 + bb13: + br i1 %cond, label %bb14, label %bb15 + bb14: + %tmp2 = load i32, i32* %A, align 4 ; loadA2 + br label %bb15 + bb15: + br i1 %cond, label %bb16, label %bb17 + bb16: + %tmp3 = load i32, i32* %A, align 4 ; loadA3 + br label %bb17 + bb17: + br i1 %cond, label %bb18, label %bb19 + bb18: + %tmp4 = load i32, i32* %B, align 4 ; loadB2 + br label %bb19 + bb19: + br i1 %cond, label %bb20, label %bb21 + bb20: + %tmp5 = load i32, i32* %B, align 4 ; loadB3 + br label %bb21 + bb21: + ret void + })"); + + run(*M, "dependence", + [&](Function &F, DominatorTree &DT, PostDominatorTree &PDT, + DependenceInfo &DI) { + Instruction *LoadA0 = getInstructionByName(F, "tmp0"); + BasicBlock *BB2 = getBasicBlockByName(F, "bb2"); + Instruction &StoreA1 = BB2->front(); + BasicBlock *BB0 = getBasicBlockByName(F, "bb0"); + Instruction &StoreA0 = BB0->front(); + // Output forward dependency + EXPECT_FALSE(isSafeToMoveBefore(StoreA0, *LoadA0, DT, &PDT, &DI)); + // Output backward dependency + EXPECT_FALSE(isSafeToMoveBefore(StoreA1, StoreA0, DT, &PDT, &DI)); + + Instruction *LoadA2 = getInstructionByName(F, "tmp2"); + BasicBlock *BB12 = getBasicBlockByName(F, "bb12"); + Instruction &StoreB1 = BB12->front(); + BasicBlock *BB10 = getBasicBlockByName(F, "bb10"); + Instruction &StoreA2 = BB10->front(); + // No Output forward dependency + EXPECT_TRUE(isSafeToMoveBefore(StoreA2, *LoadA2, DT, &PDT, &DI)); + // No Output backward dependency + EXPECT_TRUE(isSafeToMoveBefore(StoreB1, StoreA2, DT, &PDT, &DI)); + + BasicBlock *BB6 = getBasicBlockByName(F, "bb6"); + Instruction &StoreB0 = BB6->front(); + // Flow backward dependency + EXPECT_FALSE(isSafeToMoveBefore(*LoadA0, StoreA1, DT, &PDT, &DI)); + // Flow forward dependency + EXPECT_FALSE(isSafeToMoveBefore(StoreA1, StoreB0, DT, &PDT, &DI)); + + Instruction *LoadA1 = getInstructionByName(F, "tmp1"); + // Anti backward dependency + EXPECT_FALSE(isSafeToMoveBefore(StoreA2, *LoadA1, DT, &PDT, &DI)); + // Anti forward dependency + EXPECT_FALSE(isSafeToMoveBefore(*LoadA1, StoreB1, DT, &PDT, &DI)); + // No flow forward dependency + EXPECT_TRUE(isSafeToMoveBefore(StoreB0, StoreA2, DT, &PDT, &DI)); + // No flow backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA1, StoreB0, DT, &PDT, &DI)); + // No anti backward dependency + EXPECT_TRUE(isSafeToMoveBefore(StoreB0, *LoadA0, DT, &PDT, &DI)); + // No anti forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA0, *LoadA1, DT, &PDT, &DI)); + + Instruction *LoadA3 = getInstructionByName(F, "tmp3"); + Instruction *LoadB2 = getInstructionByName(F, "tmp4"); + Instruction *LoadB3 = getInstructionByName(F, "tmp5"); + // Input forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA2, *LoadB2, DT, &PDT, &DI)); + // Input backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA3, *LoadA2, DT, &PDT, &DI)); + // No input backward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadB2, *LoadA3, DT, &PDT, &DI)); + // No input forward dependency + EXPECT_TRUE(isSafeToMoveBefore(*LoadA3, *LoadB3, DT, &PDT, &DI)); + }); +}