diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6565,7 +6565,12 @@ i = ++BasicBlock::iterator(I), UI = BasicBlock::iterator(dyn_cast(Use)); i != UI; ++i) - if (i == I->getParent()->end() || i->mayHaveSideEffects()) + if (i == I->getParent()->end() || + // Explicitly check for and ignore llvm.assume intrinsics, which are + // marked as accessing InaccessibleMemOnly in order to maintain + // control dependencies, and therefore not detected as side effect + // free. + (i->mayHaveSideEffects() && !isa(i))) return false; // Look through GEPs. A load from a GEP derived from NULL is still undefined diff --git a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll --- a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll +++ b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll @@ -1,15 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -O1 -enable-knowledge-retention -S < %s | FileCheck %s -; RUN: opt -passes='default' -enable-knowledge-retention -S < %s | FileCheck %s +; RUN: opt -loop-rotate -instcombine -enable-knowledge-retention -S < %s | FileCheck %s +; RUN: opt -passes='loop(loop-rotate),instcombine' -enable-knowledge-retention -S < %s | FileCheck %s %0 = type { %0* } define %0* @f1() local_unnamed_addr { ; CHECK-LABEL: @f1( ; CHECK-NEXT: bb: -; CHECK-NEXT: br label [[BB3:%.*]] +; CHECK: br label [[BB3:%.*]] ; CHECK: bb3: -; CHECK-NEXT: [[I1:%.*]] = phi %0* [ [[I5:%.*]], [[BB3]] ], [ undef, [[BB:%.*]] ] +; CHECK-NEXT: [[I1:%.*]] = phi %0* [ undef, [[BB:%.*]] ], [ [[I5:%.*]], [[BB3]] ] ; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(%0* [[I1]]) ] ; CHECK-NEXT: [[I4:%.*]] = getelementptr inbounds [[TMP0:%.*]], %0* [[I1]], i64 0, i32 0 ; CHECK-NEXT: [[I5]] = load %0*, %0** [[I4]], align 8 diff --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll --- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -84,6 +84,41 @@ ret void } +declare void @llvm.assume(i1) +declare i1 @llvm.type.test(i8*, metadata) nounwind readnone + +;; Same as the above test but make sure the unreachable control flow is still +;; removed in the presence of a type test / assume sequence. + +define void @test5_type_test_assume(i1 %cond, i8* %ptr, [3 x i8*]* %vtable) { +; CHECK-LABEL: @test5_type_test_assume( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true +; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) +; CHECK-NEXT: [[VTABLE:%.*]] = bitcast [3 x i8*]* %vtable to i8* +; CHECK-NEXT: [[P:%.*]] = call i1 @llvm.type.test(i8* [[VTABLE]], metadata !"foo") +; CHECK-NEXT: tail call void @llvm.assume(i1 [[P]]) +; CHECK-NEXT: store i8 2, i8* [[PTR:%.*]], align 8 +; CHECK-NEXT: ret void +; +entry: + br i1 %cond, label %bb1, label %bb3 + +bb3: + br label %bb2 + +bb1: + br label %bb2 + +bb2: + %ptr.2 = phi i8* [ %ptr, %bb3 ], [ null, %bb1 ] + %vtablei8 = bitcast [3 x i8*]* %vtable to i8* + %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"foo") + tail call void @llvm.assume(i1 %p) + store i8 2, i8* %ptr.2, align 8 + ret void +} + define void @test5_no_null_opt(i1 %cond, i8* %ptr) #0 { ; CHECK-LABEL: @test5_no_null_opt( ; CHECK-NEXT: entry: