[llvm] [DSE] Add `tryToShortenBegin` support for memcpy (PR #115314)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 05:14:55 PST 2024


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/115314

It is the first step to fix https://github.com/llvm/llvm-project/issues/113134.
I will update after https://github.com/llvm/llvm-project/pull/106425 to avoid potential performance regressions.


>From f933abff2bfb15f69fa35836d075e91aae5acc18 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 7 Nov 2024 20:48:33 +0800
Subject: [PATCH] [DSE] Add `tryToShortenBegin` support for memcpy

---
 .../Scalar/DeadStoreElimination.cpp           | 29 +++++++++++++++++--
 .../DeadStoreElimination/libcalls-chk.ll      |  4 ++-
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index b619248c59de0b..a221ce75d772c6 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -203,9 +203,23 @@ static bool isShortenableAtTheEnd(Instruction *I) {
 /// Returns true if the beginning of this instruction can be safely shortened
 /// in length.
 static bool isShortenableAtTheBeginning(Instruction *I) {
-  // FIXME: Handle only memset for now. Supporting memcpy/memmove should be
-  // easily done by offsetting the source address.
-  return isa<AnyMemSetInst>(I);
+  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
+    switch (II->getIntrinsicID()) {
+    default:
+      return false;
+    case Intrinsic::memset:
+    case Intrinsic::memcpy:
+    case Intrinsic::memset_inline:
+    case Intrinsic::memcpy_inline:
+    case Intrinsic::memcpy_element_unordered_atomic:
+    case Intrinsic::memset_element_unordered_atomic:
+      // Do shorten memory intrinsics.
+      // FIXME: Add memmove if it's also safe to transform.
+      return true;
+    }
+  }
+
+  return false;
 }
 
 static std::optional<TypeSize> getPointerSize(const Value *V,
@@ -644,6 +658,15 @@ static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,
         DeadI->getIterator());
     NewDestGEP->setDebugLoc(DeadIntrinsic->getDebugLoc());
     DeadIntrinsic->setDest(NewDestGEP);
+
+    if (auto *MTI = dyn_cast<AnyMemTransferInst>(DeadIntrinsic)) {
+      Instruction *NewSrcGEP = GetElementPtrInst::CreateInBounds(
+          Type::getInt8Ty(DeadIntrinsic->getContext()), MTI->getRawSource(),
+          Indices, "", DeadI->getIterator());
+      NewSrcGEP->setDebugLoc(DeadIntrinsic->getDebugLoc());
+      MTI->setSource(NewSrcGEP);
+      MTI->setSourceAlignment(PrefAlign);
+    }
   }
 
   // Update attached dbg.assign intrinsics. Assume 8-bit byte.
diff --git a/llvm/test/Transforms/DeadStoreElimination/libcalls-chk.ll b/llvm/test/Transforms/DeadStoreElimination/libcalls-chk.ll
index 737f99f539523d..b2cea8566c5948 100644
--- a/llvm/test/Transforms/DeadStoreElimination/libcalls-chk.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/libcalls-chk.ll
@@ -130,7 +130,9 @@ define void @dse_strncpy_memcpy_chk_test2(ptr noalias %out, ptr noalias %in, i64
 
 define void @test_memcpy_intrinsic_and_memcpy_chk(ptr %A, ptr %B, ptr noalias %C) {
 ; CHECK-LABEL: @test_memcpy_intrinsic_and_memcpy_chk(
-; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[A:%.*]], ptr [[B:%.*]], i64 48, i1 false)
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 1
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[B:%.*]], i64 1
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[TMP1]], ptr align 1 [[TMP2]], i64 47, i1 false)
 ; CHECK-NEXT:    [[CALL:%.*]] = call ptr @__memcpy_chk(ptr [[A]], ptr [[C:%.*]], i64 1, i64 10)
 ; CHECK-NEXT:    ret void
 ;



More information about the llvm-commits mailing list