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,110 @@ ret i32 1 } +@0 = internal global i32 0, align 4 +@d = external global i32, align 4 +@e = external global i8, align 2 +@f = external global i16, align 2 +@h = external global i16**, align 8 +@l = external global i32, align 4 +@b = external global i64, align 8 +@a = external global i8, align 2 +@k = external global i8, align 2 +@c = external global i32, align 4 + +; CHECK-LABEL: test_pr36954 +; CHECK-NOT: xor +; PR36954 reproducer containing self referencing instruction shouldn't crash GVNSink pass. +define void @test_pr36954() { +bb: + %i = load i32, i32* @0, align 4 + %i1 = add nsw i32 %i, -1 + store i32 %i1, i32* @0, align 4 + %i26.i = load i32, i32* @0, align 4 + %0 = trunc i32 %i26.i to i8 + br label %bb4.i + +bb4.i: ; preds = %bb39.preheader.us.i, %bb + store i32 0, i32* @d, align 4 + br label %bb8.i + +bb8.i: ; preds = %bb48.i, %bb4.i + %i34.us43.i = phi i32 [ 0, %bb4.i ], [ %i34.us41.i, %bb48.i ] + %i16.i = load i32, i32* @l, align 4 + %i17.not.i = icmp eq i32 %i16.i, 0 + %i36.i = load i32, i32* @c, align 4 + %i37.not.i = icmp eq i32 %i36.i, 0 + br i1 %i17.not.i, label %bb8.split.us.split.i, label %bb8.split.i + +bb8.split.us.split.i: ; preds = %bb8.i + %i10.us36.i = load i8, i8* @e, align 2 + %i11.not.us37.i = icmp eq i8 %i10.us36.i, 0 + br i1 %i11.not.us37.i, label %bb48.i, label %bb12.us.i + +bb12.us.i: ; preds = %bb12.us.i, %bb8.split.us.split.i + %i13.us.i = load i16, i16* @f, align 2 + %i14.us.i = load i16**, i16*** @h, align 8 + %i15.us.i = load i16*, i16** %i14.us.i, align 8 + store i16 %i13.us.i, i16* %i15.us.i, align 2 + %i10.us.i = load i8, i8* @e, align 2 + %i11.not.us.i = icmp eq i8 %i10.us.i, 0 + br i1 %i11.not.us.i, label %bb48.i, label %bb12.us.i + +bb8.split.i: ; preds = %bb8.i + %i19.i = load i64, i64* @b, align 8 + %i20.not.i = icmp eq i64 %i19.i, 0 + br i1 %i20.not.i, label %bb8.split.split.us.i, label %bb8.split.split.i + +bb8.split.split.us.i: ; preds = %bb8.split.i + %i10.us13.i = load i8, i8* @e, align 2 + %i11.not.us14.i = icmp eq i8 %i10.us13.i, 0 + br i1 %i11.not.us14.i, label %bb48.i, label %n.exit + +bb8.split.split.i: ; preds = %bb8.split.i + %i10.i = load i8, i8* @e, align 2 + %i11.not.i = icmp eq i8 %i10.i, 0 + br i1 %i11.not.i, label %bb48.i, label %bb12.i + +bb9.us21.i: ; preds = %bb12.us25.i + %i10.us23.i = load i8, i8* @e, align 2 + %i11.not.us24.i = icmp eq i8 %i10.us23.i, 0 + br i1 %i11.not.us24.i, label %bb48.i, label %bb12.us25.i + +bb12.us25.i: ; preds = %bb9.us21.i + %i13.us26.i = load i16, i16* @f, align 2 + %i14.us27.i = load i16**, i16*** @h, align 8 + %i15.us28.i = load i16*, i16** %i14.us27.i, align 8 + store i16 %i13.us26.i, i16* %i15.us28.i, align 2 + %i27.us.i = load i8, i8* @a, align 2 + %i30.us.i = sub i8 %0, %i27.us.i + store i8 %i30.us.i, i8* @k, align 2 + %i32.us.i = zext i8 %i30.us.i to i32 + %i35.us.i = xor i32 %i35.us.i, %i32.us.i + store i32 %i35.us.i, i32* @d, align 4 + br i1 %i37.not.i, label %bb39.preheader.us.i, label %bb9.us21.i + +bb39.preheader.us.i: ; preds = %bb12.us25.i + br label %bb4.i + +bb12.i: ; preds = %bb8.split.split.i + %i13.i = load i16, i16* @f, align 2 + %i14.i = load i16**, i16*** @h, align 8 + %i15.i = load i16*, i16** %i14.i, align 8 + store i16 %i13.i, i16* %i15.i, align 2 + br label %bb48.i + +bb48.i: ; preds = %bb12.i, %bb8.split.split.i, %bb9.us21.i, %bb8.split.split.us.i, %bb12.us.i, %bb8.split.us.split.i + %i34.us41.i = phi i32 [ %i34.us43.i, %bb8.split.us.split.i ], [ %i34.us43.i, %bb8.split.split.us.i ], [ %i34.us43.i, %bb12.i ], [ %i34.us43.i, %bb8.split.split.i ], [ %i34.us43.i, %bb12.us.i ], [ %i35.us.i, %bb9.us21.i ] + br label %bb8.i + +n.exit: ; preds = %bb8.split.split.us.i + %i13.us16.i = load i16, i16* @f, align 2 + %i14.us17.i = load i16**, i16*** @h, align 8 + %i15.us18.i = load i16*, i16** %i14.us17.i, align 8 + store i16 %i13.us16.i, i16* %i15.us18.i, align 2 + ret void +} + ; CHECK: !0 = !{!1, !1, i64 0} ; CHECK: !1 = !{!"float", !2} ; CHECK: !2 = !{!"an example type tree"}