diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h index 781495d949817..e50621b4c1228 100644 --- a/llvm/include/llvm/SandboxIR/Utils.h +++ b/llvm/include/llvm/SandboxIR/Utils.h @@ -17,7 +17,6 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/SandboxIR/Instruction.h" -#include "llvm/SandboxIR/IntrinsicInst.h" #include namespace llvm::sandboxir { @@ -100,31 +99,8 @@ class Utils { return false; return *Diff > 0; } - - static bool isStackSaveOrRestoreIntrinsic(Instruction *I) { - if (auto *II = dyn_cast(I)) { - auto IID = II->getIntrinsicID(); - return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave; - } - return false; - } - - /// \Returns true if intrinsic \p I touches memory. This is used by the - /// dependency graph. - static bool isMemIntrinsic(IntrinsicInst *II) { - auto IID = II->getIntrinsicID(); - return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe; - } - - /// We consider \p I as a Memory Dependency Candidate instruction if it - /// reads/write memory or if it has side-effects. This is used by the - /// dependency graph. - static bool isMemDepCandidate(Instruction *I) { - IntrinsicInst *II; - return I->mayReadOrWriteMemory() && - (!(II = dyn_cast(I)) || isMemIntrinsic(II)); - } }; + } // namespace llvm::sandboxir #endif // LLVM_SANDBOXIR_UTILS_H diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h index e67051821e85c..6333f0b81f9c3 100644 --- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h +++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/DependencyGraph.h @@ -25,7 +25,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/SandboxIR/Instruction.h" -#include "llvm/SandboxIR/Utils.h" +#include "llvm/SandboxIR/IntrinsicInst.h" #include "llvm/Transforms/Vectorize/SandboxVectorizer/Interval.h" namespace llvm::sandboxir { @@ -62,13 +62,37 @@ class DGNode { /// \Returns true if this is before \p Other in program order. bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); } + static bool isStackSaveOrRestoreIntrinsic(Instruction *I) { + if (auto *II = dyn_cast(I)) { + auto IID = II->getIntrinsicID(); + return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave; + } + return false; + } + + /// \Returns true if intrinsic \p I touches memory. This is used by the + /// dependency graph. + static bool isMemIntrinsic(IntrinsicInst *I) { + auto IID = I->getIntrinsicID(); + return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe; + } + + /// We consider \p I as a Memory Dependency Candidate instruction if it + /// reads/write memory or if it has side-effects. This is used by the + /// dependency graph. + static bool isMemDepCandidate(Instruction *I) { + IntrinsicInst *II; + return I->mayReadOrWriteMemory() && + (!(II = dyn_cast(I)) || isMemIntrinsic(II)); + } + /// \Returns true if \p I is a memory dependency candidate instruction. static bool isMemDepNodeCandidate(Instruction *I) { AllocaInst *Alloca; - return Utils::isMemDepCandidate(I) || + return isMemDepCandidate(I) || ((Alloca = dyn_cast(I)) && Alloca->isUsedWithInAlloca()) || - Utils::isStackSaveOrRestoreIntrinsic(I); + isStackSaveOrRestoreIntrinsic(I); } Instruction *getInstruction() const { return I; } diff --git a/llvm/unittests/SandboxIR/UtilsTest.cpp b/llvm/unittests/SandboxIR/UtilsTest.cpp index fd7c423fef75a..a803c2a1cf977 100644 --- a/llvm/unittests/SandboxIR/UtilsTest.cpp +++ b/llvm/unittests/SandboxIR/UtilsTest.cpp @@ -215,103 +215,3 @@ define void @foo(float %arg0, double %arg1, i8 %arg2, i64 %arg3, ptr %arg4) { EXPECT_EQ(sandboxir::Utils::getNumBits(L2), 8u); EXPECT_EQ(sandboxir::Utils::getNumBits(L3), 64u); } - -TEST_F(UtilsTest, Instruction_isStackSaveOrRestoreIntrinsic) { - parseIR(C, R"IR( -declare void @llvm.sideeffect() -define void @foo(i8 %v1, ptr %ptr) { - %add = add i8 %v1, %v1 - %stacksave = call ptr @llvm.stacksave() - call void @llvm.stackrestore(ptr %stacksave) - call void @llvm.sideeffect() - ret void -} -)IR"); - llvm::Function *LLVMF = &*M->getFunction("foo"); - sandboxir::Context Ctx(C); - sandboxir::Function *F = Ctx.createFunction(LLVMF); - auto *BB = &*F->begin(); - auto It = BB->begin(); - auto *Add = cast(&*It++); - auto *StackSave = cast(&*It++); - auto *StackRestore = cast(&*It++); - auto *Other = cast(&*It++); - auto *Ret = cast(&*It++); - - EXPECT_FALSE(sandboxir::Utils::isStackSaveOrRestoreIntrinsic(Add)); - EXPECT_TRUE(sandboxir::Utils::isStackSaveOrRestoreIntrinsic(StackSave)); - EXPECT_TRUE(sandboxir::Utils::isStackSaveOrRestoreIntrinsic(StackRestore)); - EXPECT_FALSE(sandboxir::Utils::isStackSaveOrRestoreIntrinsic(Other)); - EXPECT_FALSE(sandboxir::Utils::isStackSaveOrRestoreIntrinsic(Ret)); -} - -TEST_F(UtilsTest, Instruction_isMemDepCandidate) { - parseIR(C, R"IR( -declare void @llvm.fake.use(...) -declare void @llvm.sideeffect() -declare void @llvm.pseudoprobe(i64, i64, i32, i64) -declare void @bar() -define void @foo(i8 %v1, ptr %ptr) { - %add0 = add i8 %v1, %v1 - %ld0 = load i8, ptr %ptr - store i8 %v1, ptr %ptr - call void @llvm.sideeffect() - call void @llvm.pseudoprobe(i64 42, i64 1, i32 0, i64 -1) - call void @llvm.fake.use(ptr %ptr) - call void @bar() - ret void -} -)IR"); - llvm::Function *LLVMF = &*M->getFunction("foo"); - sandboxir::Context Ctx(C); - sandboxir::Function *F = Ctx.createFunction(LLVMF); - auto *BB = &*F->begin(); - auto It = BB->begin(); - auto *Add0 = cast(&*It++); - auto *Ld0 = cast(&*It++); - auto *St0 = cast(&*It++); - auto *SideEffect0 = cast(&*It++); - auto *PseudoProbe0 = cast(&*It++); - auto *OtherIntrinsic0 = cast(&*It++); - auto *CallBar = cast(&*It++); - auto *Ret = cast(&*It++); - - using Utils = sandboxir::Utils; - - EXPECT_FALSE(Utils::isMemDepCandidate(Add0)); - EXPECT_TRUE(Utils::isMemDepCandidate(Ld0)); - EXPECT_TRUE(Utils::isMemDepCandidate(St0)); - EXPECT_FALSE(Utils::isMemDepCandidate(SideEffect0)); - EXPECT_FALSE(Utils::isMemDepCandidate(PseudoProbe0)); - EXPECT_TRUE(Utils::isMemDepCandidate(OtherIntrinsic0)); - EXPECT_TRUE(Utils::isMemDepCandidate(CallBar)); - EXPECT_FALSE(Utils::isMemDepCandidate(Ret)); -} - -TEST_F(UtilsTest, Instruction_isMemIntrinsic) { - parseIR(C, R"IR( -declare void @llvm.sideeffect() -declare void @llvm.pseudoprobe(i64) -declare void @llvm.assume(i1) - -define void @foo(ptr %ptr, i1 %cond) { - call void @llvm.sideeffect() - call void @llvm.pseudoprobe(i64 42) - call void @llvm.assume(i1 %cond) - ret void -} -)IR"); - llvm::Function *LLVMF = &*M->getFunction("foo"); - sandboxir::Context Ctx(C); - sandboxir::Function *F = Ctx.createFunction(LLVMF); - auto *BB = &*F->begin(); - auto It = BB->begin(); - auto *SideEffect = cast(&*It++); - auto *PseudoProbe = cast(&*It++); - auto *OtherIntrinsic = cast(&*It++); - using Utils = sandboxir::Utils; - - EXPECT_FALSE(Utils::isMemIntrinsic(SideEffect)); - EXPECT_FALSE(Utils::isMemIntrinsic(PseudoProbe)); - EXPECT_TRUE(Utils::isMemIntrinsic(OtherIntrinsic)); -} diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp index 28ab38ce3d353..fb8d3780684f8 100644 --- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/DependencyGraphTest.cpp @@ -29,6 +29,107 @@ struct DependencyGraphTest : public testing::Test { } }; +TEST_F(DependencyGraphTest, isStackSaveOrRestoreIntrinsic) { + parseIR(C, R"IR( +declare void @llvm.sideeffect() +define void @foo(i8 %v1, ptr %ptr) { + %add = add i8 %v1, %v1 + %stacksave = call ptr @llvm.stacksave() + call void @llvm.stackrestore(ptr %stacksave) + call void @llvm.sideeffect() + ret void +} +)IR"); + llvm::Function *LLVMF = &*M->getFunction("foo"); + sandboxir::Context Ctx(C); + sandboxir::Function *F = Ctx.createFunction(LLVMF); + auto *BB = &*F->begin(); + auto It = BB->begin(); + auto *Add = cast(&*It++); + auto *StackSave = cast(&*It++); + auto *StackRestore = cast(&*It++); + auto *Other = cast(&*It++); + auto *Ret = cast(&*It++); + + using DGNode = sandboxir::DGNode; + EXPECT_FALSE(DGNode::isStackSaveOrRestoreIntrinsic(Add)); + EXPECT_TRUE(DGNode::isStackSaveOrRestoreIntrinsic(StackSave)); + EXPECT_TRUE(DGNode::isStackSaveOrRestoreIntrinsic(StackRestore)); + EXPECT_FALSE(DGNode::isStackSaveOrRestoreIntrinsic(Other)); + EXPECT_FALSE(DGNode::isStackSaveOrRestoreIntrinsic(Ret)); +} + +TEST_F(DependencyGraphTest, Instruction_isMemDepCandidate) { + parseIR(C, R"IR( +declare void @llvm.fake.use(...) +declare void @llvm.sideeffect() +declare void @llvm.pseudoprobe(i64, i64, i32, i64) +declare void @bar() +define void @foo(i8 %v1, ptr %ptr) { + %add0 = add i8 %v1, %v1 + %ld0 = load i8, ptr %ptr + store i8 %v1, ptr %ptr + call void @llvm.sideeffect() + call void @llvm.pseudoprobe(i64 42, i64 1, i32 0, i64 -1) + call void @llvm.fake.use(ptr %ptr) + call void @bar() + ret void +} +)IR"); + llvm::Function *LLVMF = &*M->getFunction("foo"); + sandboxir::Context Ctx(C); + sandboxir::Function *F = Ctx.createFunction(LLVMF); + auto *BB = &*F->begin(); + auto It = BB->begin(); + auto *Add0 = cast(&*It++); + auto *Ld0 = cast(&*It++); + auto *St0 = cast(&*It++); + auto *SideEffect0 = cast(&*It++); + auto *PseudoProbe0 = cast(&*It++); + auto *OtherIntrinsic0 = cast(&*It++); + auto *CallBar = cast(&*It++); + auto *Ret = cast(&*It++); + + using DGNode = sandboxir::DGNode; + + EXPECT_FALSE(DGNode::isMemDepCandidate(Add0)); + EXPECT_TRUE(DGNode::isMemDepCandidate(Ld0)); + EXPECT_TRUE(DGNode::isMemDepCandidate(St0)); + EXPECT_FALSE(DGNode::isMemDepCandidate(SideEffect0)); + EXPECT_FALSE(DGNode::isMemDepCandidate(PseudoProbe0)); + EXPECT_TRUE(DGNode::isMemDepCandidate(OtherIntrinsic0)); + EXPECT_TRUE(DGNode::isMemDepCandidate(CallBar)); + EXPECT_FALSE(DGNode::isMemDepCandidate(Ret)); +} + +TEST_F(DependencyGraphTest, Instruction_isMemIntrinsic) { + parseIR(C, R"IR( +declare void @llvm.sideeffect() +declare void @llvm.pseudoprobe(i64) +declare void @llvm.assume(i1) + +define void @foo(ptr %ptr, i1 %cond) { + call void @llvm.sideeffect() + call void @llvm.pseudoprobe(i64 42) + call void @llvm.assume(i1 %cond) + ret void +} +)IR"); + llvm::Function *LLVMF = &*M->getFunction("foo"); + sandboxir::Context Ctx(C); + sandboxir::Function *F = Ctx.createFunction(LLVMF); + auto *BB = &*F->begin(); + auto It = BB->begin(); + auto *SideEffect = cast(&*It++); + auto *PseudoProbe = cast(&*It++); + auto *OtherIntrinsic = cast(&*It++); + + using DGNode = sandboxir::DGNode; + EXPECT_FALSE(DGNode::isMemIntrinsic(SideEffect)); + EXPECT_FALSE(DGNode::isMemIntrinsic(PseudoProbe)); + EXPECT_TRUE(DGNode::isMemIntrinsic(OtherIntrinsic)); +} + TEST_F(DependencyGraphTest, MemDGNode) { parseIR(C, R"IR( declare void @llvm.sideeffect()