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 @@ -381,6 +381,8 @@ } }; +using BasicBlocksSet = SmallPtrSet; + class ValueTable { DenseMap ValueNumbering; DenseMap ExpressionNumbering; @@ -388,6 +390,7 @@ BumpPtrAllocator Allocator; ArrayRecycler Recycler; uint32_t nextValueNumber = 1; + BasicBlocksSet ReachableBBs; /// 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 @@ -419,6 +422,11 @@ public: ValueTable() = default; + /// Set basic blocks reachable from entry block. + void setReachableBBs(const BasicBlocksSet &ReachableBBs) { + this->ReachableBBs = ReachableBBs; + } + /// Returns the value number for the specified value, assigning /// it a new number if it did not have one before. uint32_t lookupOrAdd(Value *V) { @@ -432,6 +440,9 @@ } Instruction *I = cast(V); + if (!ReachableBBs.contains(I->getParent())) + return ~0U; + InstructionUseExpr *exp = nullptr; switch (I->getOpcode()) { case Instruction::Load: @@ -568,6 +579,7 @@ unsigned NumSunk = 0; ReversePostOrderTraversal RPOT(&F); + VN.setReachableBBs(BasicBlocksSet(RPOT.begin(), RPOT.end())); for (auto *N : RPOT) NumSunk += sinkBB(N); 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,27 @@ ret i32 1 } +; CHECK-LABEL: test_pr36954 +; CHECK-NOT: xor +; PR36954 reproducer containing self referencing instruction shouldn't crash GVNSink pass. +define void @test_pr36954() { +bb1: + %i2 = trunc i32 undef to i8 + br label %bb2 + +bb2: + br i1 undef, label %bb2, label %exit + +bb4.critedge: + %i6 = sub i8 %i2, undef + %i7 = zext i8 %i6 to i32 + %i8 = xor i32 %i8, %i7 + br i1 false, label %exit, label %bb4.critedge + +exit: + ret void +} + ; CHECK: !0 = !{!1, !1, i64 0} ; CHECK: !1 = !{!"float", !2} ; CHECK: !2 = !{!"an example type tree"}