[llvm] fcd5098 - [Assignment Tracking][14/*] Account for assignment tracking in instcombine

via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 18 01:29:08 PST 2022


Author: OCHyams
Date: 2022-11-18T09:25:33Z
New Revision: fcd5098a03dadcd11d4cc8b7155a4c07581999de

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

LOG: [Assignment Tracking][14/*] Account for assignment tracking in instcombine

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

Most of the updates here are just to ensure DIAssignID attachments are
maintained and propagated correctly.

Reviewed By: jmorse

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

Added: 
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/alloca-bitcast.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/memset.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink-store.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/store-new-type.ll
    llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/storemerge.ll

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 3df5af6ac5171..a09c32800eb14 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -34,6 +34,7 @@
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalVariable.h"
@@ -223,6 +224,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) {
     S->setMetadata(LLVMContext::MD_mem_parallel_loop_access, LoopMemParallelMD);
   if (AccessGroupMD)
     S->setMetadata(LLVMContext::MD_access_group, AccessGroupMD);
+  S->copyMetadata(*MI, LLVMContext::MD_DIAssignID);
 
   if (auto *MT = dyn_cast<MemTransferInst>(MI)) {
     // non-atomics can be volatile
@@ -294,9 +296,15 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
     Dest = Builder.CreateBitCast(Dest, NewDstPtrTy);
 
     // Extract the fill value and store.
-    uint64_t Fill = FillC->getZExtValue()*0x0101010101010101ULL;
-    StoreInst *S = Builder.CreateStore(ConstantInt::get(ITy, Fill), Dest,
-                                       MI->isVolatile());
+    const uint64_t Fill = FillC->getZExtValue()*0x0101010101010101ULL;
+    Constant *FillVal = ConstantInt::get(ITy, Fill);
+    StoreInst *S = Builder.CreateStore(FillVal, Dest, MI->isVolatile());
+    S->copyMetadata(*MI, LLVMContext::MD_DIAssignID);
+    for (auto *DAI : at::getAssignmentMarkers(S)) {
+      if (any_of(DAI->location_ops(), [&](Value *V) { return V == FillC; }))
+        DAI->replaceVariableLocationOp(FillC, FillVal);
+    }
+
     S->setAlignment(Alignment);
     if (isa<AtomicMemSetInst>(MI))
       S->setOrdering(AtomicOrdering::Unordered);

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index dfe49fb525fc1..6ec4fec4b8c39 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Transforms/InstCombine/InstCombiner.h"
@@ -163,6 +164,8 @@ Instruction *InstCombinerImpl::PromoteCastOfAllocation(BitCastInst &CI,
   New->setAlignment(AI.getAlign());
   New->takeName(&AI);
   New->setUsedWithInAlloca(AI.isUsedWithInAlloca());
+  New->setMetadata(LLVMContext::MD_DIAssignID,
+                   AI.getMetadata(LLVMContext::MD_DIAssignID));
 
   // If the allocation has multiple real uses, insert a cast and change all
   // things that used it to use the new cast.  This will also hack on CI, but it

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index c4efd03017119..3ce62384f4374 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -511,6 +511,7 @@ static StoreInst *combineStoreToNewValue(InstCombinerImpl &IC, StoreInst &SI,
     // here.
     switch (ID) {
     case LLVMContext::MD_dbg:
+    case LLVMContext::MD_DIAssignID:
     case LLVMContext::MD_tbaa:
     case LLVMContext::MD_prof:
     case LLVMContext::MD_fpmath:
@@ -1554,6 +1555,7 @@ bool InstCombinerImpl::mergeStoreIntoSuccessor(StoreInst &SI) {
                     SI.getOrdering(), SI.getSyncScopeID());
   InsertNewInstBefore(NewSI, *BBI);
   NewSI->setDebugLoc(MergedLoc);
+  NewSI->mergeDIAssignID({&SI, OtherStore});
 
   // If the two stores had AA tags, merge them.
   AAMDNodes AATags = SI.getAAMetadata();

diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 61bac17811326..9719ace5eb8e8 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -4163,6 +4163,11 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock,
     if (!SunkVariables.insert(DbgUserVariable).second)
       continue;
 
+    // Leave dbg.assign intrinsics in their original positions and there should
+    // be no need to insert a clone.
+    if (isa<DbgAssignIntrinsic>(User))
+      continue;
+
     DIIClones.emplace_back(cast<DbgVariableIntrinsic>(User->clone()));
     if (isa<DbgDeclareInst>(User) && isa<CastInst>(I))
       DIIClones.back()->replaceVariableLocationOp(I, I->getOperand(0));

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/alloca-bitcast.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/alloca-bitcast.ll
new file mode 100644
index 0000000000000..468e287ebf160
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/alloca-bitcast.ll
@@ -0,0 +1,74 @@
+; RUN: opt -passes=instcombine -S %s -o - -experimental-assignment-tracking \
+; RUN: | FileCheck %s
+
+;; NOTE: This test uses typed pointers because it is testing a code path that
+;; doesn't get exercised with opaque pointers. If/when PromoteCastOfAllocation
+;; is removed from visitBitCast this test should just be deleted.
+
+;; Check that allocas generated in InstCombine's PromoteCastOfAllocation
+;; have DIAssignID copied from the original alloca.
+;;
+;; $ cat reduce.cpp
+;; struct c {
+;;   c(int);
+;;   int a, b;
+;; };
+;; c d() {
+;;   c e(1);
+;;   return e;
+;; }
+;; $ clang -O2 -c -g reduce.cpp -fno-inline -Xclang -disable-llvm-passes -emit-llvm -S \
+;;   | opt -passes=declare-to-assign -S
+
+; CHECK: entry:
+; CHECK-NEXT: %retval = alloca i64, align 8, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT: %tmpcast = bitcast i64* %retval to %struct.c*
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i1 undef, metadata ![[e:[0-9]+]], metadata !DIExpression(), metadata ![[ID]], metadata %struct.c* %tmpcast, metadata !DIExpression()), !dbg
+; CHECK: ![[e]] = !DILocalVariable(name: "e",
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.c = type { i32, i32 }
+
+define dso_local i64 @_Z1dv() !dbg !7 {
+entry:
+  %retval = alloca %struct.c, align 4, !DIAssignID !21
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !20, metadata !DIExpression(), metadata !21, metadata %struct.c* %retval, metadata !DIExpression()), !dbg !22
+  call void @_ZN1cC1Ei(%struct.c* %retval, i32 1), !dbg !23
+  %0 = bitcast %struct.c* %retval to i64*, !dbg !24
+  %1 = load i64, i64* %0, align 4, !dbg !24
+  ret i64 %1, !dbg !24
+}
+
+declare dso_local void @_ZN1cC1Ei(%struct.c*, i32) unnamed_addr
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, 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: "d", linkageName: "_Z1dv", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "c", file: !1, line: 1, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !11, identifier: "_ZTS1c")
+!11 = !{!12, !14, !15}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !1, line: 3, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !1, line: 3, baseType: !13, size: 32, offset: 32)
+!15 = !DISubprogram(name: "c", scope: !10, file: !1, line: 2, type: !16, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!16 = !DISubroutineType(types: !17)
+!17 = !{null, !18, !13}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!19 = !{!20}
+!20 = !DILocalVariable(name: "e", scope: !7, file: !1, line: 6, type: !10)
+!21 = distinct !DIAssignID()
+!22 = !DILocation(line: 0, scope: !7)
+!23 = !DILocation(line: 6, column: 5, scope: !7)
+!24 = !DILocation(line: 7, column: 3, scope: !7)

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/memset.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/memset.ll
new file mode 100644
index 0000000000000..6344fdb8658c8
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/memset.ll
@@ -0,0 +1,78 @@
+; RUN: opt %s -S -passes=instcombine -o - -experimental-assignment-tracking \
+; RUN: | FileCheck %s
+
+;; $ cat test.cpp
+;; void esc(int*);
+;; void fun() {
+;;   int local[5];
+;;   __builtin_memset(local, 8, 4 * 4);
+;;   __builtin_memset(local, 0, 2 * 4);
+;;   esc(local);
+;; }
+;; IR grabbed before instcombine in:
+;; clang++ -O2 -g -Xclang -fexperimental-assignment-tracking
+
+;; Instcombine is going to turn the second memset into a store. Check that it
+;; inherits the DIAssignID from the memset and that the dbg.assign's value
+;; component is correct.
+
+; CHECK:      store i64 0, ptr %local, align 16{{.*}}, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i64 0, metadata !{{.*}}, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata ![[ID]], metadata ptr %local, metadata !DIExpression())
+
+define dso_local void @_Z3funv() local_unnamed_addr #0 !dbg !7 {
+entry:
+  %local = alloca [5 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
+  %0 = bitcast ptr %local to ptr, !dbg !18
+  call void @llvm.lifetime.start.p0i8(i64 20, ptr %0) #5, !dbg !18
+  %arraydecay = getelementptr inbounds [5 x i32], ptr %local, i64 0, i64 0, !dbg !19
+  %1 = bitcast ptr %arraydecay to ptr, !dbg !19
+  call void @llvm.memset.p0i8.i64(ptr align 16 %1, i8 8, i64 16, i1 false), !dbg !19, !DIAssignID !20
+  call void @llvm.dbg.assign(metadata i8 8, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128), metadata !20, metadata ptr %1, metadata !DIExpression()), !dbg !17
+  call void @llvm.memset.p0i8.i64(ptr align 16 %1, i8 0, i64 8, i1 false), !dbg !21, !DIAssignID !22
+  call void @llvm.dbg.assign(metadata i8 0, metadata !11, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64), metadata !22, metadata ptr %1, metadata !DIExpression()), !dbg !17
+  call void @_Z3escPi(ptr noundef %arraydecay), !dbg !23
+  call void @llvm.lifetime.end.p0i8(i64 20, ptr %0) #5, !dbg !24
+  ret void, !dbg !24
+}
+
+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 !25 dso_local void @_Z3escPi(ptr noundef) local_unnamed_addr
+declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture)
+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: "fun", linkageName: "_Z3funv", 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: 3, scope: !7)
+!22 = distinct !DIAssignID()
+!23 = !DILocation(line: 6, column: 3, scope: !7)
+!24 = !DILocation(line: 7, column: 1, scope: !7)
+!25 = !DISubprogram(name: "esc", linkageName: "_Z3escPi", scope: !1, file: !1, line: 1, type: !26, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !29)
+!26 = !DISubroutineType(types: !27)
+!27 = !{null, !28}
+!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!29 = !{}

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink-store.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink-store.ll
new file mode 100644
index 0000000000000..f3990598c86be
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink-store.ll
@@ -0,0 +1,108 @@
+; RUN: opt %s -S -passes=instcombine -experimental-assignment-tracking | FileCheck %s
+
+;; Check that instcombine merges the DIAssignID metadata when merging two
+;; stores into a successor. Filecheck directives inline.
+;;
+;; Generated from the following source:
+;; int c;
+;; void esc(int*);
+;; int get();
+;; void fun() {
+;;   int local;
+;;   if (c) {
+;;     get();
+;;     local = 2;
+;;   } else {
+;;     local = 2;
+;;   }
+;;   esc(&local);
+;; }
+
+; CHECK: if.then:
+; CHECK-NEXT: %call = call
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 2, metadata ![[LOCAL:[0-9]+]], metadata !DIExpression(), metadata ![[MERGED_ID:[0-9]+]], metadata ptr %local, metadata !DIExpression()), !dbg
+
+; CHECK: if.else:
+; CHECK-NEXT: call void @llvm.dbg.assign(metadata i32 2, metadata ![[LOCAL]], metadata !DIExpression(), metadata ![[MERGED_ID]], metadata ptr %local, metadata !DIExpression()), !dbg
+
+; CHECK: if.end:
+; CHECK-NEXT: store i32 2, ptr %local{{.*}}!DIAssignID ![[MERGED_ID]]
+
+; CHECK: ![[LOCAL]] = !DILocalVariable(name: "local",
+
+ at c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
+
+; Function Attrs: uwtable mustprogress
+define dso_local void @_Z3funv() local_unnamed_addr !dbg !11 {
+entry:
+  %local = alloca i32, align 4
+  %0 = bitcast ptr %local to ptr, !dbg !16
+  call void @llvm.lifetime.start.p0i8(i64 4, ptr %0), !dbg !16
+  %1 = load i32, ptr @c, align 4, !dbg !17
+  %tobool = icmp ne i32 %1, 0, !dbg !17
+  br i1 %tobool, label %if.then, label %if.else, !dbg !23
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @_Z3getv(), !dbg !24
+  store i32 2, ptr %local, align 4, !dbg !26, !DIAssignID !27
+  call void @llvm.dbg.assign(metadata i32 2, metadata !15, metadata !DIExpression(), metadata !27, metadata ptr %local, metadata !DIExpression()), !dbg !26
+  br label %if.end, !dbg !28
+
+if.else:                                          ; preds = %entry
+  store i32 2, ptr %local, align 4, !dbg !29, !DIAssignID !31
+  call void @llvm.dbg.assign(metadata i32 2, metadata !15, metadata !DIExpression(), metadata !31, metadata ptr %local, metadata !DIExpression()), !dbg !29
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  call void @_Z3escPi(ptr %local), !dbg !32
+  call void @llvm.lifetime.end.p0i8(i64 4, ptr %0), !dbg !33
+  ret void, !dbg !33
+}
+
+declare !dbg !34 dso_local i32 @_Z3getv() local_unnamed_addr
+declare !dbg !37 dso_local void @_Z3escPi(ptr) local_unnamed_addr
+declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture)
+declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture)
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.cpp", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{i32 7, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{!"clang version 12.0.0"}
+!11 = distinct !DISubprogram(name: "fun", linkageName: "_Z3funv", scope: !3, file: !3, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !14)
+!12 = !DISubroutineType(types: !13)
+!13 = !{null}
+!14 = !{!15}
+!15 = !DILocalVariable(name: "local", scope: !11, file: !3, line: 5, type: !6)
+!16 = !DILocation(line: 5, column: 3, scope: !11)
+!17 = !DILocation(line: 6, column: 7, scope: !18)
+!18 = distinct !DILexicalBlock(scope: !11, file: !3, line: 6, column: 7)
+!23 = !DILocation(line: 6, column: 7, scope: !11)
+!24 = !DILocation(line: 7, column: 5, scope: !25)
+!25 = distinct !DILexicalBlock(scope: !18, file: !3, line: 6, column: 10)
+!26 = !DILocation(line: 8, column: 11, scope: !25)
+!27 = distinct !DIAssignID()
+!28 = !DILocation(line: 9, column: 3, scope: !25)
+!29 = !DILocation(line: 10, column: 11, scope: !30)
+!30 = distinct !DILexicalBlock(scope: !18, file: !3, line: 9, column: 10)
+!31 = distinct !DIAssignID()
+!32 = !DILocation(line: 12, column: 3, scope: !11)
+!33 = !DILocation(line: 13, column: 1, scope: !11)
+!34 = !DISubprogram(name: "get", linkageName: "_Z3getv", scope: !3, file: !3, line: 3, type: !35, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !4)
+!35 = !DISubroutineType(types: !36)
+!36 = !{!6}
+!37 = !DISubprogram(name: "esc", linkageName: "_Z3escPi", scope: !3, file: !3, line: 2, type: !38, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !4)
+!38 = !DISubroutineType(types: !39)
+!39 = !{null, !40}
+!40 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink.ll
new file mode 100644
index 0000000000000..b211a0e6f1cb8
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/sink.ll
@@ -0,0 +1,142 @@
+; RUN: opt %s -S -passes=instcombine -o - -experimental-assignment-tracking \
+; RUN: | FileCheck %s
+
+;; Check that when instcombine sinks an instruction used by a dbg.assign, the
+;; usual debug intrinsic updating doesn't take place (i.e. do not
+;; clone-and-sink a dbg.assign). Assignment tracking should be able to handle
+;; this gracefully for variables that still have a stack home. For fully
+;; promoted variables we may need to revisit this.
+
+;; $ cat test.c
+;; struct a {
+;;   char *b;
+;; } c() __attribute__((noreturn));
+;; int d;
+;; int e();
+;; int f() {
+;;   if (e())
+;;     return d;
+;;   c();
+;; }
+;; void g();
+;; void h() {
+;;   struct a i;
+;;   i.b = 0;
+;;   f();
+;;   i.b = 0;
+;;   g(&i);
+;; }
+;; $ clang -O2 -g -Xclang -fexperimental-assignment-tracking
+
+; CHECK: f.exit:
+; CHECK-NEXT: store ptr null, ptr %i, align 8,{{.+}}, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT: call void @llvm.dbg.assign({{.+}}, {{.+}}, {{.+}}, metadata ![[ID]], metadata ptr %i, {{.+}}), !dbg
+
+%struct.a = type { ptr }
+
+ at d = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0
+
+; Function Attrs: nounwind uwtable
+define dso_local i32 @f() local_unnamed_addr #0 !dbg !11 {
+entry:
+  %call = tail call i32 (...) @e() #5, !dbg !14
+  %tobool.not = icmp eq i32 %call, 0, !dbg !14
+  br i1 %tobool.not, label %if.end, label %if.then, !dbg !16
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, ptr @d, align 4, !dbg !17
+  ret i32 %0, !dbg !22
+
+if.end:                                           ; preds = %entry
+  %call1 = tail call ptr (...) @c() #6, !dbg !23
+  unreachable, !dbg !23
+}
+
+declare !dbg !24 dso_local i32 @e(...) local_unnamed_addr #1
+
+; Function Attrs: noreturn
+declare !dbg !27 dso_local ptr @c(...) local_unnamed_addr #2
+
+; Function Attrs: nounwind uwtable
+define dso_local void @h() local_unnamed_addr #0 !dbg !35 {
+entry:
+  %i = alloca %struct.a, align 8, !DIAssignID !40
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !39, metadata !DIExpression(), metadata !40, metadata ptr %i, metadata !DIExpression()), !dbg !41
+  %0 = bitcast ptr %i to ptr, !dbg !42
+  call void @llvm.lifetime.start.p0i8(i64 8, ptr nonnull %0) #5, !dbg !42
+  %b = getelementptr inbounds %struct.a, ptr %i, i64 0, i32 0, !dbg !43
+  call void @llvm.dbg.assign(metadata ptr null, metadata !39, metadata !DIExpression(), metadata !44, metadata ptr %b, metadata !DIExpression()), !dbg !41
+  %call.i = tail call i32 (...) @e() #5, !dbg !45
+  %tobool.not.i = icmp eq i32 %call.i, 0, !dbg !45
+  br i1 %tobool.not.i, label %if.end.i, label %f.exit, !dbg !47
+
+if.end.i:                                         ; preds = %entry
+  %call1.i = tail call ptr (...) @c() #6, !dbg !48
+  unreachable, !dbg !48
+
+f.exit:                                           ; preds = %entry
+  store ptr null, ptr %b, align 8, !dbg !49, !DIAssignID !53
+  call void @llvm.dbg.assign(metadata ptr null, metadata !39, metadata !DIExpression(), metadata !53, metadata ptr %b, metadata !DIExpression()), !dbg !41
+  call void @g(ptr nonnull %i) #5, !dbg !54
+  call void @llvm.lifetime.end.p0i8(i64 8, ptr nonnull %0) #5, !dbg !55
+  ret void, !dbg !55
+}
+
+declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture) #3
+declare dso_local void @g(...) local_unnamed_addr #1
+declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture) #3
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #4
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{i32 7, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{!"clang version 12.0.0"}
+!11 = distinct !DISubprogram(name: "f", scope: !3, file: !3, line: 6, type: !12, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
+!12 = !DISubroutineType(types: !13)
+!13 = !{!6}
+!14 = !DILocation(line: 7, column: 7, scope: !15)
+!15 = distinct !DILexicalBlock(scope: !11, file: !3, line: 7, column: 7)
+!16 = !DILocation(line: 7, column: 7, scope: !11)
+!17 = !DILocation(line: 8, column: 12, scope: !15)
+!22 = !DILocation(line: 8, column: 5, scope: !15)
+!23 = !DILocation(line: 9, column: 3, scope: !11)
+!24 = !DISubprogram(name: "e", scope: !3, file: !3, line: 5, type: !25, spFlags: DISPFlagOptimized, retainedNodes: !4)
+!25 = !DISubroutineType(types: !26)
+!26 = !{!6, null}
+!27 = !DISubprogram(name: "c", scope: !3, file: !3, line: 3, type: !28, flags: DIFlagNoReturn, spFlags: DISPFlagOptimized, retainedNodes: !4)
+!28 = !DISubroutineType(types: !29)
+!29 = !{!30, null}
+!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "a", file: !3, line: 1, size: 64, elements: !31)
+!31 = !{!32}
+!32 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !30, file: !3, line: 2, baseType: !33, size: 64)
+!33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 64)
+!34 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!35 = distinct !DISubprogram(name: "h", scope: !3, file: !3, line: 12, type: !36, scopeLine: 12, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !38)
+!36 = !DISubroutineType(types: !37)
+!37 = !{null}
+!38 = !{!39}
+!39 = !DILocalVariable(name: "i", scope: !35, file: !3, line: 13, type: !30)
+!40 = distinct !DIAssignID()
+!41 = !DILocation(line: 0, scope: !35)
+!42 = !DILocation(line: 13, column: 3, scope: !35)
+!43 = !DILocation(line: 14, column: 5, scope: !35)
+!44 = distinct !DIAssignID()
+!45 = !DILocation(line: 7, column: 7, scope: !15, inlinedAt: !46)
+!46 = distinct !DILocation(line: 15, column: 3, scope: !35)
+!47 = !DILocation(line: 7, column: 7, scope: !11, inlinedAt: !46)
+!48 = !DILocation(line: 9, column: 3, scope: !11, inlinedAt: !46)
+!49 = !DILocation(line: 16, column: 7, scope: !35)
+!53 = distinct !DIAssignID()
+!54 = !DILocation(line: 17, column: 3, scope: !35)
+!55 = !DILocation(line: 18, column: 1, scope: !35)

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/store-new-type.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/store-new-type.ll
new file mode 100644
index 0000000000000..cbd35af94c512
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/store-new-type.ll
@@ -0,0 +1,50 @@
+; RUN: opt %s -passes=instcombine -S | FileCheck %s
+
+;; Based on test/Transforms/InstCombine/shufflevec-bitcast.ll in which the
+;; store of <4 x i4> is replaced with a store of type <2 x i8>. Debug info
+;; added by hand. Check the DIAssignID attachment on the store is preserved.
+
+define <2 x i4> @shuf_bitcast_insert_use2(<2 x i8> %v, i8 %x, ptr %p) {
+; CHECK-LABEL: @shuf_bitcast_insert_use2(
+; CHECK-NEXT:    [[I:%.*]] = insertelement <2 x i8> [[V:%.*]], i8 [[X:%.*]], i64 0
+; CHECK-NEXT:    store <2 x i8> [[I]], ptr [[P:%.*]], align 2, !DIAssignID ![[ID:[0-9]+]]
+; CHECK-NEXT:    dbg.assign(metadata <2 x i8> %i, {{.+}}, {{.+}}, metadata ![[ID]], metadata ptr %p,{{.+}})
+; CHECK-NEXT:    [[R:%.*]] = bitcast i8 [[X]] to <2 x i4>
+; CHECK-NEXT:    ret <2 x i4> [[R]]
+;
+  %i = insertelement <2 x i8> %v, i8 %x, i32 0
+  %b = bitcast <2 x i8> %i to <4 x i4>
+  store <4 x i4> %b, ptr %p, !DIAssignID !37
+  call void @llvm.dbg.assign(metadata <4 x i4> %b, metadata !28, metadata !DIExpression(), metadata !37, metadata ptr %p, metadata !DIExpression()), !dbg !26
+  %r = shufflevector <4 x i4> %b, <4 x i4> undef, <2 x i32> <i32 0, i32 1>
+  ret <2 x i4> %r
+}
+
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!12, !13}
+!llvm.ident = !{!19}
+
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 16.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.cpp", directory: "/")
+!4 = !{}
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "int4", file: !3, line: 1, baseType: !8)
+!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, flags: DIFlagVector, elements: !10)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{!11}
+!11 = !DISubrange(count: 4)
+!12 = !{i32 7, !"Dwarf Version", i32 5}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+!19 = !{!"clang version 16.0.0"}
+!20 = distinct !DISubprogram(name: "f", linkageName: "_Z1fi", scope: !3, file: !3, line: 3, type: !21, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !23)
+!21 = !DISubroutineType(types: !22)
+!22 = !{!7, !9}
+!23 = !{}
+!26 = !DILocation(line: 0, scope: !20)
+!28 = !DILocalVariable(name: "a", scope: !20, file: !3, line: 3, type: !29)
+!29 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 256, elements: !30)
+!30 = !{!31}
+!31 = !DISubrange(count: 2)
+!37 = distinct !DIAssignID()
+

diff  --git a/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/storemerge.ll b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/storemerge.ll
new file mode 100644
index 0000000000000..f8a897b4c1728
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/assignment-tracking/instcombine/storemerge.ll
@@ -0,0 +1,252 @@
+; RUN: opt %s -S -passes=instcombine -o - -experimental-assignment-tracking | FileCheck %s
+
+;; $ cat test.cpp
+;; class a {
+;;   float b;
+;; };
+;; class c {
+;; public:
+;;   a d();
+;; };
+;; class e {
+;; public:
+;;   c &f();
+;; };
+;; class g {
+;; public:
+;;   void h(a &);
+;; };
+;; class j {
+;;   g k;
+;;   e l;
+;;   e m;
+;;   bool n;
+;;   void o();
+;; };
+;; void j::o() {
+;;   int i;
+;;   a p;
+;;   i = 0;
+;;   for (; i < 3; i++)
+;;     if (n)
+;;       p = l.f().d();
+;;     else
+;;       p = m.f().d();
+;;   k.h(p);
+;; }
+;;
+;; Generated by grabbing IR before instcombine in:
+;; $ clang++ -O2 -g -c test.cpp -Xclang -fexperimental-assignment-tracking
+
+;; Before instcombine runs we have an unrolled loop (3 iterations). Each
+;; unrolled section is an if-diamond with a store in if.then and if.else
+;; block. The "same" stores in each unrolled section have the same
+;; DIAssignID. Instcombine is going to sink the stores from if.then and if.else
+;; into if.end for each unrolled section. This involves merging the DIAssignID
+;; of the two stores. Check that each merge updates all linked instructions
+;; with the same DIAssignID attachments too.
+
+; CHECK: if.then:
+; CHECK: call void @llvm.dbg.assign(metadata float %call2, metadata ![[var:[0-9]+]], metadata !DIExpression(), metadata ![[id:[0-9]+]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK: br label %for.inc
+
+; CHECK: if.else:
+; CHECK: call void @llvm.dbg.assign(metadata float %call5, metadata ![[var]], metadata !DIExpression(), metadata ![[id]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK: br label %for.inc
+
+; CHECK: for.inc:
+; CHECK-NEXT: %storemerge = phi float [ %call2, %if.then ], [ %call5, %if.else ]
+; CHECK-NEXT: store float %storemerge, ptr %p, align 4{{.+}}!DIAssignID ![[id]]
+
+; CHECK: if.then.1:
+; CHECK: call void @llvm.dbg.assign(metadata float %call2.1, metadata ![[var]], metadata !DIExpression(), metadata ![[id]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK: br label %for.inc.1
+
+; CHECK: if.else.1:
+; CHECK: call void @llvm.dbg.assign(metadata float %call5.1, metadata ![[var]], metadata !DIExpression(), metadata ![[id]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK: br label %for.inc.1
+
+; CHECK: for.inc.1:
+; CHECK-NEXT: %storemerge1 = phi float [ %call2.1, %if.then.1 ], [ %call5.1, %if.else.1 ]
+; CHECK-NEXT: store float %storemerge1, ptr %p, align 4{{.+}}!DIAssignID ![[id]]
+
+; CHECK: if.then.2:
+; CHECK: call void @llvm.dbg.assign(metadata float %call2.2, metadata ![[var]], metadata !DIExpression(), metadata ![[id]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK: br label %for.inc.2
+
+; CHECK: if.else.2:
+; CHECK: call void @llvm.dbg.assign(metadata float %call5.2, metadata ![[var]], metadata !DIExpression(), metadata ![[id]], metadata ptr %p, metadata !DIExpression()), !dbg
+; CHECK:  br label %for.inc.2
+
+; CHECK: for.inc.2:
+; CHECK-NEXT: %storemerge2 = phi float [ %call2.2, %if.then.2 ], [ %call5.2, %if.else.2 ]
+; CHECK-NEXT: store float %storemerge2, ptr %p, align 4{{.+}}!DIAssignID ![[id]]
+
+%class.j = type { %class.g, %class.e, %class.e, i8 }
+%class.g = type { i8 }
+%class.e = type { i8 }
+%class.a = type { float }
+%class.c = type { i8 }
+
+; Function Attrs: uwtable
+define dso_local void @_ZN1j1oEv(ptr %this) local_unnamed_addr #0 align 2 !dbg !7 {
+entry:
+  %p = alloca %class.a, align 4, !DIAssignID !49
+  call void @llvm.dbg.assign(metadata i1 undef, metadata !48, metadata !DIExpression(), metadata !49, metadata ptr %p, metadata !DIExpression()), !dbg !50
+  %0 = bitcast ptr %p to ptr, !dbg !51
+  call void @llvm.lifetime.start.p0i8(i64 4, ptr nonnull %0) #4, !dbg !51
+  %n = getelementptr inbounds %class.j, ptr %this, i64 0, i32 3
+  %l = getelementptr inbounds %class.j, ptr %this, i64 0, i32 1
+  %ref.tmp.sroa.0.0..sroa_idx = getelementptr inbounds %class.a, ptr %p, i64 0, i32 0
+  %m = getelementptr inbounds %class.j, ptr %this, i64 0, i32 2
+  %1 = load i8, ptr %n, align 1, !dbg !52
+  %tobool.not = icmp eq i8 %1, 0, !dbg !52
+  br i1 %tobool.not, label %if.else, label %if.then, !dbg !64
+
+if.then:                                          ; preds = %entry
+  %call = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %l), !dbg !65
+  %call2 = tail call float @_ZN1c1dEv(ptr nonnull %call), !dbg !66
+  store float %call2, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !67, !DIAssignID !71
+  call void @llvm.dbg.assign(metadata float %call2, metadata !48, metadata !DIExpression(), metadata !71, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc, !dbg !72
+
+if.else:                                          ; preds = %entry
+  %call4 = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %m), !dbg !73
+  %call5 = tail call float @_ZN1c1dEv(ptr nonnull %call4), !dbg !74
+  store float %call5, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !75, !DIAssignID !76
+  call void @llvm.dbg.assign(metadata float %call5, metadata !48, metadata !DIExpression(), metadata !76, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.then, %if.else
+  %2 = load i8, ptr %n, align 1, !dbg !52
+  %tobool.not.1 = icmp eq i8 %2, 0, !dbg !52
+  br i1 %tobool.not.1, label %if.else.1, label %if.then.1, !dbg !64
+
+if.then.1:                                        ; preds = %for.inc
+  %call.1 = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %l), !dbg !65
+  %call2.1 = tail call float @_ZN1c1dEv(ptr nonnull %call.1), !dbg !66
+  store float %call2.1, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !67, !DIAssignID !71
+  call void @llvm.dbg.assign(metadata float %call2.1, metadata !48, metadata !DIExpression(), metadata !71, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc.1, !dbg !72
+
+if.else.1:                                        ; preds = %for.inc
+  %call4.1 = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %m), !dbg !73
+  %call5.1 = tail call float @_ZN1c1dEv(ptr nonnull %call4.1), !dbg !74
+  store float %call5.1, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !75, !DIAssignID !76
+  call void @llvm.dbg.assign(metadata float %call5.1, metadata !48, metadata !DIExpression(), metadata !76, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc.1
+
+for.inc.1:                                        ; preds = %if.else.1, %if.then.1
+  %3 = load i8, ptr %n, align 1, !dbg !52
+  %tobool.not.2 = icmp eq i8 %3, 0, !dbg !52
+  br i1 %tobool.not.2, label %if.else.2, label %if.then.2, !dbg !64
+
+if.then.2:                                        ; preds = %for.inc.1
+  %call.2 = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %l), !dbg !65
+  %call2.2 = tail call float @_ZN1c1dEv(ptr nonnull %call.2), !dbg !66
+  store float %call2.2, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !67, !DIAssignID !71
+  call void @llvm.dbg.assign(metadata float %call2.2, metadata !48, metadata !DIExpression(), metadata !71, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc.2, !dbg !72
+
+if.else.2:                                        ; preds = %for.inc.1
+  %call4.2 = tail call nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr nonnull %m), !dbg !73
+  %call5.2 = tail call float @_ZN1c1dEv(ptr nonnull %call4.2), !dbg !74
+  store float %call5.2, ptr %ref.tmp.sroa.0.0..sroa_idx, align 4, !dbg !75, !DIAssignID !76
+  call void @llvm.dbg.assign(metadata float %call5.2, metadata !48, metadata !DIExpression(), metadata !76, metadata ptr %ref.tmp.sroa.0.0..sroa_idx, metadata !DIExpression()), !dbg !50
+  br label %for.inc.2
+
+for.inc.2:                                        ; preds = %if.else.2, %if.then.2
+  %k = getelementptr inbounds %class.j, ptr %this, i64 0, i32 0, !dbg !77
+  call void @_ZN1g1hER1a(ptr %k, ptr nonnull align 4 dereferenceable(4) %p), !dbg !78
+  call void @llvm.lifetime.end.p0i8(i64 4, ptr nonnull %0) #4, !dbg !79
+  ret void, !dbg !79
+}
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, ptr nocapture) #1
+
+declare dso_local nonnull align 1 dereferenceable(1) ptr @_ZN1e1fEv(ptr) local_unnamed_addr #2
+
+declare dso_local float @_ZN1c1dEv(ptr) local_unnamed_addr #2
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, ptr nocapture) #1
+
+declare dso_local void @_ZN1g1hER1a(ptr, ptr nonnull align 4 dereferenceable(4)) local_unnamed_addr #2
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #3
+
+!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: "test.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: "o", linkageName: "_ZN1j1oEv", scope: !8, file: !1, line: 23, type: !40, scopeLine: 23, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !39, retainedNodes: !43)
+!8 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "j", file: !1, line: 16, size: 32, flags: DIFlagTypePassByValue, elements: !9, identifier: "_ZTS1j")
+!9 = !{!10, !22, !36, !37, !39}
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: !8, file: !1, line: 17, baseType: !11, size: 8)
+!11 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "g", file: !1, line: 12, size: 8, flags: DIFlagTypePassByValue, elements: !12, identifier: "_ZTS1g")
+!12 = !{!13}
+!13 = !DISubprogram(name: "h", linkageName: "_ZN1g1hER1a", scope: !11, file: !1, line: 14, type: !14, scopeLine: 14, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!14 = !DISubroutineType(types: !15)
+!15 = !{null, !16, !17}
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!17 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !18, size: 64)
+!18 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "a", file: !1, line: 1, size: 32, flags: DIFlagTypePassByValue, elements: !19, identifier: "_ZTS1a")
+!19 = !{!20}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !18, file: !1, line: 2, baseType: !21, size: 32)
+!21 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "l", scope: !8, file: !1, line: 18, baseType: !23, size: 8, offset: 8)
+!23 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "e", file: !1, line: 8, size: 8, flags: DIFlagTypePassByValue, elements: !24, identifier: "_ZTS1e")
+!24 = !{!25}
+!25 = !DISubprogram(name: "f", linkageName: "_ZN1e1fEv", scope: !23, file: !1, line: 10, type: !26, scopeLine: 10, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!26 = !DISubroutineType(types: !27)
+!27 = !{!28, !35}
+!28 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !29, size: 64)
+!29 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "c", file: !1, line: 4, size: 8, flags: DIFlagTypePassByValue, elements: !30, identifier: "_ZTS1c")
+!30 = !{!31}
+!31 = !DISubprogram(name: "d", linkageName: "_ZN1c1dEv", scope: !29, file: !1, line: 6, type: !32, scopeLine: 6, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!32 = !DISubroutineType(types: !33)
+!33 = !{!18, !34}
+!34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !23, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!36 = !DIDerivedType(tag: DW_TAG_member, name: "m", scope: !8, file: !1, line: 19, baseType: !23, size: 8, offset: 16)
+!37 = !DIDerivedType(tag: DW_TAG_member, name: "n", scope: !8, file: !1, line: 20, baseType: !38, size: 8, offset: 24)
+!38 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!39 = !DISubprogram(name: "o", linkageName: "_ZN1j1oEv", scope: !8, file: !1, line: 21, type: !40, scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!40 = !DISubroutineType(types: !41)
+!41 = !{null, !42}
+!42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!43 = !{!44, !46, !48}
+!44 = !DILocalVariable(name: "this", arg: 1, scope: !7, type: !45, flags: DIFlagArtificial | DIFlagObjectPointer)
+!45 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!46 = !DILocalVariable(name: "i", scope: !7, file: !1, line: 24, type: !47)
+!47 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!48 = !DILocalVariable(name: "p", scope: !7, file: !1, line: 25, type: !18)
+!49 = distinct !DIAssignID()
+!50 = !DILocation(line: 0, scope: !7)
+!51 = !DILocation(line: 25, column: 3, scope: !7)
+!52 = !DILocation(line: 28, column: 9, scope: !53)
+!53 = distinct !DILexicalBlock(scope: !54, file: !1, line: 28, column: 9)
+!54 = distinct !DILexicalBlock(scope: !55, file: !1, line: 27, column: 3)
+!55 = distinct !DILexicalBlock(scope: !7, file: !1, line: 27, column: 3)
+!64 = !DILocation(line: 28, column: 9, scope: !54)
+!65 = !DILocation(line: 29, column: 13, scope: !53)
+!66 = !DILocation(line: 29, column: 17, scope: !53)
+!67 = !DILocation(line: 29, column: 9, scope: !53)
+!71 = distinct !DIAssignID()
+!72 = !DILocation(line: 29, column: 7, scope: !53)
+!73 = !DILocation(line: 31, column: 13, scope: !53)
+!74 = !DILocation(line: 31, column: 17, scope: !53)
+!75 = !DILocation(line: 31, column: 9, scope: !53)
+!76 = distinct !DIAssignID()
+!77 = !DILocation(line: 32, column: 3, scope: !7)
+!78 = !DILocation(line: 32, column: 5, scope: !7)
+!79 = !DILocation(line: 33, column: 1, scope: !7)


        


More information about the llvm-commits mailing list