[llvm] fe6f6cd - [DebugInfo] Prevent explosion of debug intrinsics during jump threading

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 12 03:39:34 PST 2020


Author: stozer
Date: 2020-02-12T11:22:54Z
New Revision: fe6f6cd6b8e647c5b4ac82f4fcd56c057c2ef8ce

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

LOG: [DebugInfo] Prevent explosion of debug intrinsics during jump threading

This patch is a fix following the revert of 72ce759
(https://reviews.llvm.org/rG72ce759928e6dfee6a9efa310b966c19722352ba)
and fixes the failure that it caused.

The above patch failed on the Thread Sanitizer buildbot with an out of
memory error. After an investigation, the cause was identified as an
explosion in debug intrinsics while running the Jump Threading pass on
ModuleMap.ll. The above patched prevented debug intrinsics from being
dropped when their Basic Block was deleted due to being "empty". In this
case, one of the functions in ModuleMap.ll had (after many optimization
passes) a very large number of debug intrinsics representing a set of
repeatedly inlined variables. Previously the vast majority of these were
silently dropped during Jump Threading when their blocks were deleted,
but as of the above patch they survived for longer, causing a large
increase in the number of debug intrinsics. These intrinsics were then
repeatedly cloned by the Jump Threading pass as edges were threaded,
multiplying the intrinsic count further. The memory consumed by this
process spiralled out of control, crashing the buildbot that uses TSan
(which has an estimated 5-10x memory overhead compared to non-sanitized
builds).

This patch adds RemoveRedundantDbgInstrs to the Jump Threading pass, in
order to reduce the number of debug intrinsics down to a manageable
amount in cases where many intrinsics for the same variable end up
bunched together contiguously, as in this case.

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

Added: 
    llvm/test/Transforms/JumpThreading/redundant-dbg-info.ll

Modified: 
    llvm/lib/Transforms/Scalar/JumpThreading.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index a48b8e323428..411e3c1cca2a 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -405,6 +405,12 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
         continue;
       while (ProcessBlock(&BB)) // Thread all of the branches we can over BB.
         Changed = true;
+
+      // Jump threading may have introduced redundant debug values into BB
+      // which should be removed.
+      if (Changed)
+        RemoveRedundantDbgInstrs(&BB);
+
       // Stop processing BB if it's the entry or is now deleted. The following
       // routines attempt to eliminate BB and locating a suitable replacement
       // for the entry is non-trivial.
@@ -427,17 +433,21 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_,
       // ProcessBlock doesn't thread BBs with unconditional TIs. However, if BB
       // is "almost empty", we attempt to merge BB with its sole successor.
       auto *BI = dyn_cast<BranchInst>(BB.getTerminator());
-      if (BI && BI->isUnconditional() &&
-          // The terminator must be the only non-phi instruction in BB.
-          BB.getFirstNonPHIOrDbg()->isTerminator() &&
-          // Don't alter Loop headers and latches to ensure another pass can
-          // detect and transform nested loops later.
-          !LoopHeaders.count(&BB) && !LoopHeaders.count(BI->getSuccessor(0)) &&
-          TryToSimplifyUncondBranchFromEmptyBlock(&BB, DTU)) {
-        // BB is valid for cleanup here because we passed in DTU. F remains
-        // BB's parent until a DTU->getDomTree() event.
-        LVI->eraseBlock(&BB);
-        Changed = true;
+      if (BI && BI->isUnconditional()) {
+        BasicBlock *Succ = BI->getSuccessor(0);
+        if (
+            // The terminator must be the only non-phi instruction in BB.
+            BB.getFirstNonPHIOrDbg()->isTerminator() &&
+            // Don't alter Loop headers and latches to ensure another pass can
+            // detect and transform nested loops later.
+            !LoopHeaders.count(&BB) && !LoopHeaders.count(Succ) &&
+            TryToSimplifyUncondBranchFromEmptyBlock(&BB, DTU)) {
+          RemoveRedundantDbgInstrs(Succ);
+          // BB is valid for cleanup here because we passed in DTU. F remains
+          // BB's parent until a DTU->getDomTree() event.
+          LVI->eraseBlock(&BB);
+          Changed = true;
+        }
       }
     }
     EverChanged |= Changed;

diff  --git a/llvm/test/Transforms/JumpThreading/redundant-dbg-info.ll b/llvm/test/Transforms/JumpThreading/redundant-dbg-info.ll
new file mode 100644
index 000000000000..7927df9520de
--- /dev/null
+++ b/llvm/test/Transforms/JumpThreading/redundant-dbg-info.ll
@@ -0,0 +1,78 @@
+; RUN: opt -jump-threading -S < %s | FileCheck %s
+
+define dso_local i32 @_Z3fooi(i32 %a) !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %a, metadata !12, metadata !DIExpression()), !dbg !13
+  call void @llvm.dbg.value(metadata i32 1, metadata !14, metadata !DIExpression()), !dbg !13
+  %tobool = icmp ne i32 %a, 0, !dbg !15
+  br i1 %tobool, label %if.then, label %if.end, !dbg !17
+
+if.then:                                          ; preds = %entry
+  call void @_Z4callv(), !dbg !18
+  call void @llvm.dbg.value(metadata i32 0, metadata !14, metadata !DIExpression()), !dbg !13
+  br label %if.end, !dbg !20
+
+if.end:                                           ; preds = %if.then, %entry
+  %c.0 = phi i32 [ 0, %if.then ], [ 1, %entry ], !dbg !13
+  call void @llvm.dbg.value(metadata i32 %c.0, metadata !14, metadata !DIExpression()), !dbg !13
+  %tobool1 = icmp ne i32 %c.0, 0, !dbg !21
+  br i1 %tobool1, label %if.else, label %if.then2, !dbg !23
+
+; CHECK-LABEL: if.then2:
+; CHECK: call void @llvm.dbg.value({{.+}}, metadata ![[B:[0-9]+]], metadata !DIExpression())
+; CHECK: call void @llvm.dbg.value({{.+}}, metadata ![[B:[0-9]+]], metadata !DIExpression())
+; CHECK-NOT: call void @llvm.dbg.value({{.+}}, metadata ![[B]], metadata !DIExpression())
+if.then2:                                         ; preds = %if.end
+  call void @llvm.dbg.value(metadata i32 4, metadata !24, metadata !DIExpression()), !dbg !13
+  br label %if.end3, !dbg !25
+
+; CHECK-LABEL: if.end3:
+if.else:                                          ; preds = %if.end
+  call void @llvm.dbg.value(metadata i32 6, metadata !24, metadata !DIExpression()), !dbg !13
+  br label %if.end3
+
+if.end3:                                          ; preds = %if.else, %if.then2
+  %b.0 = phi i32 [ 6, %if.else ], [ 4, %if.then2 ], !dbg !27
+  call void @llvm.dbg.value(metadata i32 %b.0, metadata !24, metadata !DIExpression()), !dbg !13
+  ret i32 %b.0, !dbg !28
+}
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+declare dso_local void @_Z4callv()
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+; CHECK: ![[B]] = !DILocalVariable(name: "b"
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: false, 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 10.0.0"}
+!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !8, file: !8, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DIFile(filename: "./test.cpp", directory: "/")
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !8, line: 3, type: !11)
+!13 = !DILocation(line: 0, scope: !7)
+!14 = !DILocalVariable(name: "c", scope: !7, file: !8, line: 4, type: !11)
+!15 = !DILocation(line: 5, column: 7, scope: !16)
+!16 = distinct !DILexicalBlock(scope: !7, file: !8, line: 5, column: 7)
+!17 = !DILocation(line: 5, column: 7, scope: !7)
+!18 = !DILocation(line: 6, column: 5, scope: !19)
+!19 = distinct !DILexicalBlock(scope: !16, file: !8, line: 5, column: 10)
+!20 = !DILocation(line: 8, column: 3, scope: !19)
+!21 = !DILocation(line: 9, column: 8, scope: !22)
+!22 = distinct !DILexicalBlock(scope: !7, file: !8, line: 9, column: 7)
+!23 = !DILocation(line: 9, column: 7, scope: !7)
+!24 = !DILocalVariable(name: "b", scope: !7, file: !8, line: 4, type: !11)
+!25 = !DILocation(line: 11, column: 3, scope: !26)
+!26 = distinct !DILexicalBlock(scope: !22, file: !8, line: 9, column: 11)
+!27 = !DILocation(line: 0, scope: !22)
+!28 = !DILocation(line: 14, column: 3, scope: !7)


        


More information about the llvm-commits mailing list