Index: llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -485,41 +485,148 @@
   return true;
 }
 
-static void shortenAssignment(Instruction *Inst, uint64_t OldOffsetInBits,
-                              uint64_t OldSizeInBits, uint64_t NewSizeInBits,
-                              bool IsOverwriteEnd) {
-  DIExpression::FragmentInfo DeadFragment;
-  DeadFragment.SizeInBits = OldSizeInBits - NewSizeInBits;
-  DeadFragment.OffsetInBits =
-      OldOffsetInBits + (IsOverwriteEnd ? NewSizeInBits : 0);
+/// Returns a zero-sized fragment if A and B don't intersect.
+static DIExpression::FragmentInfo intersect(DIExpression::FragmentInfo A,
+                                            DIExpression::FragmentInfo B) {
+  uint64_t StartInBits = std::max(A.OffsetInBits, B.OffsetInBits);
+  uint64_t EndInBits = std::min(A.endInBits(), B.endInBits());
+  if (EndInBits <= StartInBits)
+    return {0, 0};
+  return DIExpression::FragmentInfo(EndInBits - StartInBits, StartInBits);
+}
+
+/// Return the fragment info from the DIExpression or the variable dimensions
+/// or a zero-sized fragment if the variable size is unknown.
+static DIExpression::FragmentInfo
+getVariableFragment(const DbgAssignIntrinsic *DAI) {
+  DIExpression::FragmentInfo VariableSlice(0, 0);
+  // Get the fragment or variable size, or zero.
+  if (auto Sz = DAI->getFragmentSizeInBits())
+    VariableSlice.SizeInBits = *Sz;
+  if (auto Frag = DAI->getExpression()->getFragmentInfo())
+    VariableSlice.OffsetInBits = Frag->OffsetInBits;
+  return VariableSlice;
+}
+
+/// Calculate the fragment of the variable in \p DAI covered
+/// from (Dest + DeadSliceOffsetInBits) to
+///   to (Dest + DeadSliceOffsetInBits + DeadSliceSizeInBits)
+/// taking into account the (optional) FragmentInfo in \p DAI.
+/// Return false if it can't be calculated for any reason.
+/// Result is set to nullopt if the intersect equals the variable fragment (or
+/// variable size) in DAI.
+/// Result contains a zero-sized fragment if there's no intersect.
+/// FIXME: Can this be merged with SROA's calculateFragment?
+static bool calculateFragmentIntersect(
+    const DataLayout &DL, const Value *Dest, uint64_t DeadSliceOffsetInBits,
+    uint64_t DeadSliceSizeInBits, const DbgAssignIntrinsic *DAI,
+    std::optional<DIExpression::FragmentInfo> &Result) {
+  if (DAI->isKillAddress())
+    return false;
+
+  DIExpression::FragmentInfo VarFrag = getVariableFragment(DAI);
+  if (VarFrag.SizeInBits == 0)
+    return false; // Variable size is unknown.
+
+  // Calculate the difference between Dest and the dbg.assign address +
+  // address-modifying expression.
+  int64_t PointerOffsetInBits;
+  {
+    auto DestOffsetInBytes = llvm::isPointerOffset(Dest, DAI->getAddress(), DL);
+    if (!DestOffsetInBytes)
+      return false; // Can't calculate difference in addresses.
+
+    int64_t ExprOffsetInBytes;
+    if (!DAI->getAddressExpression()->extractIfOffset(ExprOffsetInBytes))
+      return false;
+
+    int64_t PointerOffsetInBytes = *DestOffsetInBytes + ExprOffsetInBytes;
+    PointerOffsetInBits = PointerOffsetInBytes * 8;
+  }
 
-  auto CreateDeadFragExpr = [Inst, DeadFragment]() {
-    // FIXME: This should be using the DIExpression in the Alloca's dbg.assign
-    // for the variable, since that could also contain a fragment?
-    return *DIExpression::createFragmentExpression(
-        DIExpression::get(Inst->getContext(), std::nullopt),
+  // Move the dead slice from "dest space" into "variable space".
+  int64_t NewOffsetInBits =
+      DeadSliceOffsetInBits + VarFrag.OffsetInBits - PointerOffsetInBits;
+  if (NewOffsetInBits < 0)
+    return false; // Fragment offsets can only be positive.
+  DIExpression::FragmentInfo DeadSliceOfVar(DeadSliceSizeInBits,
+                                            NewOffsetInBits);
+  // Intersect the "variable space" dead bits with the variable fragment.
+  DIExpression::FragmentInfo DeadFrag = intersect(DeadSliceOfVar, VarFrag);
+  if (DeadFrag == VarFrag)
+    Result = std::nullopt;
+  else
+    Result = DeadFrag;
+  return true;
+}
+
+static void shortenAssignment(Instruction *Inst, Value *OriginalDest,
+                              uint64_t OldOffsetInBits, uint64_t OldSizeInBits,
+                              uint64_t NewSizeInBits, bool IsOverwriteEnd) {
+  const DataLayout &DL = Inst->getModule()->getDataLayout();
+  uint64_t DeadSliceSizeInBits = OldSizeInBits - NewSizeInBits;
+  uint64_t DeadSliceOffsetInBits =
+      OldOffsetInBits + (IsOverwriteEnd ? NewSizeInBits : 0);
+  auto SetDeadFragExpr = [](DbgAssignIntrinsic *DAI,
+                            DIExpression::FragmentInfo DeadFragment) {
+    // createFragmentExpression expects a relative offset if there is already a
+    // fragment.
+    uint64_t RelativeOffset = DeadFragment.OffsetInBits -
+                              DAI->getExpression()
+                                  ->getFragmentInfo()
+                                  .value_or(DIExpression::FragmentInfo(0, 0))
+                                  .OffsetInBits;
+    if (auto NewExpr = DIExpression::createFragmentExpression(
+            DAI->getExpression(), RelativeOffset, DeadFragment.SizeInBits)) {
+      DAI->setExpression(*NewExpr);
+      return;
+    }
+    // Failed to create a fragment expression for this so discard the value,
+    // making this a kill location.
+    auto *Expr = *DIExpression::createFragmentExpression(
+        DIExpression::get(DAI->getContext(), std::nullopt),
         DeadFragment.OffsetInBits, DeadFragment.SizeInBits);
+    DAI->setExpression(Expr);
+    DAI->setKillLocation();
   };
 
   // A DIAssignID to use so that the inserted dbg.assign intrinsics do not
   // link to any instructions. Created in the loop below (once).
   DIAssignID *LinkToNothing = nullptr;
+  LLVMContext &Ctx = Inst->getContext();
+  auto GetDeadLink = [&Ctx, &LinkToNothing]() {
+    if (!LinkToNothing)
+      LinkToNothing = DIAssignID::getDistinct(Ctx);
+    return LinkToNothing;
+  };
 
   // Insert an unlinked dbg.assign intrinsic for the dead fragment after each
-  // overlapping dbg.assign intrinsic.
-  for (auto *DAI : at::getAssignmentMarkers(Inst)) {
-    if (auto FragInfo = DAI->getExpression()->getFragmentInfo()) {
-      if (!DIExpression::fragmentsOverlap(*FragInfo, DeadFragment))
-        continue;
+  // overlapping dbg.assign intrinsic. The loop invalidates the iterators
+  // returned by getAssignmentMarkers so save a copy of the markers to iterate
+  // over.
+  auto Linked = at::getAssignmentMarkers(Inst);
+  for (auto *DAI :
+       SmallVector<DbgAssignIntrinsic *>(Linked.begin(), Linked.end())) {
+    std::optional<DIExpression::FragmentInfo> NewFragment;
+    if (!calculateFragmentIntersect(DL, OriginalDest, DeadSliceOffsetInBits,
+                                    DeadSliceSizeInBits, DAI, NewFragment) ||
+        !NewFragment) {
+      // We couldn't calculate the intersecting fragment for some reason. Be
+      // cautious and unlink the whole assignment from the store.
+      DAI->setKillAddress();
+      DAI->setAssignId(GetDeadLink());
+      continue;
     }
+    // No intersect.
+    if (NewFragment->SizeInBits == 0)
+      continue;
 
     // Fragments overlap: insert a new dbg.assign for this dead part.
     auto *NewAssign = cast<DbgAssignIntrinsic>(DAI->clone());
     NewAssign->insertAfter(DAI);
-    if (!LinkToNothing)
-      LinkToNothing = DIAssignID::getDistinct(Inst->getContext());
-    NewAssign->setAssignId(LinkToNothing);
-    NewAssign->setExpression(CreateDeadFragExpr());
+    NewAssign->setAssignId(GetDeadLink());
+    if (NewFragment)
+      SetDeadFragExpr(NewAssign, *NewFragment);
     NewAssign->setKillAddress();
   }
 }
@@ -596,8 +703,8 @@
   DeadIntrinsic->setLength(TrimmedLength);
   DeadIntrinsic->setDestAlignment(PrefAlign);
 
+  Value *OrigDest = DeadIntrinsic->getRawDest();
   if (!IsOverwriteEnd) {
-    Value *OrigDest = DeadIntrinsic->getRawDest();
     Type *Int8PtrTy =
         Type::getInt8PtrTy(DeadIntrinsic->getContext(),
                            OrigDest->getType()->getPointerAddressSpace());
@@ -616,7 +723,7 @@
   }
 
   // Update attached dbg.assign intrinsics. Assume 8-bit byte.
-  shortenAssignment(DeadI, DeadStart * 8, DeadSize * 8, NewSize * 8,
+  shortenAssignment(DeadI, OrigDest, DeadStart * 8, DeadSize * 8, NewSize * 8,
                     IsOverwriteEnd);
 
   // Finally update start and size of dead access.
Index: llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
===================================================================
--- llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
+++ llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
@@ -1,4 +1,4 @@
-; RUN: opt %s -S -passes=dse -o - | FileCheck %s
+; RUN: opt %s -S -passes=dse -o - | FileCheck %s --implicit-check-not="call void @llvm.dbg"
 
 ;; Observed in the wild, but test is created by running memcpyopt on
 ;; assignment-tracking/memcpyopt/merge-stores.ll then manually inserting
@@ -7,19 +7,17 @@
 ;; A memory intrinsic (or vector instruction) might have multiple dbg.assigns
 ;; linked to it if it has been created as a result of merging scalar stores,
 ;; such as in this example. DSE is going to shorten the memset because there's
-;; a later store that overwrites part of it. Insert a linked dbg.assign after
-;; each overlapping fragment to undef the dead part's memory location without
-;; needing to work out how to split the fragments exactly.
+;; a later store that overwrites part of it. Unlink the dbg.assigns that
+;; describe the overlapping fragments.
 
 ;; Check that there's an unlinked dbg.assign inserted after each overlapping
 ;; fragment of the shortened store.
 ;;
-; CHECK:      call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[VAR:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata ![[ID:[0-9]+]], metadata ptr %arrayidx5.i, metadata !DIExpression())
-; CHECK-NEXT: call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata ![[UniqueID1:[0-9]+]], metadata ptr undef, metadata !DIExpression())
-
-; CHECK:      call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 96, 32), metadata ![[ID]], metadata ptr %arrayidx7.i, metadata !DIExpression())
-; CHECK-NEXT: call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 96, 32), metadata ![[UniqueID2:[0-9]+]], metadata ptr undef, metadata !DIExpression())
-
+; CHECK: llvm.dbg.assign({{.*}}, metadata ptr %g, metadata !DIExpression())
+; CHECK: llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata ![[ID:[0-9]+]], metadata ptr %arrayidx.i, metadata !DIExpression())
+; CHECK: llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata ![[ID]], metadata ptr %arrayidx3.i, metadata !DIExpression())
+; CHECK: llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata ![[UniqueID1:[0-9]+]], metadata ptr undef, metadata !DIExpression())
+; CHECK: llvm.dbg.assign(metadata float 0.000000e+00, metadata ![[#]], metadata !DIExpression(DW_OP_LLVM_fragment, 96, 32), metadata ![[UniqueID2:[0-9]+]], metadata ptr undef, metadata !DIExpression())
 ; CHECK: call void @llvm.memset{{.*}}, !DIAssignID ![[ID]]
 
 ; CHECK-DAG: ![[ID]] = distinct !DIAssignID()
@@ -34,10 +32,7 @@
 entry:
   %g = alloca %struct.v, align 4, !DIAssignID !23
   call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !23, metadata ptr %g, metadata !DIExpression()), !dbg !24
-  call void @llvm.lifetime.start.p0i8(i64 16, ptr nonnull %g), !dbg !25
-  call void @llvm.dbg.assign(metadata ptr %g, metadata !26, metadata !DIExpression(), metadata !35, metadata ptr undef, metadata !DIExpression()), !dbg !32
-  call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !29, metadata !DIExpression(), metadata !36, metadata ptr undef, metadata !DIExpression()), !dbg !32
-  %arrayidx.i = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 2, !dbg !37
+   %arrayidx.i = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 2, !dbg !37
   call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata !39, metadata ptr %arrayidx.i, metadata !DIExpression()), !dbg !24
   %arrayidx3.i = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 1, !dbg !40
   call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !39, metadata ptr %arrayidx3.i, metadata !DIExpression()), !dbg !24
@@ -50,19 +45,14 @@
   ;; -- Start modification
   %arrayidx7 = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 3, !dbg !24
   store float 0.000000e+00, ptr %arrayidx7, align 4, !dbg !24, !DIAssignID !49
-  call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 96, 32), metadata !49, metadata ptr %arrayidx7, metadata !DIExpression()), !dbg !24
   %arrayidx = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 0, !dbg !24
   store float 0.000000e+00, ptr %arrayidx, align 4, !dbg !24, !DIAssignID !50
-  call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !50, metadata ptr %arrayidx, metadata !DIExpression()), !dbg !24
   ;; -- End modification
   call void @_Z3escP1v(ptr nonnull %g), !dbg !43
-  call void @llvm.lifetime.end.p0i8(i64 16, ptr nonnull %0), !dbg !45
   ret void, !dbg !45
 }
 
-declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture)
 declare !dbg !64 dso_local void @_Z3escP1v(ptr) local_unnamed_addr
-declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture)
 declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
 declare void @llvm.memset.p0i8.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
 
Index: llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten-offset.ll
===================================================================
--- /dev/null
+++ llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten-offset.ll
@@ -0,0 +1,134 @@
+; RUN: opt %s -S -passes=dse -o - | FileCheck %s --implicit-check-not="call void @llvm.dbg"
+
+;; Based on the test shorten.ll with some adjustments.
+;;
+;; $ cat test.cpp
+;; void esc(char*);
+;; void shortenEnd() {
+;;   char local[80];                      //        bits    frag
+;;   __builtin_memset(local + 8,  0, 24); // local:  64-160 ( 64, 96)
+;;   __builtin_memset(local + 16, 8, 40); // local: 128-160 (128, 32)
+;;   esc(local);
+;; }
+;; void shortenStart() {
+;;   char local2[40];                 //          bits   frag
+;;   __builtin_memset(local2, 0, 40); // local2:  0-160  (0, 160)
+;;   __builtin_memset(local2, 8, 16); // local2:  0-128  (0, 128)
+;;   esc(local2);
+;; }
+
+;; The variables and intrinsics have been adjusted with by hand to test
+;; what happens when the variable doesn't fill the whole alloca, and
+;; when offsets are encoded with both the address component of the dbg.assign
+;; and the address modifying DIExpression.
+
+;; DeadStoreElimination will shorten the first store in shortenEnd from [64,
+;; 192) bits to [64, 128) bits. Variable 'local' has been adjusted to be 160
+;; bits large. Check that we get an unlinked dbg.assign covering the deleted
+;; bits that overlap the dbg.assign's fagment: [128, 160) (offset=128 size=32).
+
+; CHECK: @_Z10shortenEndv
+; CHECK:      call void @llvm.dbg.assign({{.*}}, metadata ptr %local, metadata !DIExpression())
+; CHECK:      call void @llvm.memset{{.*}}, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i8 0, metadata ![[VAR:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 64, 96), metadata ![[ID:[0-9]+]], metadata ptr %offset_4_bytes, metadata !DIExpression(DW_OP_plus_uconst, 4))
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i8 0, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32), metadata ![[UniqueID1:[0-9]+]], metadata ptr undef, metadata !DIExpression({{.*}}))
+
+;; DSE will shorten the first store in shortenStart from [0, 160) bits to [128,
+;; 160) bits. Variable 'local2' has been adjusted to be 160 bits.  Check we get
+;; an unlinked dbg.assign covering the deleted bits that overlap the
+;; dbg.assign's fragment (no fragment in this case, i.e. the whole variable):
+;; [0, 128) (offset=0, size=128).
+
+; CHECK: @_Z12shortenStartv
+; CHECK:      call void @llvm.dbg.assign({{.*}}, metadata ptr %local2, metadata !DIExpression())
+; CHECK:      call void @llvm.memset{{.*}}, !DIAssignID ![[ID2:[0-9]+]]
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i8 0, metadata ![[VAR2:[0-9]+]], metadata !DIExpression(), metadata ![[ID2]], metadata ptr %local2, metadata !DIExpression())
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i8 0, metadata ![[VAR2]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128), metadata ![[UniqueID2:[0-9]+]], metadata ptr undef, metadata !DIExpression())
+
+; CHECK-DAG: ![[ID]] = distinct !DIAssignID()
+; CHECK-DAG: ![[UniqueID1]] = distinct !DIAssignID()
+; CHECK-DAG: ![[UniqueID2]] = distinct !DIAssignID()
+
+define dso_local void @_Z10shortenEndv() local_unnamed_addr #0 !dbg !7 {
+entry:
+  %local = alloca [80 x i8], align 16, !DIAssignID !16
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !16, metadata ptr %local, metadata !DIExpression()), !dbg !17
+  %arraydecay = getelementptr inbounds [80 x i8], ptr %local, i64 0, i64 0, !dbg !19
+  %offset_4_bytes = getelementptr inbounds [80 x i8], ptr %local, i64 0, i64 4, !dbg !21
+  %offset_8_bytes = getelementptr inbounds [80 x i8], ptr %local, i64 0, i64 8, !dbg !21
+  call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(24) %offset_8_bytes, i8 0, i64 72, i1 false), !dbg !19, !DIAssignID !20
+  call void @llvm.dbg.assign(metadata i8 0, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 96), metadata !20, metadata ptr %offset_4_bytes, metadata !DIExpression(DW_OP_plus_uconst, 4)), !dbg !17
+  %offset_16_bytes = getelementptr inbounds [80 x i8], ptr %local, i64 0, i64 4, !dbg !21
+  call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(40) %offset_16_bytes, i8 8, i64 64, i1 false), !dbg !22, !DIAssignID !23
+  call void @_Z3escPi(ptr noundef nonnull %arraydecay), !dbg !24
+  ret void, !dbg !25
+}
+
+declare void @llvm.memset.p0i8.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
+declare !dbg !26 dso_local void @_Z3escPi(ptr noundef) local_unnamed_addr
+
+define dso_local void @_Z12shortenStartv() local_unnamed_addr #0 !dbg !31 {
+entry:
+  %local2 = alloca [40 x i8], align 16, !DIAssignID !37
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !33, metadata !DIExpression(), metadata !37, metadata ptr %local2, metadata !DIExpression()), !dbg !38
+  %arraydecay = getelementptr inbounds [40 x i8], ptr %local2, i64 0, i64 0, !dbg !40
+  call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(40) %local2, i8 0, i64 36, i1 false), !dbg !40, !DIAssignID !41
+  call void @llvm.dbg.assign(metadata i8 0, metadata !33, metadata !DIExpression(), metadata !41, metadata ptr %local2, metadata !DIExpression()), !dbg !38
+  call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(16) %local2, i8 8, i64 16, i1 false), !dbg !42, !DIAssignID !43
+  call void @_Z3escPi(ptr noundef nonnull %arraydecay), !dbg !44
+  ret void, !dbg !45
+}
+
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !1000}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "/")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"uwtable", i32 1}
+!6 = !{!"clang version 14.0.0"}
+!7 = distinct !DISubprogram(name: "shortenEnd", linkageName: "_Z10shortenEndv", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !{!11}
+!11 = !DILocalVariable(name: "local", scope: !7, file: !1, line: 3, type: !12)
+!12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 160, elements: !14)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15}
+!15 = !DISubrange(count: 5)
+!16 = distinct !DIAssignID()
+!17 = !DILocation(line: 0, scope: !7)
+!18 = !DILocation(line: 3, column: 3, scope: !7)
+!19 = !DILocation(line: 4, column: 3, scope: !7)
+!20 = distinct !DIAssignID()
+!21 = !DILocation(line: 5, column: 26, scope: !7)
+!22 = !DILocation(line: 5, column: 3, scope: !7)
+!23 = distinct !DIAssignID()
+!24 = !DILocation(line: 6, column: 3, scope: !7)
+!25 = !DILocation(line: 7, column: 1, scope: !7)
+!26 = !DISubprogram(name: "esc", linkageName: "_Z3escPi", scope: !1, file: !1, line: 1, type: !27, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !30)
+!27 = !DISubroutineType(types: !28)
+!28 = !{null, !29}
+!29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!30 = !{}
+!31 = distinct !DISubprogram(name: "shortenStart", linkageName: "_Z12shortenStartv", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !32)
+!32 = !{!33}
+!33 = !DILocalVariable(name: "local2", scope: !31, file: !1, line: 9, type: !34)
+!34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 160, elements: !35)
+!35 = !{!36}
+!36 = !DISubrange(count: 5)
+!37 = distinct !DIAssignID()
+!38 = !DILocation(line: 0, scope: !31)
+!39 = !DILocation(line: 9, column: 3, scope: !31)
+!40 = !DILocation(line: 10, column: 3, scope: !31)
+!41 = distinct !DIAssignID()
+!42 = !DILocation(line: 11, column: 3, scope: !31)
+!43 = distinct !DIAssignID()
+!44 = !DILocation(line: 12, column: 3, scope: !31)
+!45 = !DILocation(line: 13, column: 1, scope: !31)
+!1000 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
Index: llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll
===================================================================
--- llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll
+++ llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll
@@ -42,7 +42,6 @@
 entry:
   %local = alloca [20 x i32], align 16, !DIAssignID !16
   call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !16, metadata ptr %local, metadata !DIExpression()), !dbg !17
-  call void @llvm.lifetime.start.p0i8(i64 80, ptr nonnull %local) #5, !dbg !18
   %arraydecay = getelementptr inbounds [20 x i32], ptr %local, i64 0, i64 0, !dbg !19
   call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(24) %local, i8 0, i64 24, i1 false), !dbg !19, !DIAssignID !20
   call void @llvm.dbg.assign(metadata i8 0, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 192), metadata !20, metadata ptr %local, metadata !DIExpression()), !dbg !17
@@ -50,27 +49,22 @@
   call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(40) %add.ptr, i8 8, i64 40, i1 false), !dbg !22, !DIAssignID !23
   call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 128, 320), metadata !23, metadata ptr %add.ptr, metadata !DIExpression()), !dbg !17
   call void @_Z3escPi(ptr noundef nonnull %arraydecay), !dbg !24
-  call void @llvm.lifetime.end.p0i8(i64 80, ptr nonnull %local) #5, !dbg !25
   ret void, !dbg !25
 }
 
-declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture)
 declare void @llvm.memset.p0i8.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
 declare !dbg !26 dso_local void @_Z3escPi(ptr noundef) local_unnamed_addr
-declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture)
 
 define dso_local void @_Z12shortenStartv() local_unnamed_addr #0 !dbg !31 {
 entry:
   %local2 = alloca [10 x i32], align 16, !DIAssignID !37
   call void @llvm.dbg.assign(metadata i1 undef, metadata !33, metadata !DIExpression(), metadata !37, metadata ptr %local2, metadata !DIExpression()), !dbg !38
-  call void @llvm.lifetime.start.p0i8(i64 40, ptr nonnull %local2) #5, !dbg !39
   %arraydecay = getelementptr inbounds [10 x i32], ptr %local2, i64 0, i64 0, !dbg !40
   call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(40) %local2, i8 0, i64 40, i1 false), !dbg !40, !DIAssignID !41
   call void @llvm.dbg.assign(metadata i8 0, metadata !33, metadata !DIExpression(), metadata !41, metadata ptr %local2, metadata !DIExpression()), !dbg !38
   call void @llvm.memset.p0i8.i64(ptr noundef nonnull align 16 dereferenceable(16) %local2, i8 8, i64 16, i1 false), !dbg !42, !DIAssignID !43
   call void @llvm.dbg.assign(metadata i1 undef, metadata !33, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128), metadata !43, metadata ptr %local2, metadata !DIExpression()), !dbg !38
   call void @_Z3escPi(ptr noundef nonnull %arraydecay), !dbg !44
-  call void @llvm.lifetime.end.p0i8(i64 40, ptr nonnull %local2) #5, !dbg !45
   ret void, !dbg !45
 }