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 @@ -349,6 +349,7 @@ unsigned MemoryUseOrder = -1; bool Volatile = false; ArrayRef ShuffleMask; + bool SelfReferenced = false; public: InstructionUseExpr(Instruction *I, ArrayRecycler &R, @@ -361,11 +362,17 @@ if (ShuffleVectorInst *SVI = dyn_cast(I)) ShuffleMask = SVI->getShuffleMask().copy(A); - for (auto &U : I->uses()) + SelfReferenced = llvm::find_if(I->users(), [I](User *U) { + return U == (User *)I; + }) != I->users().end(); + for (auto &U : I->uses()) { op_push_back(U.getUser()); + } llvm::sort(op_begin(), op_end()); } + bool isSelfReferenced() const { return SelfReferenced; } + void setMemoryUseOrder(unsigned MUO) { MemoryUseOrder = MUO; } void setVolatile(bool V) { Volatile = V; } @@ -494,6 +501,8 @@ ValueNumbering[V] = nextValueNumber; return nextValueNumber++; } + if (exp->isSelfReferenced()) + return ~0U; uint32_t e = ExpressionNumbering[exp]; if (!e) { 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"}