[llvm] bfa7f62 - [Assignment Tracking][20/*] Account for assignment tracking in DSE

via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 15 05:43:46 PST 2022


Author: OCHyams
Date: 2022-11-15T13:42:56Z
New Revision: bfa7f6241251589b0c8ba8d203347cf63a8dc298

URL: https://github.com/llvm/llvm-project/commit/bfa7f6241251589b0c8ba8d203347cf63a8dc298
DIFF: https://github.com/llvm/llvm-project/commit/bfa7f6241251589b0c8ba8d203347cf63a8dc298.diff

LOG: [Assignment Tracking][20/*] Account for assignment tracking in DSE

The Assignment Tracking debug-info feature is outlined in this RFC:

https://discourse.llvm.org/t/
rfc-assignment-tracking-a-better-way-of-specifying-variable-locations-in-ir

DeadStoreElimmination shortens stores that are shadowed by later stores such
that the overlapping part of the earlier store is omitted. Insert an unlinked
dbg.assign intrinsic with a variable fragment that describes the omitted part
to signal that that fragment of the variable has a stale value in memory.

Reviewed By: jmorse

Differential Revision: https://reviews.llvm.org/D133315

Added: 
    llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll

Modified: 
    llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 194220cd161d..21603c96fecd 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -56,6 +56,7 @@
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
@@ -483,6 +484,45 @@ memoryIsNotModifiedBetween(Instruction *FirstI, Instruction *SecondI,
   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);
+
+  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(), None), DeadFragment.OffsetInBits,
+        DeadFragment.SizeInBits);
+  };
+
+  // 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;
+
+  // 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;
+    }
+
+    // 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->setAddress(UndefValue::get(DAI->getAddress()->getType()));
+  }
+}
+
 static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,
                          uint64_t &DeadSize, int64_t KillingStart,
                          uint64_t KillingSize, bool IsOverwriteEnd) {
@@ -574,6 +614,10 @@ static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart,
     DeadIntrinsic->setDest(NewDestGEP);
   }
 
+  // Update attached dbg.assign intrinsics. Assume 8-bit byte.
+  shortenAssignment(DeadI, DeadStart * 8, DeadSize * 8, NewSize * 8,
+                    IsOverwriteEnd);
+
   // Finally update start and size of dead access.
   if (!IsOverwriteEnd)
     DeadStart += ToRemoveSize;

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
new file mode 100644
index 000000000000..87e99a9e4060
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/dse/dse-after-memcpyopt-merge.ll
@@ -0,0 +1,135 @@
+; RUN: opt %s -S -dse -o - -experimental-assignment-tracking | FileCheck %s
+
+;; Observed in the wild, but test is created by running memcpyopt on
+;; assignment-tracking/memcpyopt/merge-stores.ll then manually inserting
+;; two stores that overwrite each end of the memset.
+;;
+;; 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.
+
+;; 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: call void @llvm.memset{{.*}}, !DIAssignID ![[ID]]
+
+; CHECK-DAG: ![[ID]] = distinct !DIAssignID()
+; CHECK-DAG: ![[UniqueID1]] = distinct !DIAssignID()
+; CHECK-DAG: ![[UniqueID2]] = distinct !DIAssignID()
+
+%struct.v = type { [4 x float] }
+
+$_ZN1vC2Ef = comdat any
+
+define dso_local void @_Z1fv() local_unnamed_addr !dbg !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
+  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
+  %arrayidx5.i = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 0, !dbg !41
+  call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !39, metadata ptr %arrayidx5.i, metadata !DIExpression()), !dbg !24
+  %arrayidx7.i = getelementptr inbounds %struct.v, ptr %g, i64 0, i32 0, i64 3, !dbg !42
+  call void @llvm.dbg.assign(metadata float 0.000000e+00, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 96, 32), metadata !39, metadata ptr %arrayidx7.i, metadata !DIExpression()), !dbg !24
+  %0 = bitcast ptr %arrayidx5.i to ptr, !dbg !43
+  call void @llvm.memset.p0i8.i64(ptr align 4 %0, i8 0, i64 16, i1 false), !dbg !44, !DIAssignID !39
+  ;; -- 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)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "reduce.cpp", directory: "/")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 12.0.0"}
+!7 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !1, file: !1, line: 12, type: !8, scopeLine: 12, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !{!11}
+!11 = !DILocalVariable(name: "g", scope: !7, file: !1, line: 13, type: !12)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "v", file: !1, line: 1, size: 128, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !13, identifier: "_ZTS1v")
+!13 = !{!14, !19}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !12, file: !1, line: 2, baseType: !15, size: 128)
+!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !16, size: 128, elements: !17)
+!16 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!17 = !{!18}
+!18 = !DISubrange(count: 4)
+!19 = !DISubprogram(name: "v", scope: !12, file: !1, line: 4, type: !20, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!20 = !DISubroutineType(types: !21)
+!21 = !{null, !22, !16}
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!23 = distinct !DIAssignID()
+!24 = !DILocation(line: 0, scope: !7)
+!25 = !DILocation(line: 13, column: 3, scope: !7)
+!26 = !DILocalVariable(name: "this", arg: 1, scope: !27, type: !30, flags: DIFlagArtificial | DIFlagObjectPointer)
+!27 = distinct !DISubprogram(name: "v", linkageName: "_ZN1vC2Ef", scope: !12, file: !1, line: 4, type: !20, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !19, retainedNodes: !28)
+!28 = !{!26, !29}
+!29 = !DILocalVariable(name: "d", arg: 2, scope: !27, file: !1, line: 4, type: !16)
+!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!31 = distinct !DIAssignID()
+!32 = !DILocation(line: 0, scope: !27, inlinedAt: !33)
+!33 = distinct !DILocation(line: 13, column: 5, scope: !7)
+!34 = distinct !DIAssignID()
+!35 = distinct !DIAssignID()
+!36 = distinct !DIAssignID()
+!37 = !DILocation(line: 5, column: 19, scope: !38, inlinedAt: !33)
+!38 = distinct !DILexicalBlock(scope: !27, file: !1, line: 4, column: 14)
+!39 = distinct !DIAssignID()
+!40 = !DILocation(line: 5, column: 12, scope: !38, inlinedAt: !33)
+!41 = !DILocation(line: 5, column: 5, scope: !38, inlinedAt: !33)
+!42 = !DILocation(line: 6, column: 5, scope: !38, inlinedAt: !33)
+!43 = !DILocation(line: 14, column: 3, scope: !7)
+!44 = !DILocation(line: 5, column: 17, scope: !38, inlinedAt: !33)
+!45 = !DILocation(line: 15, column: 1, scope: !7)
+!46 = distinct !DIAssignID()
+!47 = !DILocation(line: 0, scope: !27)
+!48 = distinct !DIAssignID()
+!49 = distinct !DIAssignID()
+!50 = distinct !DIAssignID()
+!51 = !DILocation(line: 5, column: 19, scope: !38)
+!52 = !DILocation(line: 5, column: 24, scope: !38)
+!57 = !DILocation(line: 5, column: 12, scope: !38)
+!58 = !DILocation(line: 5, column: 17, scope: !38)
+!59 = !DILocation(line: 5, column: 5, scope: !38)
+!60 = !DILocation(line: 5, column: 10, scope: !38)
+!61 = !DILocation(line: 6, column: 5, scope: !38)
+!62 = !DILocation(line: 6, column: 10, scope: !38)
+!63 = !DILocation(line: 7, column: 3, scope: !27)
+!64 = !DISubprogram(name: "esc", linkageName: "_Z3escP1v", scope: !1, file: !1, line: 10, type: !65, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+!65 = !DISubroutineType(types: !66)
+!66 = !{null, !30}

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll
new file mode 100644
index 000000000000..9843c094ee3d
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/dse/shorten.ll
@@ -0,0 +1,128 @@
+; RUN: opt %s -S -dse -o - -experimental-assignment-tracking | FileCheck %s
+
+;; $ cat test.cpp
+;; void esc(int*);
+;; void shortenEnd() {
+;;   int local[20];
+;;   __builtin_memset(local, 0, 6 * 4);
+;;   __builtin_memset(local + 4, 8, 10 * 4);
+;;   esc(local);
+;; }
+;; void shortenStart() {
+;;   int local2[10];
+;;   __builtin_memset(local2, 0, 10 * 4);
+;;   __builtin_memset(local2, 8, 4 * 4);
+;;   esc(local2);
+;; }
+;; IR grabbed before dse in:
+;; clang++ -O2 -g -Xclang -fexperimental-assignment-tracking
+
+;; DeadStoreElimination will shorten the first store in shortenEnd from [0,
+;; 192) bits to [0, 128) bits. Check that we get an unlinked dbg.assign covering
+;; the deleted bits [128, 192) (offset=128 size=64). It will shorten also the
+;; first store in shortenStart from [0, 320) bits to [128, 320). Check that we
+;; get an unlinked dbg.assign covering the deleted bits [0, 128) (offset=0
+;; size=128).
+
+; CHECK: @_Z10shortenEndv
+; 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, 0, 192), metadata ![[ID:[0-9]+]], metadata ptr %local, metadata !DIExpression())
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i8 0, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 64), metadata ![[UniqueID1:[0-9]+]], metadata ptr undef, metadata !DIExpression())
+
+; CHECK: @_Z12shortenStartv
+; 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 [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
+  %add.ptr = getelementptr inbounds [20 x i32], ptr %local, i64 0, i64 4, !dbg !21
+  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
+}
+
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+!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: 640, elements: !14)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15}
+!15 = !DISubrange(count: 20)
+!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: 320, elements: !35)
+!35 = !{!36}
+!36 = !DISubrange(count: 10)
+!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)


        


More information about the llvm-commits mailing list