diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ b/llvm/lib/Transforms/IPO/IROutliner.cpp @@ -16,8 +16,9 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Attributes.h" -#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/PassManager.h" @@ -679,6 +680,18 @@ if (!isa(&Val)) { // Remove the debug information for outlined functions. Val.setDebugLoc(DebugLoc()); + + // Loop info metadata may contain line locations. Update them to have no + // value in the new subprogram since the outlined code could be from + // several locations. + auto updateLoopInfoLoc = [&New](Metadata *MD) -> Metadata * { + if (DISubprogram *SP = New.getSubprogram()) + if (auto *Loc = dyn_cast_or_null(MD)) + return DILocation::get(New.getContext(), Loc->getLine(), + Loc->getColumn(), SP, nullptr); + return MD; + }; + updateLoopMetadataDebugLocations(Val, updateLoopInfoLoc); continue; } diff --git a/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll b/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll @@ -0,0 +1,78 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs +; RUN: opt -S -verify -iroutliner -ir-outlining-no-cost < %s | FileCheck %s + +; Make sure that we strip loop debug info from instructions that are outlined as +; well as regular debug info. + +define void @ham(i64 %arg0, i64 %arg1) !dbg !1 { +bb0: + br label %bb1 +bb1: + %phi = phi i64 [ 0, %bb0 ], [ %arg1, %bb1 ] + %icmp = icmp ult i64 %phi, %arg0 + br i1 %icmp, label %bb1, label %bb2, !dbg !7, !llvm.loop !11 + +bb2: + ret void +} + +define void @wombat(i64 %arg0, i64 %arg1) !dbg !13 { +bb0: + br label %bb1 +bb1: + %phi = phi i64 [ 0, %bb0 ], [ %arg1, %bb1 ] + %icmp = icmp ult i64 %phi, %arg0 + br i1 %icmp, label %bb1, label %bb2 + +bb2: + ret void +} + +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram(name: "ham", scope: !2, file: !2, line: 160, type: !3, scopeLine: 161, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5) +!2 = !DIFile(filename: "file", directory: "dir") +!3 = !DISubroutineType(types: !4) +!4 = !{} +!5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "ver", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None, sysroot: "sysroot", sdk: "sdk") +!6 = !DIFile(filename: "file", directory: "dir") +!7 = !DILocation(line: 354, column: 13, scope: !8, inlinedAt: !10) +!8 = distinct !DISubprogram(name: "baz", scope: !9, file: !9, line: 345, type: !3, scopeLine: 346, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5) +!9 = !DIFile(filename: "file", directory: "dir") +!10 = distinct !DILocation(line: 164, column: 15, scope: !1) +!11 = distinct !{!11, !7, !12} +!12 = !DILocation(line: 355, column: 37, scope: !8, inlinedAt: !10) +!13 = distinct !DISubprogram(name: "wombat", scope: !2, file: !2, line: 172, type: !3, scopeLine: 173, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5) +!14 = distinct !DISubprogram(name: "bar", scope: !15, file: !15, line: 219, type: !3, scopeLine: 220, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !5) +!15 = !DIFile(filename: "file", directory: "dir") + +; CHECK-LABEL: @ham( +; CHECK-NEXT: bb0: +; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[ARG1:%.*]], i64 [[ARG0:%.*]]), !dbg [[DBG6:![0-9]+]] +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: ret void +; +; +; CHECK-LABEL: @wombat( +; CHECK-NEXT: bb0: +; CHECK-NEXT: call void @outlined_ir_func_0(i64 [[ARG1:%.*]], i64 [[ARG0:%.*]]), !dbg [[DBG10:![0-9]+]] +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: ret void +; +; +; CHECK-LABEL: define internal void @outlined_ir_func_0( +; CHECK-NEXT: newFuncRoot: +; CHECK-NEXT: br label [[BB0_TO_OUTLINE:%.*]] +; CHECK: bb0_to_outline: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB0_TO_OUTLINE]] ], [ [[TMP0:%.*]], [[BB1]] ] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], [[TMP1:%.*]] +; CHECK-NEXT: br i1 [[ICMP]], label [[BB1]], label [[BB2_EXITSTUB:%.*]], !llvm.loop [[LOOP12:![0-9]+]] +; CHECK: bb2.exitStub: +; CHECK-NEXT: ret void +;