diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp --- a/llvm/lib/Analysis/CaptureTracking.cpp +++ b/llvm/lib/Analysis/CaptureTracking.cpp @@ -89,7 +89,9 @@ if (isa(U->getUser()) && !ReturnCaptures) return false; - if (EphValues.contains(U->getUser())) + // Consider ephemeral calls reading or writing memory as capturing to avoid memory optimizations that may result in UB after inlining such calls. + if (EphValues.contains(U->getUser()) && + !cast(U->getUser())->mayReadOrWriteMemory()) return false; LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n"); @@ -181,7 +183,8 @@ if (isa(I) && !ReturnCaptures) return false; - if (EphValues.contains(I)) + // Consider ephemeral calls reading or writing memory as capturing to avoid memory optimizations that may result in UB after inlining such calls. + if (EphValues.contains(I) && !I->mayReadOrWriteMemory()) return false; if (!EarliestCapture) diff --git a/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll b/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll --- a/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll +++ b/llvm/test/Transforms/PhaseOrdering/dse-ephemeral-value-captures.ll @@ -26,7 +26,13 @@ define i32 @test() { ; CHECK-LABEL: define i32 @test() { ; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; CHECK-NEXT: br label [[THEN_I:%.*]] +; CHECK: then.i: +; CHECK-NEXT: [[RES_I:%.*]] = call i1 @cond() +; CHECK-NEXT: br label [[CHECK_COND_EXIT:%.*]] +; CHECK: check_cond.exit: +; CHECK-NEXT: call void @llvm.assume(i1 [[RES_I]]) +; CHECK-NEXT: ret i32 0 ; entry: %a = alloca i32, align 4