Index: llvm/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2223,6 +2223,7 @@ case Intrinsic::fshl: case Intrinsic::fshr: return optimizeFunnelShift(II); + case Intrinsic::dbg_assign: case Intrinsic::dbg_value: return fixupDbgValue(II); case Intrinsic::vscale: { Index: llvm/test/DebugInfo/Generic/assignment-tracking/codegenprepare/sunk-addr.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/Generic/assignment-tracking/codegenprepare/sunk-addr.ll @@ -0,0 +1,194 @@ +;; RUN: llc --stop-after=codegenprepare %s -experimental-assignment-tracking -o - \ +;; RUN: | FileCheck %s + +;; Check that when CodeGenPrepare moves an address computation to a block its used +;; in its dbg.assign uses are udpated. + +;; $ cat reduce.cpp +;; typedef float a; +;; class b { +;; public: +;; a c[]; +;; operator a *() { return &c[0]; } +;; }; +;; void d(a *); +;; a e(a *f) { return f[0]; } +;; typedef a g[]; +;; void h(b, b); +;; int i, j; +;; a k; +;; void l(g f) { +;; d(f + 2); +;; b m, n; +;; for (; j;) +;; ; +;; n[i] = j = 0; +;; for (; j < 3; j++) { +;; k = e(f + j); +;; i = 0; +;; for (; i < 3; i++) +;; n[i] += f[i]; +;; } +;; h(m, n); +;; } +;; $ clang -O2 -g -Xclang -fexperimental-assignment-tracking + +; CHECK-LABEL: for.end: +; CHECK: %sunkaddr = getelementptr inbounds i8, i8* %6, i64 8 +; CHECK: %7 = bitcast i8* %sunkaddr to float* +; CHECK: call void @llvm.dbg.assign(metadata float* %7 + +%class.b = type { [0 x float] } + +@i = dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 +@j = dso_local local_unnamed_addr global i32 0, align 4, !dbg !5 +@k = dso_local local_unnamed_addr global float 0.000000e+00, align 4, !dbg !8 + +; Function Attrs: mustprogress nofree norecurse nosync nounwind readonly uwtable willreturn +define dso_local noundef float @_Z1ePf(float* nocapture noundef readonly %f) local_unnamed_addr #0 !dbg !18 { +entry: + call void @llvm.dbg.assign(metadata float* %f, metadata !23, metadata !DIExpression(), metadata !24, metadata float** undef, metadata !DIExpression()), !dbg !25 + %0 = load float, float* %f, align 4, !dbg !26 + ret float %0, !dbg !26 +} + +; Function Attrs: uwtable +define dso_local void @_Z1lPf(float* noundef %f) local_unnamed_addr #1 !dbg !31 { +entry: + %m = alloca %class.b, align 8, !DIAssignID !48 + call void @llvm.dbg.assign(metadata i1 undef, metadata !36, metadata !DIExpression(), metadata !48, metadata %class.b* %m, metadata !DIExpression()), !dbg !49 + call void @llvm.dbg.assign(metadata float* %f, metadata !35, metadata !DIExpression(), metadata !50, metadata float** undef, metadata !DIExpression()), !dbg !49 + %add.ptr = getelementptr inbounds float, float* %f, i64 2, !dbg !51 + tail call void @_Z1dPf(float* noundef nonnull %add.ptr), !dbg !51 + %0 = bitcast %class.b* %m to i8*, !dbg !52 + call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0) #5, !dbg !52 + call void @llvm.lifetime.start.p0i8(i64 0, i8* nonnull %0) #5, !dbg !52 + %.pr = load i32, i32* @j, align 4, !dbg !53 + %tobool.not = icmp eq i32 %.pr, 0 + br i1 %tobool.not, label %for.end, label %for.cond.preheader, !dbg !58, !llvm.loop !59 + +for.cond.preheader: ; preds = %entry + br label %for.cond + +for.cond: ; preds = %for.cond.preheader, %for.cond + br label %for.cond + +for.end: ; preds = %entry + %1 = getelementptr inbounds %class.b, %class.b* %m, i64 0, i32 0, i64 0, !dbg !61 + call void @llvm.dbg.assign(metadata float* %f, metadata !23, metadata !DIExpression(), metadata !62, metadata float** undef, metadata !DIExpression()), !dbg !63 + %2 = load float, float* %f, align 4, !dbg !68 + store float %2, float* @k, align 4, !dbg !69 + %3 = load float, float* %f, align 4, !dbg !70 + %add = fadd float %3, 0.000000e+00, !dbg !70 + %arrayidx9.1 = getelementptr inbounds float, float* %f, i64 1, !dbg !70 + %4 = load float, float* %arrayidx9.1, align 4, !dbg !70 + %add.1 = fadd float %4, %add, !dbg !70 + %5 = load float, float* %add.ptr, align 4, !dbg !70 + %add.2 = fadd float %5, %add.1, !dbg !70 + call void @llvm.dbg.assign(metadata float* %arrayidx9.1, metadata !23, metadata !DIExpression(), metadata !62, metadata float** undef, metadata !DIExpression()), !dbg !63 + store float %4, float* @k, align 4, !dbg !69 + %6 = load float, float* %f, align 4, !dbg !70 + %add.131 = fadd float %6, %add.2, !dbg !70 + %add.1.1 = fadd float %4, %add.131, !dbg !70 + %add.2.1 = fadd float %5, %add.1.1, !dbg !70 + call void @llvm.dbg.assign(metadata float* %add.ptr, metadata !23, metadata !DIExpression(), metadata !62, metadata float** undef, metadata !DIExpression()), !dbg !63 + store float %5, float* @k, align 4, !dbg !69 + %7 = load float, float* %f, align 4, !dbg !70 + %add.232 = fadd float %7, %add.2.1, !dbg !70 + %add.1.2 = fadd float %4, %add.232, !dbg !70 + %add.2.2 = fadd float %5, %add.1.2, !dbg !70 + store float %add.2.2, float* %1, align 8 + store i32 3, i32* @i, align 4, !dbg !73 + store i32 3, i32* @j, align 4, !dbg !74 + tail call void @_Z1h1bS_(%class.b* noundef nonnull byval(%class.b) align 8 %m, %class.b* noundef nonnull byval(%class.b) align 8 %m), !dbg !75 + call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0) #5, !dbg !76 + call void @llvm.lifetime.end.p0i8(i64 0, i8* nonnull %0) #5, !dbg !76 + ret void, !dbg !76 +} + +declare !dbg !77 dso_local void @_Z1dPf(float* noundef) local_unnamed_addr +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) +declare !dbg !79 dso_local void @_Z1h1bS_(%class.b* noundef byval(%class.b) align 8, %class.b* noundef byval(%class.b) align 8) local_unnamed_addr +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14, !15, !16} +!llvm.ident = !{!17} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "i", scope: !2, file: !3, line: 11, type: !7, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "reduce.cpp", directory: "/") +!4 = !{!0, !5, !8} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "j", scope: !2, file: !3, line: 11, type: !7, isLocal: false, isDefinition: true) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) +!9 = distinct !DIGlobalVariable(name: "k", scope: !2, file: !3, line: 12, type: !10, isLocal: false, isDefinition: true) +!10 = !DIDerivedType(tag: DW_TAG_typedef, name: "a", file: !3, line: 1, baseType: !11) +!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!12 = !{i32 7, !"Dwarf Version", i32 5} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{i32 7, !"uwtable", i32 1} +!16 = !{i32 7, !"frame-pointer", i32 2} +!17 = !{!"clang version 14.0.0"} +!18 = distinct !DISubprogram(name: "e", linkageName: "_Z1ePf", scope: !3, file: !3, line: 8, type: !19, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !22) +!19 = !DISubroutineType(types: !20) +!20 = !{!10, !21} +!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!22 = !{!23} +!23 = !DILocalVariable(name: "f", arg: 1, scope: !18, file: !3, line: 8, type: !21) +!24 = distinct !DIAssignID() +!25 = !DILocation(line: 0, scope: !18) +!26 = !DILocation(line: 8, scope: !18) +!31 = distinct !DISubprogram(name: "l", linkageName: "_Z1lPf", scope: !3, file: !3, line: 13, type: !32, scopeLine: 13, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !34) +!32 = !DISubroutineType(types: !33) +!33 = !{null, !21} +!34 = !{!35, !36, !47} +!35 = !DILocalVariable(name: "f", arg: 1, scope: !31, file: !3, line: 13, type: !21) +!36 = !DILocalVariable(name: "m", scope: !31, file: !3, line: 15, type: !37) +!37 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "b", file: !3, line: 2, flags: DIFlagTypePassByValue, elements: !38, identifier: "_ZTS1b") +!38 = !{!39, !43} +!39 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !37, file: !3, line: 4, baseType: !40, flags: DIFlagPublic) +!40 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, elements: !41) +!41 = !{!42} +!42 = !DISubrange(count: -1) +!43 = !DISubprogram(name: "operator float *", linkageName: "_ZN1bcvPfEv", scope: !37, file: !3, line: 5, type: !44, scopeLine: 5, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagOptimized) +!44 = !DISubroutineType(types: !45) +!45 = !{!21, !46} +!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !37, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!47 = !DILocalVariable(name: "n", scope: !31, file: !3, line: 15, type: !37) +!48 = distinct !DIAssignID() +!49 = !DILocation(line: 0, scope: !31) +!50 = distinct !DIAssignID() +!51 = !DILocation(line: 14, scope: !31) +!52 = !DILocation(line: 15, scope: !31) +!53 = !DILocation(line: 16, scope: !54) +!54 = distinct !DILexicalBlock(scope: !55, file: !3, line: 16) +!55 = distinct !DILexicalBlock(scope: !31, file: !3, line: 16) +!58 = !DILocation(line: 16, scope: !55) +!59 = distinct !{!59, !58, !60} +!60 = !DILocation(line: 17, scope: !55) +!61 = !DILocation(line: 18, scope: !31) +!62 = distinct !DIAssignID() +!63 = !DILocation(line: 0, scope: !18, inlinedAt: !64) +!64 = distinct !DILocation(line: 20, scope: !65) +!65 = distinct !DILexicalBlock(scope: !66, file: !3, line: 19) +!66 = distinct !DILexicalBlock(scope: !67, file: !3, line: 19) +!67 = distinct !DILexicalBlock(scope: !31, file: !3, line: 19) +!68 = !DILocation(line: 8, scope: !18, inlinedAt: !64) +!69 = !DILocation(line: 20, scope: !65) +!70 = !DILocation(line: 23, scope: !71) +!71 = distinct !DILexicalBlock(scope: !72, file: !3, line: 22) +!72 = distinct !DILexicalBlock(scope: !65, file: !3, line: 22) +!73 = !DILocation(line: 0, scope: !65) +!74 = !DILocation(line: 19, scope: !66) +!75 = !DILocation(line: 25, scope: !31) +!76 = !DILocation(line: 26, scope: !31) +!77 = !DISubprogram(name: "d", linkageName: "_Z1dPf", scope: !3, file: !3, line: 7, type: !32, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !78) +!78 = !{} +!79 = !DISubprogram(name: "h", linkageName: "_Z1h1bS_", scope: !3, file: !3, line: 10, type: !80, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !78) +!80 = !DISubroutineType(types: !81) +!81 = !{null, !37, !37}