diff --git a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp --- a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp @@ -181,6 +181,17 @@ MI->removeFromParent(); MBB.insert(II, MI); Changed = true; + + // If the instruction (constant) being localized has single user, we can + // propagate debug location from user. + if (Users.size() == 1) { + const auto &DefDL = MI->getDebugLoc(); + const auto &UserDL = (*Users.begin())->getDebugLoc(); + + if ((!DefDL || DefDL.getLine() == 0) && UserDL && UserDL.getLine() != 0) { + MI->setDebugLoc(UserDL); + } + } } return Changed; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/localizer-propagate-debug-loc.mir b/llvm/test/CodeGen/AArch64/GlobalISel/localizer-propagate-debug-loc.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/localizer-propagate-debug-loc.mir @@ -0,0 +1,141 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 %s -global-isel -start-before localizer \ +# RUN: -stop-after localizer -o - | FileCheck --check-prefix=CHECK %s +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "arm64-apple-macosx12.0.0" + + @A = global i32 1234, align 4 + @B = global i32 5678, align 4 + @C = global i32 9012, align 4 + + define noundef i32 @foo() !dbg !5 { + %1 = alloca i32, align 4 + br i1 false, label %2, label %4 + + 2: ; preds = %0 + %3 = load i32, ptr @A, align 4, !dbg !10 + store volatile i32 %3, ptr %1, align 4 + br label %9 + + 4: ; preds = %0 + br i1 false, label %5, label %8 + + 5: ; preds = %4 + %6 = load i32, ptr @B, align 4, !dbg !13 + store volatile i32 %6, ptr %1, align 4 + %7 = load i32, ptr @B, align 4, !dbg !16 + store volatile i32 %7, ptr %1, align 4 + br label %9 + + 8: ; preds = %4 + store i32 3, ptr @C, align 4, !dbg !17 + br label %9 + + 9: ; preds = %8, %5, %2 + ret i32 0 + } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!2, !3, !4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) + !1 = !DIFile(filename: "tmp.ll", directory: "/") + !2 = !{i32 7, !"Dwarf Version", i32 4} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = !{i32 1, !"wchar_size", i32 4} + !5 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, type: !6, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9) + !6 = !DISubroutineType(types: !7) + !7 = !{!8} + !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !9 = !{} + !10 = !DILocation(line: 9, column: 9, scope: !11) + !11 = distinct !DILexicalBlock(scope: !12, file: !1, line: 8, column: 15) + !12 = distinct !DILexicalBlock(scope: !5, file: !1, line: 8, column: 7) + !13 = !DILocation(line: 11, column: 9, scope: !14) + !14 = distinct !DILexicalBlock(scope: !15, file: !1, line: 10, column: 22) + !15 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10, column: 14) + !16 = !DILocation(line: 12, column: 13, scope: !14) + !17 = !DILocation(line: 14, column: 7, scope: !18) + !18 = distinct !DILexicalBlock(scope: !15, file: !1, line: 13, column: 10) + +... +--- +name: foo +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +stack: + - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + ; CHECK: [[ADRP3:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @A, debug-location !10 + ; CHECK-NEXT: [[ADD_LOW3:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP3]](p0), target-flags(aarch64-pageoff, aarch64-nc) @A, debug-location !10 + ; CHECK-NEXT: [[LOAD:%[0-9]+]]:gpr(s32) = G_LOAD [[ADD_LOW3]](p0), debug-location !10 :: (dereferenceable load (s32)) + + ; CHECK: [[ADRP4:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @B, debug-location !DILocation(line: 0, scope: !14) + ; CHECK-NEXT: [[ADD_LOW4:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP4]](p0), target-flags(aarch64-pageoff, aarch64-nc) @B, debug-location !DILocation(line: 0, scope: !14) + ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:gpr(s32) = G_LOAD [[ADD_LOW4]](p0), debug-location !13 :: (dereferenceable load (s32)) + + ; CHECK: [[ADRP5:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @C, debug-location !17 + ; CHECK-NEXT: [[ADD_LOW5:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP5]](p0), target-flags(aarch64-pageoff, aarch64-nc) @C, debug-location !17 + ; CHECK-NEXT: [[C5:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3, debug-location !17 + ; CHECK-NEXT: G_STORE [[C5]](s32), [[ADD_LOW5]](p0), debug-location !17 :: (store (s32) into @C) + bb.1: + successors: %bb.2(0x40000000), %bb.3(0x40000000) + + %2:gpr(s32) = G_CONSTANT i32 3 + %24:gpr64(p0) = ADRP target-flags(aarch64-page) @C, debug-location !DILocation(line: 0, scope: !18) + %3:gpr(p0) = G_ADD_LOW %24(p0), target-flags(aarch64-pageoff, aarch64-nc) @C, debug-location !DILocation(line: 0, scope: !18) + %23:gpr64(p0) = ADRP target-flags(aarch64-page) @B, debug-location !DILocation(line: 0, scope: !14) + %5:gpr(p0) = G_ADD_LOW %23(p0), target-flags(aarch64-pageoff, aarch64-nc) @B, debug-location !DILocation(line: 0, scope: !14) + %22:gpr64(p0) = ADRP target-flags(aarch64-page) @A, debug-location !DILocation(line: 0, scope: !11) + %8:gpr(p0) = G_ADD_LOW %22(p0), target-flags(aarch64-pageoff, aarch64-nc) @A, debug-location !DILocation(line: 0, scope: !11) + %9:gpr(s32) = G_CONSTANT i32 0 + %0:gpr(p0) = G_FRAME_INDEX %stack.0 + %18:gpr(s32) = COPY %9(s32) + %19:gpr(s32) = G_CONSTANT i32 1 + %20:gpr(s32) = G_XOR %18, %19 + %11:gpr(s1) = G_TRUNC %20(s32) + G_BRCOND %11(s1), %bb.3 + G_BR %bb.2 + + bb.2: + successors: %bb.6(0x80000000) + + %7:gpr(s32) = G_LOAD %8(p0), debug-location !10 :: (dereferenceable load (s32)) + G_STORE %7(s32), %0(p0) :: (volatile store (s32) into %ir.1) + G_BR %bb.6 + + bb.3: + successors: %bb.4(0x40000000), %bb.5(0x40000000) + + %14:gpr(s32) = G_CONSTANT i32 0 + %15:gpr(s32) = G_CONSTANT i32 1 + %16:gpr(s32) = G_XOR %14, %15 + %13:gpr(s1) = G_TRUNC %16(s32) + G_BRCOND %13(s1), %bb.5 + G_BR %bb.4 + + bb.4: + successors: %bb.6(0x80000000) + + %4:gpr(s32) = G_LOAD %5(p0), debug-location !13 :: (dereferenceable load (s32)) + G_STORE %4(s32), %0(p0) :: (volatile store (s32) into %ir.1) + %6:gpr(s32) = G_LOAD %5(p0), debug-location !16 :: (dereferenceable load (s32)) + G_STORE %6(s32), %0(p0) :: (volatile store (s32) into %ir.1) + G_BR %bb.6 + + bb.5: + successors: %bb.6(0x80000000) + + G_STORE %2(s32), %3(p0), debug-location !17 :: (store (s32) into @C) + G_BR %bb.6 + + bb.6: + $w0 = COPY %9(s32) + RET_ReallyLR implicit $w0 + +...