[llvm] 6b69985 - [MemCpyOpt] Use helper for unwind check

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 26 03:43:37 PST 2022


Author: Nikita Popov
Date: 2022-01-26T12:43:31+01:00
New Revision: 6b69985da42c6bdbe83127de9653ee795024c8d0

URL: https://github.com/llvm/llvm-project/commit/6b69985da42c6bdbe83127de9653ee795024c8d0
DIFF: https://github.com/llvm/llvm-project/commit/6b69985da42c6bdbe83127de9653ee795024c8d0.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
    llvm/test/Transforms/MemCpyOpt/callslot_throw.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 4959125e1055e..6698db26626b7 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<AllocaInst>(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 ce0d575ab21b9..62b6fcfe4d5a3 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:


        


More information about the llvm-commits mailing list