[clang] ab76cfd - Recommit "[CodeView] Add option to disable inline line tables."

Amy Huang via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 4 09:15:50 PST 2019


Author: Amy Huang
Date: 2019-11-04T09:15:26-08:00
New Revision: ab76cfdd200d35177df2042a1c0c7e86868d01bc

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

LOG: Recommit "[CodeView] Add option to disable inline line tables."

This reverts commit 004ed2b0d1b86d424643ffc88fce20ad8bab6804.
Original commit hash 6d03890384517919a3ba7fe4c35535425f278f89

Summary:
This adds a clang option to disable inline line tables. When it is used,
the inliner uses the call site as the location of the inlined function instead of
marking it as an inline location with the function location.

https://reviews.llvm.org/D67723

Added: 
    clang/test/CodeGen/debug-info-no-inline-line-tables.c
    llvm/test/Transforms/Inline/no-inline-line-tables.ll

Modified: 
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Driver/Options.td
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Frontend/CompilerInvocation.cpp
    llvm/docs/LangRef.rst
    llvm/include/llvm/IR/Attributes.td
    llvm/lib/Transforms/Utils/InlineFunction.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 0a47869af61b..99559b5abe7b 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -138,6 +138,8 @@ CODEGENOPT(FatalWarnings     , 1, 0) ///< Set when -Wa,--fatal-warnings is
                                      ///< enabled.
 CODEGENOPT(NoWarn            , 1, 0) ///< Set when -Wa,--no-warn is enabled.
 CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
+CODEGENOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
+                                     ///< inline line tables.
 CODEGENOPT(NoImplicitFloat   , 1, 0) ///< Set when -mno-implicit-float is enabled.
 CODEGENOPT(NoInfsFPMath      , 1, 0) ///< Assume FP arguments, results not +-Inf.
 CODEGENOPT(NoSignedZeros     , 1, 0) ///< Allow ignoring the signedness of FP zero

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3093dc65fce4..47e8bbf3eb12 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1998,6 +1998,9 @@ def gcodeview_ghash : Flag<["-"], "gcodeview-ghash">,
   HelpText<"Emit type record hashes in a .debug$H section">,
   Flags<[CC1Option, CoreOption]>;
 def gno_codeview_ghash : Flag<["-"], "gno-codeview-ghash">, Flags<[CoreOption]>;
+def ginline_line_tables : Flag<["-"], "ginline-line-tables">, Flags<[CoreOption]>;
+def gno_inline_line_tables : Flag<["-"], "gno-inline-line-tables">,
+  Flags<[CC1Option, CoreOption]>, HelpText<"Don't emit inline line tables">;
 
 def gfull : Flag<["-"], "gfull">, Group<g_Group>;
 def gused : Flag<["-"], "gused">, Group<g_Group>;

diff  --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 3f9a52ab7638..1b1d391a63df 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -764,6 +764,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
   Fn->addFnAttr("no-jump-tables",
                 llvm::toStringRef(CGM.getCodeGenOpts().NoUseJumpTables));
 
+  // Add no-inline-line-tables value.
+  if (CGM.getCodeGenOpts().NoInlineLineTables)
+    Fn->addFnAttr("no-inline-line-tables");
+
   // Add profile-sample-accurate value.
   if (CGM.getCodeGenOpts().ProfileSampleAccurate)
     Fn->addFnAttr("profile-sample-accurate");

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 529c33a16748..369d8cc1aa96 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3312,6 +3312,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
     }
   }
 
+  // Omit inline line tables if requested.
+  if (Args.hasFlag(options::OPT_gno_inline_line_tables,
+                   options::OPT_ginline_line_tables, false)) {
+    CmdArgs.push_back("-gno-inline-line-tables");
+  }
+
   // Adjust the debug info kind for the given toolchain.
   TC.adjustDebugInfoKind(DebugInfoKind, Args);
 

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 0775d1021c54..c935ce5ebab5 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -809,6 +809,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
   Opts.RecordCommandLine = Args.getLastArgValue(OPT_record_command_line);
   Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
   Opts.NoCommon = Args.hasArg(OPT_fno_common);
+  Opts.NoInlineLineTables = Args.hasArg(OPT_gno_inline_line_tables);
   Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
   Opts.OptimizeSize = getOptimizationLevelSize(Args);
   Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||

diff  --git a/clang/test/CodeGen/debug-info-no-inline-line-tables.c b/clang/test/CodeGen/debug-info-no-inline-line-tables.c
new file mode 100644
index 000000000000..ac9216247c82
--- /dev/null
+++ b/clang/test/CodeGen/debug-info-no-inline-line-tables.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited \
+// RUN:   -gno-inline-line-tables -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang -gno-inline-line-tables -S -emit-llvm -o - %s | FileCheck %s \
+// RUN:   -check-prefix=INLINE-FLAG
+// RUN: %clang -S -emit-llvm -o - %s | FileCheck %s -check-prefix=NO-FLAG
+
+int x;
+__attribute((always_inline)) void f() {
+  x += 1;
+}
+int main() {
+  f();
+  x += 2;
+  return x;
+}
+
+// Check that clang emits the location of the call site and not the inlined
+// function in the debug info.
+// CHECK: define dso_local i32 @main()
+// CHECK: %{{.+}} = load i32, i32* @x, align 4, !dbg [[DbgLoc:![0-9]+]]
+
+// Check that the no-inline-line-tables attribute is added.
+// CHECK: attributes #0 = {{.*}}"no-inline-line-tables"{{.*}}
+// CHECK: attributes #1 = {{.*}}"no-inline-line-tables"{{.*}}
+
+// CHECK: [[DbgLoc]] = !DILocation(line: 12,
+// CHECK-NOT:  inlinedAt:
+
+// INLINE-FLAG: attributes #0 = {{.*}}"no-inline-line-tables"{{.*}}
+// INLINE-FLAG: attributes #1 = {{.*}}"no-inline-line-tables"{{.*}}
+// NO-FLAG-NOT: "no-inline-line-tables"

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6e99f25b572a..b6b94dd3078f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1456,6 +1456,13 @@ example:
 ``naked``
     This attribute disables prologue / epilogue emission for the
     function. This can have very system-specific consequences.
+``"no-inline-line-tables"``
+    When this attribute is set to true, the inliner discards source locations
+    when inlining code and instead uses the source location of the call site.
+    Breakpoints set on code that was inlined into the current function will
+    not fire during the execution of the inlined call sites. If the debugger
+    stops inside an inlined call site, it will appear to be stopped at the
+    outermost inlined call site.
 ``no-jump-tables``
     When this attribute is set to true, the jump tables and lookup tables that
     can be generated from a switch case lowering are disabled.

diff  --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index 153046d2311c..5d4a5f6743b7 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -220,6 +220,7 @@ def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
 def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
 def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
 def NoJumpTables : StrBoolAttr<"no-jump-tables">;
+def NoInlineLineTables : StrBoolAttr<"no-inline-line-tables">;
 def ProfileSampleAccurate : StrBoolAttr<"profile-sample-accurate">;
 
 class CompatRule<string F> {

diff  --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 7e08da355634..b522dd2b631a 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1405,6 +1405,10 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
   // other.
   DenseMap<const MDNode *, MDNode *> IANodes;
 
+  // Check if we are not generating inline line tables and want to use
+  // the call site location instead.
+  bool NoInlineLineTables = Fn->hasFnAttribute("no-inline-line-tables");
+
   for (; FI != Fn->end(); ++FI) {
     for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
          BI != BE; ++BI) {
@@ -1416,20 +1420,22 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
         BI->setMetadata(LLVMContext::MD_loop, NewLoopID);
       }
 
-      if (DebugLoc DL = BI->getDebugLoc()) {
-        DebugLoc IDL =
-            inlineDebugLoc(DL, InlinedAtNode, BI->getContext(), IANodes);
-        BI->setDebugLoc(IDL);
-        continue;
-      }
+      if (!NoInlineLineTables)
+        if (DebugLoc DL = BI->getDebugLoc()) {
+          DebugLoc IDL =
+              inlineDebugLoc(DL, InlinedAtNode, BI->getContext(), IANodes);
+          BI->setDebugLoc(IDL);
+          continue;
+        }
 
-      if (CalleeHasDebugInfo)
+      if (CalleeHasDebugInfo && !NoInlineLineTables)
         continue;
 
-      // If the inlined instruction has no line number, make it look as if it
-      // originates from the call location. This is important for
-      // ((__always_inline__, __nodebug__)) functions which must use caller
-      // location for all instructions in their function body.
+      // If the inlined instruction has no line number, or if inline info
+      // is not being generated, make it look as if it originates from the call
+      // location. This is important for ((__always_inline, __nodebug__))
+      // functions which must use caller location for all instructions in their
+      // function body.
 
       // Don't update static allocas, as they may get moved later.
       if (auto *AI = dyn_cast<AllocaInst>(BI))
@@ -1438,6 +1444,19 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
 
       BI->setDebugLoc(TheCallDL);
     }
+
+    // Remove debug info intrinsics if we're not keeping inline info.
+    if (NoInlineLineTables) {
+      BasicBlock::iterator BI = FI->begin();
+      while (BI != FI->end()) {
+        if (isa<DbgInfoIntrinsic>(BI)) {
+          BI = BI->eraseFromParent();
+          continue;
+        }
+        ++BI;
+      }
+    }
+
   }
 }
 

diff  --git a/llvm/test/Transforms/Inline/no-inline-line-tables.ll b/llvm/test/Transforms/Inline/no-inline-line-tables.ll
new file mode 100644
index 000000000000..b20f6b75888d
--- /dev/null
+++ b/llvm/test/Transforms/Inline/no-inline-line-tables.ll
@@ -0,0 +1,99 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+
+; This tests that functions with the attribute `no-inline-line-tables` have the
+; correct debug information when they are inlined.
+
+; ModuleID = 't.c'
+source_filename = "t.c"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-windows-msvc"
+
+; Function Attrs: alwaysinline nounwind
+define dso_local i32 @f(i32 %x) #0 !dbg !7 {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !12, metadata !DIExpression()), !dbg !13
+  %0 = load i32, i32* %x.addr, align 4, !dbg !14
+  ret i32 %0, !dbg !14
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: alwaysinline nounwind
+define i32 @g(i32 %x) #0 !dbg !15 {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !16, metadata !DIExpression()), !dbg !17
+  br label %L, !dbg !17
+
+L:                                                ; preds = %entry
+  call void @llvm.dbg.label(metadata !18), !dbg !19
+  store i32 42, i32* %x.addr, align 4, !dbg !20
+  %0 = load i32, i32* %x.addr, align 4, !dbg !21
+  ret i32 %0, !dbg !21
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.label(metadata) #1
+
+; Check that debug info for inlined code uses the call location and that debug
+; intrinsics are removed.
+; Function Attrs: noinline nounwind optnone
+define i32 @main() #2 !dbg !22 {
+entry:
+; CHECK-LABEL: @main()
+; CHECK-NOT: @f
+; CHECK-NOT: @llvm.dbg.declare
+; CHECK: %{{[0-9]+}} = load i32, i32* %x.addr.i, align 4, !dbg ![[VAR1:[0-9]+]]
+  %call = call i32 @f(i32 3), !dbg !25
+
+; Another test for inlining debug intrinsics where the intrinsic appears at the
+; start of the basic block.
+; CHECK-NOT: @g
+; CHECK-NOT: @llvm.dbg.label
+; CHECK: %{{[0-9]+}} = load i32, i32* %x.addr.i1, align 4, !dbg ![[VAR2:[0-9]+]]
+  %call1 = call i32 @g(i32 340), !dbg !26
+  ret i32 0, !dbg !27
+}
+
+; CHECK: ![[VAR1]] = !DILocation(line: 10, scope: ![[SCOPE:[0-9]+]])
+; CHECK: ![[VAR2]] = !DILocation(line: 11, scope: ![[SCOPE]])
+
+attributes #0 = { alwaysinline nounwind "no-inline-line-tables" }
+attributes #2 = { noinline nounwind optnone "no-inline-line-tables"}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 03ec3a12a94bbbaa11999b6da3a43221a5aa54a5)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "<stdin>", directory: "/usr/local/google/home/akhuang/testing/inline-line-tables", checksumkind: CSK_MD5, checksum: "38a4785b48742d3ea655b8f3461436a4")
+!2 = !{}
+!3 = !{i32 2, !"CodeView", i32 1}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 03ec3a12a94bbbaa11999b6da3a43221a5aa54a5)"}
+!7 = distinct !DISubprogram(name: "f", scope: !8, file: !8, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DIFile(filename: "t.c", directory: "/usr/local/google/home/akhuang/testing/inline-line-tables", checksumkind: CSK_MD5, checksum: "38a4785b48742d3ea655b8f3461436a4")
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !DILocalVariable(name: "x", arg: 1, scope: !7, file: !8, line: 1, type: !11)
+!13 = !DILocation(line: 1, scope: !7)
+!14 = !DILocation(line: 2, scope: !7)
+!15 = distinct !DISubprogram(name: "g", scope: !8, file: !8, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!16 = !DILocalVariable(name: "x", arg: 1, scope: !15, file: !8, line: 4, type: !11)
+!17 = !DILocation(line: 4, scope: !15)
+!18 = !DILabel(scope: !15, name: "L", file: !8, line: 5)
+!19 = !DILocation(line: 5, scope: !15)
+!20 = !DILocation(line: 6, scope: !15)
+!21 = !DILocation(line: 7, scope: !15)
+!22 = distinct !DISubprogram(name: "main", scope: !8, file: !8, line: 9, type: !23, scopeLine: 9, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!23 = !DISubroutineType(types: !24)
+!24 = !{!11}
+!25 = !DILocation(line: 10, scope: !22)
+!26 = !DILocation(line: 11, scope: !22)
+!27 = !DILocation(line: 12, scope: !22)


        


More information about the cfe-commits mailing list