[llvm] [DSE] Split memory intrinsics if they are dead in the middle (PR #75478)

Nabeel Omer via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 14 06:45:46 PST 2023


https://github.com/omern1 created https://github.com/llvm/llvm-project/pull/75478

This patch enables Dead Store Elimination to split memory intrinsics that are dead in the middle into `Front` and `Rear`:

```
  // __Front__                 ___Rear___
  // | ------------- Dead ------------- |
  //         | --- Killing --- |
```

Resolves #72113

Pre-committing the tests to show diff in a moment.

>From 89c3eb2c08a121821836c7e7bd11cac8459f6401 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Thu, 14 Dec 2023 14:39:45 +0000
Subject: [PATCH] [DSE] Split memory intrinsics if they are dead in the middle

Resolves #72113
---
 .../Scalar/DeadStoreElimination.cpp           |  92 +++++-
 .../test/DebugInfo/dse-split-memintrinsics.ll | 305 ++++++++++++++++++
 .../DeadStoreElimination/dead-middle-split.ll |  43 +++
 3 files changed, 433 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/DebugInfo/dse-split-memintrinsics.ll
 create mode 100644 llvm/test/Transforms/DeadStoreElimination/dead-middle-split.ll

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 008dcc53fd44fc..7e9f1b6350a014 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -48,6 +48,7 @@
 #include "llvm/Analysis/MustExecute.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Argument.h"
 #include "llvm/IR/BasicBlock.h"
@@ -554,6 +555,78 @@ static void shortenAssignment(Instruction *Inst, Value *OriginalDest,
   }
 }
 
+static bool tryToSplitMiddle(Instruction *DeadI, OverlapIntervalsTy &IntervalMap,
+                      int64_t &DeadStart, uint64_t &DeadSize, const TargetTransformInfo& TTI) {
+  if (IntervalMap.empty() || !isShortenableAtTheEnd(DeadI))
+    return false;
+
+  OverlapIntervalsTy::iterator OII = IntervalMap.begin();
+  int64_t KillingStart = OII->second;
+  uint64_t KillingSize = OII->first - KillingStart;
+
+  assert(OII->first - KillingStart >= 0 && "Size expected to be positive");
+
+  uint64_t Threshold = TTI.getMaxMemIntrinsicInlineSizeThreshold();
+
+  // __Front__                 ___Rear___
+  // | ------------- Dead ------------- |
+  //         | --- Killing --- |
+
+  if (KillingStart < DeadStart ||
+      uint64_t(KillingStart + KillingSize) > uint64_t(DeadStart + DeadSize))
+    return false;
+
+  auto *DeadIntrinsic = cast<AnyMemIntrinsic>(DeadI);
+  Align PrefAlign = DeadIntrinsic->getDestAlign().valueOrOne();
+
+  // Assume Front is already correctly aligned.
+  uint64_t FrontSize = KillingStart - DeadStart;
+
+  int64_t RearStart = alignDown(
+      uint64_t(KillingStart + KillingSize), PrefAlign.value());
+  uint64_t RearSize = (DeadStart + DeadSize) - RearStart;
+
+  // If Front and Rear are both bigger than the threshold they won't be inlined
+  // so this seems like a bad idea. If Dead is smaller than the threshold it
+  // will be inlined so this isn't a good idea.
+  if ((FrontSize > Threshold && RearSize > Threshold) || DeadSize < Threshold)
+    return false;
+
+  Value *DeadWriteLength = DeadIntrinsic->getLength();
+  Value *DeadDest = DeadIntrinsic->getRawDest();
+
+  LLVM_DEBUG(dbgs() << "DSE: Split and shortened partially dead store: ["
+                    << DeadStart << ", " << DeadSize + DeadStart
+                    << "]\nInto: Front: [" << DeadStart << ", "
+                    << DeadStart + FrontSize << "], Rear: [" << RearStart
+                    << ", " << RearStart + RearSize << "]\n"
+                    << "Killer: [" << KillingStart << ", "
+                    << KillingSize + KillingStart << "]\n");
+
+  // Dead is now Front.
+  DeadIntrinsic->setLength(
+      ConstantInt::get(DeadWriteLength->getType(), FrontSize));
+  DeadIntrinsic->addDereferenceableParamAttr(0, FrontSize);
+
+  Value *Indices[1] = {ConstantInt::get(DeadWriteLength->getType(), RearStart)};
+  Instruction *RearDestGEP = GetElementPtrInst::CreateInBounds(
+      Type::getInt8Ty(DeadIntrinsic->getContext()), DeadDest, Indices, "",
+      DeadI);
+  auto *Rear = cast<AnyMemIntrinsic>(DeadIntrinsic->clone());
+  Rear->setDest(RearDestGEP);
+  Rear->setLength(ConstantInt::get(DeadWriteLength->getType(), RearSize));
+  Rear->insertAfter(RearDestGEP);
+  Rear->setDestAlignment(PrefAlign);
+  Rear->addDereferenceableParamAttr(0, RearSize);
+
+  shortenAssignment(DeadI, DeadDest, DeadStart * 8, DeadSize * 8, FrontSize * 8,
+                    true);
+
+  IntervalMap.erase(OII);
+  DeadSize = FrontSize;
+  return true;
+}
+
 static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,
                          uint64_t &DeadSize, int64_t KillingStart,
                          uint64_t KillingSize, bool IsOverwriteEnd) {
@@ -821,6 +894,7 @@ struct DSEState {
   const TargetLibraryInfo &TLI;
   const DataLayout &DL;
   const LoopInfo &LI;
+  const TargetTransformInfo &TTI;
 
   // Whether the function contains any irreducible control flow, useful for
   // being accurately able to detect loops.
@@ -860,9 +934,9 @@ struct DSEState {
 
   DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,
            PostDominatorTree &PDT, const TargetLibraryInfo &TLI,
-           const LoopInfo &LI)
+           const LoopInfo &LI, const TargetTransformInfo& TTI)
       : F(F), AA(AA), EI(DT, &LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT),
-        PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
+        PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI), TTI(TTI) {
     // Collect blocks with throwing instructions not modeled in MemorySSA and
     // alloc-like objects.
     unsigned PO = 0;
@@ -1978,7 +2052,7 @@ struct DSEState {
     return false;
   }
 
-  bool removePartiallyOverlappedStores(InstOverlapIntervalsTy &IOL) {
+  bool removePartiallyOverlappedIntrinsicStores(InstOverlapIntervalsTy &IOL) {
     bool Changed = false;
     for (auto OI : IOL) {
       Instruction *DeadI = OI.first;
@@ -1994,6 +2068,9 @@ struct DSEState {
       if (IntervalMap.empty())
         continue;
       Changed |= tryToShortenBegin(DeadI, IntervalMap, DeadStart, DeadSize);
+      if (IntervalMap.empty())
+        continue;
+      Changed |= tryToSplitMiddle(DeadI, IntervalMap, DeadStart, DeadSize, TTI);
     }
     return Changed;
   }
@@ -2059,10 +2136,10 @@ struct DSEState {
 static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
                                 DominatorTree &DT, PostDominatorTree &PDT,
                                 const TargetLibraryInfo &TLI,
-                                const LoopInfo &LI) {
+                                const LoopInfo &LI, const TargetTransformInfo& TTI) {
   bool MadeChange = false;
 
-  DSEState State(F, AA, MSSA, DT, PDT, TLI, LI);
+  DSEState State(F, AA, MSSA, DT, PDT, TLI, LI, TTI);
   // For each store:
   for (unsigned I = 0; I < State.MemDefs.size(); I++) {
     MemoryDef *KillingDef = State.MemDefs[I];
@@ -2226,7 +2303,7 @@ static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
 
   if (EnablePartialOverwriteTracking)
     for (auto &KV : State.IOLs)
-      MadeChange |= State.removePartiallyOverlappedStores(KV.second);
+      MadeChange |= State.removePartiallyOverlappedIntrinsicStores(KV.second);
 
   MadeChange |= State.eliminateRedundantStoresOfExistingValues();
   MadeChange |= State.eliminateDeadWritesAtEndOfFunction();
@@ -2244,8 +2321,9 @@ PreservedAnalyses DSEPass::run(Function &F, FunctionAnalysisManager &AM) {
   MemorySSA &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
   PostDominatorTree &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
   LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
+  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
 
-  bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);
+  bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI, TTI);
 
 #ifdef LLVM_ENABLE_STATS
   if (AreStatisticsEnabled())
diff --git a/llvm/test/DebugInfo/dse-split-memintrinsics.ll b/llvm/test/DebugInfo/dse-split-memintrinsics.ll
new file mode 100644
index 00000000000000..f7c083a2f0969c
--- /dev/null
+++ b/llvm/test/DebugInfo/dse-split-memintrinsics.ll
@@ -0,0 +1,305 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -passes=dse -S | FileCheck %s
+
+; Check a dbg.assign is inserted that sets the dead middle bits to no-location (see tryToSplitMiddle).
+
+define dso_local void @_Z22overwrite_middle_localv() local_unnamed_addr #0 !dbg !103 {
+; CHECK-LABEL: define dso_local void @_Z22overwrite_middle_localv(
+; CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] !dbg [[DBG103:![0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[BLOB:%.*]] = alloca [1000 x i8], align 16, !DIAssignID [[DIASSIGNID112:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.dbg.assign(metadata i1 undef, metadata [[META108:![0-9]+]], metadata !DIExpression(), metadata [[DIASSIGNID112]], metadata ptr [[BLOB]], metadata !DIExpression()), !dbg [[DBG113:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 1000, ptr nonnull [[BLOB]]) #[[ATTR5:[0-9]+]], !dbg [[DBG114:![0-9]+]]
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[BLOB]], i64 976
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(24) [[TMP0]], i8 5, i64 24, i1 false), !dbg [[DBG115:![0-9]+]], !DIAssignID [[DIASSIGNID116:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(10) [[BLOB]], i8 5, i64 10, i1 false), !dbg [[DBG115]], !DIAssignID [[DIASSIGNID116]]
+; CHECK-NEXT:    call void @llvm.dbg.assign(metadata i1 undef, metadata [[META108]], metadata !DIExpression(), metadata [[DIASSIGNID116]], metadata ptr [[BLOB]], metadata !DIExpression()), !dbg [[DBG113]]
+; CHECK-NEXT:    call void @llvm.dbg.assign(metadata i1 undef, metadata [[META108]], metadata !DIExpression(DW_OP_LLVM_fragment, 80, 7920), metadata [[META117:![0-9]+]], metadata ptr undef, metadata !DIExpression()), !dbg [[DBG113]]
+; CHECK-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[BLOB]], i64 10, !dbg [[DBG118:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 2 dereferenceable(980) [[ADD_PTR]], i8 3, i64 980, i1 false), !dbg [[DBG119:![0-9]+]], !DIAssignID [[DIASSIGNID120:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.dbg.assign(metadata i1 undef, metadata [[META108]], metadata !DIExpression(DW_OP_LLVM_fragment, 80, 7840), metadata [[DIASSIGNID120]], metadata ptr [[ADD_PTR]], metadata !DIExpression()), !dbg [[DBG113]]
+; CHECK-NEXT:    call void @_Z3escPc(ptr noundef nonnull [[BLOB]]), !dbg [[DBG121:![0-9]+]]
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 1000, ptr nonnull [[BLOB]]) #[[ATTR5]], !dbg [[DBG122:![0-9]+]]
+; CHECK-NEXT:    ret void, !dbg [[DBG122]]
+;
+entry:
+  %blob = alloca [1000 x i8], align 16, !DIAssignID !112
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !108, metadata !DIExpression(), metadata !112, metadata ptr %blob, metadata !DIExpression()), !dbg !113
+  call void @llvm.lifetime.start.p0(i64 1000, ptr nonnull %blob) #5, !dbg !114
+  call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(1000) %blob, i8 5, i64 1000, i1 false), !dbg !115, !DIAssignID !116
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !108, metadata !DIExpression(), metadata !116, metadata ptr %blob, metadata !DIExpression()), !dbg !113
+  %add.ptr = getelementptr inbounds i8, ptr %blob, i64 10, !dbg !117
+  call void @llvm.memset.p0.i64(ptr noundef nonnull align 2 dereferenceable(980) %add.ptr, i8 3, i64 980, i1 false), !dbg !118, !DIAssignID !119
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !108, metadata !DIExpression(DW_OP_LLVM_fragment, 80, 7840), metadata !119, metadata ptr %add.ptr, metadata !DIExpression()), !dbg !113
+  call void @_Z3escPc(ptr noundef nonnull %blob), !dbg !120
+  call void @llvm.lifetime.end.p0(i64 1000, ptr nonnull %blob) #5, !dbg !121
+  ret void, !dbg !121
+}
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+; Function Attrs: mustprogress nocallback nofree nounwind willreturn memory(argmem: write)
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2
+
+declare !dbg !122 void @_Z3escPc(ptr noundef) local_unnamed_addr #3
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #4
+
+attributes #0 = { mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+attributes #2 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) }
+attributes #3 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #4 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+attributes #5 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!95, !96, !97, !98, !99, !100, !101}
+!llvm.ident = !{!102}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, imports: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "debuginfo.cpp", directory: "/home", checksumkind: CSK_MD5, checksum: "3dc84462c14a3d86dd372d0473fa13aa")
+!2 = !{!3, !16, !20, !27, !31, !35, !45, !49, !51, !53, !57, !61, !65, !69, !73, !75, !77, !79, !83, !87, !91, !93}
+!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !5, file: !15, line: 77)
+!4 = !DINamespace(name: "std", scope: null)
+!5 = !DISubprogram(name: "memchr", scope: !6, file: !6, line: 100, type: !7, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!6 = !DIFile(filename: "/usr/include/string.h", directory: "", checksumkind: CSK_MD5, checksum: "3fc3efdf2e52b973f380a6e7608374ff")
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !9, !11, !12}
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null)
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !13, line: 13, baseType: !14)
+!13 = !DIFile(filename: "build_upstream/lib/clang/18/include/__stddef_size_t.h", directory: "/home", checksumkind: CSK_MD5, checksum: "405db6ea5fb824de326715f26fa9fab5")
+!14 = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned)
+!15 = !DIFile(filename: "/usr/lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/cstring", directory: "")
+!16 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !17, file: !15, line: 78)
+!17 = !DISubprogram(name: "memcmp", scope: !6, file: !6, line: 64, type: !18, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!18 = !DISubroutineType(types: !19)
+!19 = !{!11, !9, !9, !12}
+!20 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !21, file: !15, line: 79)
+!21 = !DISubprogram(name: "memcpy", scope: !6, file: !6, line: 43, type: !22, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!22 = !DISubroutineType(types: !23)
+!23 = !{!24, !25, !26, !12}
+!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!25 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !24)
+!26 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !9)
+!27 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !28, file: !15, line: 80)
+!28 = !DISubprogram(name: "memmove", scope: !6, file: !6, line: 47, type: !29, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!29 = !DISubroutineType(types: !30)
+!30 = !{!24, !24, !9, !12}
+!31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !32, file: !15, line: 81)
+!32 = !DISubprogram(name: "memset", scope: !6, file: !6, line: 61, type: !33, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!33 = !DISubroutineType(types: !34)
+!34 = !{!24, !24, !11, !12}
+!35 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !36, file: !15, line: 82)
+!36 = !DISubprogram(name: "strcat", scope: !6, file: !6, line: 149, type: !37, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!37 = !DISubroutineType(types: !38)
+!38 = !{!39, !41, !42}
+!39 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !40, size: 64)
+!40 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!41 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !39)
+!42 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !43)
+!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !44, size: 64)
+!44 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !40)
+!45 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !46, file: !15, line: 83)
+!46 = !DISubprogram(name: "strcmp", scope: !6, file: !6, line: 156, type: !47, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!47 = !DISubroutineType(types: !48)
+!48 = !{!11, !43, !43}
+!49 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !50, file: !15, line: 84)
+!50 = !DISubprogram(name: "strcoll", scope: !6, file: !6, line: 163, type: !47, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!51 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !52, file: !15, line: 85)
+!52 = !DISubprogram(name: "strcpy", scope: !6, file: !6, line: 141, type: !37, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!53 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !54, file: !15, line: 86)
+!54 = !DISubprogram(name: "strcspn", scope: !6, file: !6, line: 293, type: !55, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!55 = !DISubroutineType(types: !56)
+!56 = !{!12, !43, !43}
+!57 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !58, file: !15, line: 87)
+!58 = !DISubprogram(name: "strerror", scope: !6, file: !6, line: 419, type: !59, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!59 = !DISubroutineType(types: !60)
+!60 = !{!39, !11}
+!61 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !62, file: !15, line: 88)
+!62 = !DISubprogram(name: "strlen", scope: !6, file: !6, line: 407, type: !63, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!63 = !DISubroutineType(types: !64)
+!64 = !{!12, !43}
+!65 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !66, file: !15, line: 89)
+!66 = !DISubprogram(name: "strncat", scope: !6, file: !6, line: 152, type: !67, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!67 = !DISubroutineType(types: !68)
+!68 = !{!39, !41, !42, !12}
+!69 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !70, file: !15, line: 90)
+!70 = !DISubprogram(name: "strncmp", scope: !6, file: !6, line: 159, type: !71, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!71 = !DISubroutineType(types: !72)
+!72 = !{!11, !43, !43, !12}
+!73 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !74, file: !15, line: 91)
+!74 = !DISubprogram(name: "strncpy", scope: !6, file: !6, line: 144, type: !67, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!75 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !76, file: !15, line: 92)
+!76 = !DISubprogram(name: "strspn", scope: !6, file: !6, line: 297, type: !55, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!77 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !78, file: !15, line: 93)
+!78 = !DISubprogram(name: "strtok", scope: !6, file: !6, line: 356, type: !37, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!79 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !80, file: !15, line: 94)
+!80 = !DISubprogram(name: "strxfrm", scope: !6, file: !6, line: 166, type: !81, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!81 = !DISubroutineType(types: !82)
+!82 = !{!12, !41, !42, !12}
+!83 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !84, file: !15, line: 95)
+!84 = !DISubprogram(name: "strchr", scope: !6, file: !6, line: 239, type: !85, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!85 = !DISubroutineType(types: !86)
+!86 = !{!43, !43, !11}
+!87 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !88, file: !15, line: 96)
+!88 = !DISubprogram(name: "strpbrk", scope: !6, file: !6, line: 316, type: !89, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!89 = !DISubroutineType(types: !90)
+!90 = !{!43, !43, !43}
+!91 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !92, file: !15, line: 97)
+!92 = !DISubprogram(name: "strrchr", scope: !6, file: !6, line: 266, type: !85, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!93 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !94, file: !15, line: 98)
+!94 = !DISubprogram(name: "strstr", scope: !6, file: !6, line: 343, type: !89, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!95 = !{i32 7, !"Dwarf Version", i32 5}
+!96 = !{i32 2, !"Debug Info Version", i32 3}
+!97 = !{i32 1, !"wchar_size", i32 4}
+!98 = !{i32 8, !"PIC Level", i32 2}
+!99 = !{i32 7, !"PIE Level", i32 2}
+!100 = !{i32 7, !"uwtable", i32 2}
+!101 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!102 = !{!"clang version 18.0.0"}
+!103 = distinct !DISubprogram(name: "overwrite_middle_local", linkageName: "_Z22overwrite_middle_localv", scope: !104, file: !104, line: 3, type: !105, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !107)
+!104 = !DIFile(filename: "./debuginfo.cpp", directory: "/home", checksumkind: CSK_MD5, checksum: "3dc84462c14a3d86dd372d0473fa13aa")
+!105 = !DISubroutineType(types: !106)
+!106 = !{null}
+!107 = !{!108}
+!108 = !DILocalVariable(name: "blob", scope: !103, file: !104, line: 4, type: !109)
+!109 = !DICompositeType(tag: DW_TAG_array_type, baseType: !40, size: 8000, elements: !110)
+!110 = !{!111}
+!111 = !DISubrange(count: 1000)
+!112 = distinct !DIAssignID()
+!113 = !DILocation(line: 0, scope: !103)
+!114 = !DILocation(line: 4, column: 5, scope: !103)
+!115 = !DILocation(line: 5, column: 5, scope: !103)
+!116 = distinct !DIAssignID()
+!117 = !DILocation(line: 6, column: 17, scope: !103)
+!118 = !DILocation(line: 6, column: 5, scope: !103)
+!119 = distinct !DIAssignID()
+!120 = !DILocation(line: 7, column: 5, scope: !103)
+!121 = !DILocation(line: 8, column: 1, scope: !103)
+!122 = !DISubprogram(name: "esc", linkageName: "_Z3escPc", scope: !104, file: !104, line: 2, type: !123, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!123 = !DISubroutineType(types: !124)
+!124 = !{null, !39}
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, imports: [[META2:![0-9]+]], splitDebugInlining: false, nameTableKind: None)
+; CHECK: [[META1]] = !DIFile(filename: "debuginfo.cpp", directory: {{.*}})
+; CHECK: [[META2]] = !{[[META3:![0-9]+]], [[META16:![0-9]+]], [[META20:![0-9]+]], [[META27:![0-9]+]], [[META31:![0-9]+]], [[META35:![0-9]+]], [[META45:![0-9]+]], [[META49:![0-9]+]], [[META51:![0-9]+]], [[META53:![0-9]+]], [[META57:![0-9]+]], [[META61:![0-9]+]], [[META65:![0-9]+]], [[META69:![0-9]+]], [[META73:![0-9]+]], [[META75:![0-9]+]], [[META77:![0-9]+]], [[META79:![0-9]+]], [[META83:![0-9]+]], [[META87:![0-9]+]], [[META91:![0-9]+]], [[META93:![0-9]+]]}
+; CHECK: [[META3]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4:![0-9]+]], entity: [[META5:![0-9]+]], file: [[META15:![0-9]+]], line: 77)
+; CHECK: [[META4]] = !DINamespace(name: "std", scope: null)
+; CHECK: [[META5]] = !DISubprogram(name: "memchr", scope: [[META6:![0-9]+]], file: [[META6]], line: 100, type: [[META7:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META6]] = !DIFile(filename: "/usr/include/string.h", directory: {{.*}})
+; CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]])
+; CHECK: [[META8]] = !{[[META9:![0-9]+]], [[META9]], [[META11:![0-9]+]], [[META12:![0-9]+]]}
+; CHECK: [[META9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META10:![0-9]+]], size: 64)
+; CHECK: [[META10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: null)
+; CHECK: [[META11]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: [[META12]] = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: [[META13:![0-9]+]], line: 13, baseType: [[META14:![0-9]+]])
+; CHECK: [[META13]] = !DIFile(filename: "build_upstream/lib/clang/18/include/__stddef_size_t.h", directory: {{.*}})
+; CHECK: [[META14]] = !DIBasicType(name: "unsigned long", size: 64, encoding: DW_ATE_unsigned)
+; CHECK: [[META15]] = !DIFile(filename: "/usr/lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/cstring", directory: "")
+; CHECK: [[META16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META17:![0-9]+]], file: [[META15]], line: 78)
+; CHECK: [[META17]] = !DISubprogram(name: "memcmp", scope: [[META6]], file: [[META6]], line: 64, type: [[META18:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META18]] = !DISubroutineType(types: [[META19:![0-9]+]])
+; CHECK: [[META19]] = !{[[META11]], [[META9]], [[META9]], [[META12]]}
+; CHECK: [[META20]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META21:![0-9]+]], file: [[META15]], line: 79)
+; CHECK: [[META21]] = !DISubprogram(name: "memcpy", scope: [[META6]], file: [[META6]], line: 43, type: [[META22:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META22]] = !DISubroutineType(types: [[META23:![0-9]+]])
+; CHECK: [[META23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]], [[META26:![0-9]+]], [[META12]]}
+; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+; CHECK: [[META25]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: [[META24]])
+; CHECK: [[META26]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: [[META9]])
+; CHECK: [[META27]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META28:![0-9]+]], file: [[META15]], line: 80)
+; CHECK: [[META28]] = !DISubprogram(name: "memmove", scope: [[META6]], file: [[META6]], line: 47, type: [[META29:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META29]] = !DISubroutineType(types: [[META30:![0-9]+]])
+; CHECK: [[META30]] = !{[[META24]], [[META24]], [[META9]], [[META12]]}
+; CHECK: [[META31]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META32:![0-9]+]], file: [[META15]], line: 81)
+; CHECK: [[META32]] = !DISubprogram(name: "memset", scope: [[META6]], file: [[META6]], line: 61, type: [[META33:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META33]] = !DISubroutineType(types: [[META34:![0-9]+]])
+; CHECK: [[META34]] = !{[[META24]], [[META24]], [[META11]], [[META12]]}
+; CHECK: [[META35]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META36:![0-9]+]], file: [[META15]], line: 82)
+; CHECK: [[META36]] = !DISubprogram(name: "strcat", scope: [[META6]], file: [[META6]], line: 149, type: [[META37:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META37]] = !DISubroutineType(types: [[META38:![0-9]+]])
+; CHECK: [[META38]] = !{[[META39:![0-9]+]], [[META41:![0-9]+]], [[META42:![0-9]+]]}
+; CHECK: [[META39]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META40:![0-9]+]], size: 64)
+; CHECK: [[META40]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+; CHECK: [[META41]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: [[META39]])
+; CHECK: [[META42]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: [[META43:![0-9]+]])
+; CHECK: [[META43]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META44:![0-9]+]], size: 64)
+; CHECK: [[META44]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[META40]])
+; CHECK: [[META45]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META46:![0-9]+]], file: [[META15]], line: 83)
+; CHECK: [[META46]] = !DISubprogram(name: "strcmp", scope: [[META6]], file: [[META6]], line: 156, type: [[META47:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META47]] = !DISubroutineType(types: [[META48:![0-9]+]])
+; CHECK: [[META48]] = !{[[META11]], [[META43]], [[META43]]}
+; CHECK: [[META49]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META50:![0-9]+]], file: [[META15]], line: 84)
+; CHECK: [[META50]] = !DISubprogram(name: "strcoll", scope: [[META6]], file: [[META6]], line: 163, type: [[META47]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META51]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META52:![0-9]+]], file: [[META15]], line: 85)
+; CHECK: [[META52]] = !DISubprogram(name: "strcpy", scope: [[META6]], file: [[META6]], line: 141, type: [[META37]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META53]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META54:![0-9]+]], file: [[META15]], line: 86)
+; CHECK: [[META54]] = !DISubprogram(name: "strcspn", scope: [[META6]], file: [[META6]], line: 293, type: [[META55:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META55]] = !DISubroutineType(types: [[META56:![0-9]+]])
+; CHECK: [[META56]] = !{[[META12]], [[META43]], [[META43]]}
+; CHECK: [[META57]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META58:![0-9]+]], file: [[META15]], line: 87)
+; CHECK: [[META58]] = !DISubprogram(name: "strerror", scope: [[META6]], file: [[META6]], line: 419, type: [[META59:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META59]] = !DISubroutineType(types: [[META60:![0-9]+]])
+; CHECK: [[META60]] = !{[[META39]], [[META11]]}
+; CHECK: [[META61]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META62:![0-9]+]], file: [[META15]], line: 88)
+; CHECK: [[META62]] = !DISubprogram(name: "strlen", scope: [[META6]], file: [[META6]], line: 407, type: [[META63:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META63]] = !DISubroutineType(types: [[META64:![0-9]+]])
+; CHECK: [[META64]] = !{[[META12]], [[META43]]}
+; CHECK: [[META65]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META66:![0-9]+]], file: [[META15]], line: 89)
+; CHECK: [[META66]] = !DISubprogram(name: "strncat", scope: [[META6]], file: [[META6]], line: 152, type: [[META67:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META67]] = !DISubroutineType(types: [[META68:![0-9]+]])
+; CHECK: [[META68]] = !{[[META39]], [[META41]], [[META42]], [[META12]]}
+; CHECK: [[META69]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META70:![0-9]+]], file: [[META15]], line: 90)
+; CHECK: [[META70]] = !DISubprogram(name: "strncmp", scope: [[META6]], file: [[META6]], line: 159, type: [[META71:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META71]] = !DISubroutineType(types: [[META72:![0-9]+]])
+; CHECK: [[META72]] = !{[[META11]], [[META43]], [[META43]], [[META12]]}
+; CHECK: [[META73]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META74:![0-9]+]], file: [[META15]], line: 91)
+; CHECK: [[META74]] = !DISubprogram(name: "strncpy", scope: [[META6]], file: [[META6]], line: 144, type: [[META67]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META75]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META76:![0-9]+]], file: [[META15]], line: 92)
+; CHECK: [[META76]] = !DISubprogram(name: "strspn", scope: [[META6]], file: [[META6]], line: 297, type: [[META55]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META77]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META78:![0-9]+]], file: [[META15]], line: 93)
+; CHECK: [[META78]] = !DISubprogram(name: "strtok", scope: [[META6]], file: [[META6]], line: 356, type: [[META37]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META79]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META80:![0-9]+]], file: [[META15]], line: 94)
+; CHECK: [[META80]] = !DISubprogram(name: "strxfrm", scope: [[META6]], file: [[META6]], line: 166, type: [[META81:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META81]] = !DISubroutineType(types: [[META82:![0-9]+]])
+; CHECK: [[META82]] = !{[[META12]], [[META41]], [[META42]], [[META12]]}
+; CHECK: [[META83]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META84:![0-9]+]], file: [[META15]], line: 95)
+; CHECK: [[META84]] = !DISubprogram(name: "strchr", scope: [[META6]], file: [[META6]], line: 239, type: [[META85:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META85]] = !DISubroutineType(types: [[META86:![0-9]+]])
+; CHECK: [[META86]] = !{[[META43]], [[META43]], [[META11]]}
+; CHECK: [[META87]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META88:![0-9]+]], file: [[META15]], line: 96)
+; CHECK: [[META88]] = !DISubprogram(name: "strpbrk", scope: [[META6]], file: [[META6]], line: 316, type: [[META89:![0-9]+]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META89]] = !DISubroutineType(types: [[META90:![0-9]+]])
+; CHECK: [[META90]] = !{[[META43]], [[META43]], [[META43]]}
+; CHECK: [[META91]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META92:![0-9]+]], file: [[META15]], line: 97)
+; CHECK: [[META92]] = !DISubprogram(name: "strrchr", scope: [[META6]], file: [[META6]], line: 266, type: [[META85]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[META93]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[META4]], entity: [[META94:![0-9]+]], file: [[META15]], line: 98)
+; CHECK: [[META94]] = !DISubprogram(name: "strstr", scope: [[META6]], file: [[META6]], line: 343, type: [[META89]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+; CHECK: [[DBG103]] = distinct !DISubprogram(name: "overwrite_middle_local", linkageName: "_Z22overwrite_middle_localv", scope: [[META104:![0-9]+]], file: [[META104]], line: 3, type: [[META105:![0-9]+]], scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META107:![0-9]+]])
+; CHECK: [[META104]] = !DIFile(filename: "./debuginfo.cpp", directory: {{.*}})
+; CHECK: [[META105]] = !DISubroutineType(types: [[META106:![0-9]+]])
+; CHECK: [[META106]] = !{null}
+; CHECK: [[META107]] = !{[[META108]]}
+; CHECK: [[META108]] = !DILocalVariable(name: "blob", scope: [[DBG103]], file: [[META104]], line: 4, type: [[META109:![0-9]+]])
+; CHECK: [[META109]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META40]], size: 8000, elements: [[META110:![0-9]+]])
+; CHECK: [[META110]] = !{[[META111:![0-9]+]]}
+; CHECK: [[META111]] = !DISubrange(count: 1000)
+; CHECK: [[DIASSIGNID112]] = distinct !DIAssignID()
+; CHECK: [[DBG113]] = !DILocation(line: 0, scope: [[DBG103]])
+; CHECK: [[DBG114]] = !DILocation(line: 4, column: 5, scope: [[DBG103]])
+; CHECK: [[DBG115]] = !DILocation(line: 5, column: 5, scope: [[DBG103]])
+; CHECK: [[DIASSIGNID116]] = distinct !DIAssignID()
+; CHECK: [[META117]] = distinct !DIAssignID()
+; CHECK: [[DBG118]] = !DILocation(line: 6, column: 17, scope: [[DBG103]])
+; CHECK: [[DBG119]] = !DILocation(line: 6, column: 5, scope: [[DBG103]])
+; CHECK: [[DIASSIGNID120]] = distinct !DIAssignID()
+; CHECK: [[DBG121]] = !DILocation(line: 7, column: 5, scope: [[DBG103]])
+; CHECK: [[DBG122]] = !DILocation(line: 8, column: 1, scope: [[DBG103]])
+;.
diff --git a/llvm/test/Transforms/DeadStoreElimination/dead-middle-split.ll b/llvm/test/Transforms/DeadStoreElimination/dead-middle-split.ll
new file mode 100644
index 00000000000000..cf74b6013e2ae4
--- /dev/null
+++ b/llvm/test/Transforms/DeadStoreElimination/dead-middle-split.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+
+; RUN: opt < %s -passes=dse -S | FileCheck %s
+
+define dso_local void @overwrite_middle(ptr nocapture noundef writeonly %X) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local void @overwrite_middle(
+; CHECK-SAME: ptr nocapture noundef writeonly [[X:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 976
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(24) [[TMP0]], i8 5, i64 24, i1 false)
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(10) [[X]], i8 5, i64 10, i1 false)
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 10
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(980) [[ARRAYIDX]], i8 3, i64 980, i1 false)
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(1000) %X, i8 5, i64 1000, i1 false)
+  %arrayidx = getelementptr inbounds i8, ptr %X, i64 10
+  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 16 dereferenceable(980) %arrayidx, i8 3, i64 980, i1 false)
+  ret void
+}
+
+define dso_local void @overwrite_middle2(ptr nocapture noundef writeonly %X) local_unnamed_addr #0 {
+; CHECK-LABEL: define dso_local void @overwrite_middle2(
+; CHECK-SAME: ptr nocapture noundef writeonly [[X:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 990
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(10) [[TMP0]], i8 5, i64 10, i1 false)
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(10) [[X]], i8 5, i64 10, i1 false)
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 10
+; CHECK-NEXT:    tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(980) [[ARRAYIDX]], i8 3, i64 980, i1 false)
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1000) %X, i8 5, i64 1000, i1 false)
+  %arrayidx = getelementptr inbounds i8, ptr %X, i64 10
+  tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(980) %arrayidx, i8 3, i64 980, i1 false)
+  ret void
+}
+
+; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
+



More information about the llvm-commits mailing list