[IROutliner] Make sure that loop debug info is stripped.
authorAndrew Litteken <andrew.litteken@gmail.com>
Mon, 14 Mar 2022 04:45:29 +0000 (23:45 -0500)
committerAndrew Litteken <andrew.litteken@gmail.com>
Thu, 17 Mar 2022 20:41:53 +0000 (14:41 -0600)
As pointed out in https://github.com/llvm/llvm-project/issues/54155#issuecomment-1057465479, there was a crash when loop info was being outlined. It was not being properly stripped and adjusted, so would point to the wrong location. This uses similar logic found in the CodeExtractor to adjust the loop debug info.

Reviewer: fhahn, paquette

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

llvm/lib/Transforms/IPO/IROutliner.cpp
llvm/test/Transforms/IROutliner/outlining-strip-loop-info.ll [new file with mode: 0644]

index a7b77ee..51e1f99 100644 (file)
@@ -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 @@ static void moveFunctionData(Function &Old, Function &New,
       if (!isa<CallInst>(&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<DILocation>(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 (file)
index 0000000..53b798f
--- /dev/null
@@ -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
+;