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 &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(Linked.begin(), Linked.end())) { + std::optional 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(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 }