From 6b69985da42c6bdbe83127de9653ee795024c8d0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 26 Jan 2022 11:27:44 +0100 Subject: [PATCH] [MemCpyOpt] Use helper for unwind check This extends support to byval arguments. It would be further extended to handle the case of non-captured noalias returns. --- llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp | 24 +++++++++++++++--------- llvm/test/Transforms/MemCpyOpt/callslot_throw.ll | 6 ++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 4959125..6698db2 100644 --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -313,15 +313,21 @@ INITIALIZE_PASS_END(MemCpyOptLegacyPass, "memcpyopt", "MemCpy Optimization", static bool mayBeVisibleThroughUnwinding(Value *V, Instruction *Start, Instruction *End) { assert(Start->getParent() == End->getParent() && "Must be in same block"); - if (!Start->getFunction()->doesNotThrow() && - !isa(getUnderlyingObject(V))) { - for (const Instruction &I : - make_range(Start->getIterator(), End->getIterator())) { - if (I.mayThrow()) - return true; - } - } - return false; + // Function can't unwind, so it also can't be visible through unwinding. + if (Start->getFunction()->doesNotThrow()) + return false; + + // Object is not visible on unwind. + // TODO: Support RequiresNoCaptureBeforeUnwind case. + bool RequiresNoCaptureBeforeUnwind; + if (isNotVisibleOnUnwind(getUnderlyingObject(V), + RequiresNoCaptureBeforeUnwind) && + !RequiresNoCaptureBeforeUnwind) + return false; + + // Check whether there are any unwinding instructions in the range. + return any_of(make_range(Start->getIterator(), End->getIterator()), + [](const Instruction &I) { return I.mayThrow(); }); } void MemCpyOptPass::eraseInstruction(Instruction *I) { diff --git a/llvm/test/Transforms/MemCpyOpt/callslot_throw.ll b/llvm/test/Transforms/MemCpyOpt/callslot_throw.ll index ce0d575..62b6fcf 100644 --- a/llvm/test/Transforms/MemCpyOpt/callslot_throw.ll +++ b/llvm/test/Transforms/MemCpyOpt/callslot_throw.ll @@ -40,14 +40,12 @@ entry: ret void } -; TODO: byval argument is not visible on unwind. +; byval argument is not visible on unwind. define void @test_byval(i32* nocapture noalias dereferenceable(4) byval(i32) %x) { ; CHECK-LABEL: @test_byval( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 -; CHECK-NEXT: call void @may_throw(i32* nonnull [[T]]) -; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32* [[T]], align 4 -; CHECK-NEXT: store i32 [[LOAD]], i32* [[X:%.*]], align 4 +; CHECK-NEXT: call void @may_throw(i32* nonnull [[X:%.*]]) ; CHECK-NEXT: ret void ; entry: -- 2.7.4