diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -388,6 +388,7 @@ BumpPtrAllocator Allocator; ArrayRecycler Recycler; uint32_t nextValueNumber = 1; + const DominatorTree *DT = nullptr; /// Create an expression for I based on its opcode and its uses. If I /// touches or reads memory, the expression is also based upon its memory @@ -418,6 +419,7 @@ public: ValueTable() = default; + explicit ValueTable(const DominatorTree *DT) : DT(DT) {} /// Returns the value number for the specified value, assigning /// it a new number if it did not have one before. @@ -432,6 +434,9 @@ } Instruction *I = cast(V); + if (DT && !DT->isReachableFromEntry(I->getParent())) + return ~0U; + InstructionUseExpr *exp = nullptr; switch (I->getOpcode()) { case Instruction::Load: @@ -561,11 +566,11 @@ class GVNSink { public: GVNSink() = default; + explicit GVNSink(const DominatorTree *DT) : VN(DT) {} bool run(Function &F) { LLVM_DEBUG(dbgs() << "GVNSink: running on function @" << F.getName() << "\n"); - unsigned NumSunk = 0; ReversePostOrderTraversal RPOT(&F); for (auto *N : RPOT) @@ -895,7 +900,9 @@ bool runOnFunction(Function &F) override { if (skipFunction(F)) return false; - GVNSink G; + auto *DTWP = getAnalysisIfAvailable(); + auto *DT = DTWP ? &DTWP->getDomTree() : nullptr; + GVNSink G(DT); return G.run(F); } @@ -907,7 +914,8 @@ } // end anonymous namespace PreservedAnalyses GVNSinkPass::run(Function &F, FunctionAnalysisManager &AM) { - GVNSink G; + DominatorTree *DT = &AM.getResult(F); + GVNSink G(DT); if (!G.run(F)) return PreservedAnalyses::all(); return PreservedAnalyses::none(); diff --git a/llvm/test/Transforms/GVNSink/sink-common-code.ll b/llvm/test/Transforms/GVNSink/sink-common-code.ll --- a/llvm/test/Transforms/GVNSink/sink-common-code.ll +++ b/llvm/test/Transforms/GVNSink/sink-common-code.ll @@ -759,6 +759,43 @@ ret i32 1 } +@0 = global i32 0, align 4 +@1 = global i8 0, align 2 + +; CHECK-LABEL: test_pr36954 +; CHECK-NOT: xor +; PR36954 reproducer containing self referencing instruction shouldn't crash GVNSink pass. +define void @test_pr36954() { +bb1: + %i1 = load i32, i32* @0, align 4 + %i2 = trunc i32 %i1 to i8 + br label %bb2 + +bb2: + %i3 = phi i32 [ 0, %bb1 ], [ %i10, %bb5 ] + %i4 = icmp eq i32 %i3, 0 + br i1 %i4, label %bb5, label %exit + +bb3: + br i1 %i4, label %bb5, label %bb4 + +bb4: + %i5 = load i8, i8* @1, align 2 + %i6 = sub i8 %i2, %i5 + store i8 %i6, i8* @1, align 2 + %i7 = zext i8 %i6 to i32 + %i8 = xor i32 %i8, %i7 + %i9 = icmp eq i32 %i8, 0 + br i1 %i9, label %exit, label %bb3 + +bb5: + %i10 = phi i32 [ %i3, %bb2 ], [ %i8, %bb3 ] + br label %bb2 + +exit: + ret void +} + ; CHECK: !0 = !{!1, !1, i64 0} ; CHECK: !1 = !{!"float", !2} ; CHECK: !2 = !{!"an example type tree"}