[llvm] [MemCpyOpt] Extend call slot optimization for non-dereferenceable destinations. (PR #217436)

Alina Sbirlea via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 23 15:55:27 PDT 2026


================
@@ -924,8 +924,18 @@ bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,
                         ExplicitlyDereferenceableOnly) ||
       !isDereferenceablePointer(cpyDest, APInt(64, cpySize),
                                 SimplifyQuery(DL, DT, AC, C))) {
-    LLVM_DEBUG(dbgs() << "Call Slot: Dest pointer not dereferenceable\n");
-    return false;
+    // If the call is guaranteed to return normally (willreturn + nounwind),
+    // and there are no instructions between the call and the store that might
+    // trap or throw, execution will reach the store. Since the store would
+    // trap anyway if the pointer was not dereferenceable, we can forward the
+    // pointer to the call. Perform optimization only for non-memcpy/memset
+    // calls, as those are special cased later.
----------------
alinas wrote:

I excluded it because I wasn't sure this was the place to handle it.

The call slot optimization claims to be for a memcpy and a call, but that call may be a memcpy/memset, and then there is special handling in processMemCpyMemCpyDependence and performMemCpyToMemSetOptzn that considers more patterns afaict.

In practice a few tests would change.
For callslot_deref.ll:must_not_remove_memcpy() The first memset gets removed which I think is correct.
A few tests in memcpy.ll get the optimization from this earlier code path, the memcpy is the mostly the same. For the memcpy inline cases, it's going to keep the "kind" - inline or not - of the first one, not the second though, as currently tested. I'm not sure this change is correct.

Also, for all of these, the allocas don't get removed, because DSE was doing the cleanup. So before, MemCpyOpt only transforms the second intrinsic, then DSE cleans the first one that's now dead and the alloca that feeds into it. But if MemCpyOpt turns 2 memcpys into one, DSE doesn't remove anything, so the alloca isn't removed. Which of course can be fixed by removing it in MemCpyOpt after doing call slot optimization, but I'm coming back to: is this the place to handle it? Feedback welcome on which way to go here.
I don't think the compile time will be larger, this should just be doing the code change earlier.

https://github.com/llvm/llvm-project/pull/217436


More information about the llvm-commits mailing list