[llvm] r285094 - Add -strip-nonlinetable-debuginfo capability

Michael Ilseman via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 25 11:44:13 PDT 2016


Author: milseman
Date: Tue Oct 25 13:44:13 2016
New Revision: 285094

URL: http://llvm.org/viewvc/llvm-project?rev=285094&view=rev
Log:
Add -strip-nonlinetable-debuginfo capability

This adds a new function to DebugInfo.cpp that takes an llvm::Module
as input and removes all debug info metadata that is not directly
needed for line tables, thus effectively stripping all type and
variable information from the module.

The primary motivation for this feature was the bitcode work flow
(cf. http://lists.llvm.org/pipermail/llvm-dev/2016-June/100643.html
for more background). This is not wired up yet, but will be in
subsequent patches.  For testing, the new functionality is exposed to
opt with a -strip-nonlinetable-debuginfo option.

The secondary use-case (and one that works right now!) is as a
reduction pass in bugpoint. I added two new bugpoint options
(-disable-strip-debuginfo and -disable-strip-debug-types) to control
the new features. By default it will first attempt to remove all debug
information, then only the type info, and then proceed to hack at any
remaining MDNodes.

Thanks to Adrian Prantl for stewarding this patch!

Added:
    llvm/trunk/lib/Transforms/Utils/StripNonLineTableDebugInfo.cpp
    llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll
    llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll
    llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll
    llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll
Modified:
    llvm/trunk/include/llvm/IR/DebugInfo.h
    llvm/trunk/include/llvm/IR/Metadata.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/include/llvm/Transforms/IPO.h
    llvm/trunk/lib/IR/DebugInfo.cpp
    llvm/trunk/lib/IR/Metadata.cpp
    llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
    llvm/trunk/lib/Transforms/Utils/Utils.cpp
    llvm/trunk/test/BugPoint/metadata.ll
    llvm/trunk/test/BugPoint/named-md.ll
    llvm/trunk/tools/bugpoint/CrashDebugger.cpp

Modified: llvm/trunk/include/llvm/IR/DebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfo.h?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfo.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfo.h Tue Oct 25 13:44:13 2016
@@ -44,6 +44,18 @@ DISubprogram *getDISubprogram(const MDNo
 bool StripDebugInfo(Module &M);
 bool stripDebugInfo(Function &F);
 
+/// Downgrade the debug info in a module to contain only line table information.
+///
+/// In order to convert debug info to what -gline-tables-only would have
+/// created, this does the following:
+///   1) Delete all debug intrinsics.
+///   2) Delete all non-CU named metadata debug info nodes.
+///   3) Create new DebugLocs for each instruction.
+///   4) Create a new CU debug info, and similarly for every metadata node
+///      that's reachable from the CU debug info.
+///   All debug type metadata nodes are unreachable and garbage collected.
+bool stripNonLineTableDebugInfo(Module &M);
+
 /// \brief Return Debug Info Metadata Version by checking module flags.
 unsigned getDebugMetadataVersionFromModule(const Module &M);
 

Modified: llvm/trunk/include/llvm/IR/Metadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Metadata.h (original)
+++ llvm/trunk/include/llvm/IR/Metadata.h Tue Oct 25 13:44:13 2016
@@ -1299,8 +1299,10 @@ public:
   /// \brief Drop all references and remove the node from parent module.
   void eraseFromParent();
 
-  /// \brief Remove all uses and clear node vector.
-  void dropAllReferences();
+  /// Remove all uses and clear node vector.
+  void dropAllReferences() { clearOperands(); }
+  /// Drop all references to this node's operands.
+  void clearOperands();
 
   ~NamedMDNode();
 

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Tue Oct 25 13:44:13 2016
@@ -330,6 +330,7 @@ void initializeStripDeadDebugInfoPass(Pa
 void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&);
 void initializeStripDebugDeclarePass(PassRegistry&);
 void initializeStripNonDebugSymbolsPass(PassRegistry&);
+void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
 void initializeStripSymbolsPass(PassRegistry&);
 void initializeStructurizeCFGPass(PassRegistry&);
 void initializeTailCallElimPass(PassRegistry&);

Modified: llvm/trunk/include/llvm/Transforms/IPO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO.h Tue Oct 25 13:44:13 2016
@@ -43,6 +43,10 @@ ModulePass *createStripSymbolsPass(bool
 //
 ModulePass *createStripNonDebugSymbolsPass();
 
+/// This function returns a new pass that downgrades the debug info in the
+/// module to line tables only.
+ModulePass *createStripNonLineTableDebugInfoPass();
+
 //===----------------------------------------------------------------------===//
 //
 // These pass removes llvm.dbg.declare intrinsics.

Modified: llvm/trunk/lib/IR/DebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfo.cpp?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfo.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfo.cpp Tue Oct 25 13:44:13 2016
@@ -300,6 +300,299 @@ bool llvm::StripDebugInfo(Module &M) {
   return Changed;
 }
 
+namespace {
+
+/// Helper class to downgrade -g metadata to -gline-tables-only metadata.
+class DebugTypeInfoRemoval {
+  DenseMap<Metadata *, Metadata *> Replacements;
+
+public:
+  /// The (void)() type.
+  MDNode *EmptySubroutineType;
+
+private:
+  /// Remember what linkage name we originally had before stripping. If we end
+  /// up making two subprograms identical who originally had different linkage
+  /// names, then we need to make one of them distinct, to avoid them getting
+  /// uniqued. Maps the new node to the old linkage name.
+  DenseMap<DISubprogram *, StringRef> NewToLinkageName;
+
+  // TODO: Remember the distinct subprogram we created for a given linkage name,
+  // so that we can continue to unique whenever possible. Map <newly created
+  // node, old linkage name> to the first (possibly distinct) mdsubprogram
+  // created for that combination. This is not strictly needed for correctness,
+  // but can cut down on the number of MDNodes and let us diff cleanly with the
+  // output of -gline-tables-only.
+
+public:
+  DebugTypeInfoRemoval(LLVMContext &C)
+      : EmptySubroutineType(DISubroutineType::get(C, DINode::FlagZero, 0,
+                                                  MDNode::get(C, {}))) {}
+
+  Metadata *map(Metadata *M) {
+    if (!M)
+      return nullptr;
+    auto Replacement = Replacements.find(M);
+    if (Replacement != Replacements.end())
+      return Replacement->second;
+
+    return M;
+  }
+  MDNode *mapNode(Metadata *N) { return dyn_cast_or_null<MDNode>(map(N)); }
+
+  /// Recursively remap N and all its referenced children. Does a DF post-order
+  /// traversal, so as to remap bottoms up.
+  void traverseAndRemap(MDNode *N) { traverse(N); }
+
+private:
+  // Create a new DISubprogram, to replace the one given.
+  DISubprogram *getReplacementSubprogram(DISubprogram *MDS) {
+    auto *FileAndScope = cast_or_null<DIFile>(map(MDS->getFile()));
+    StringRef LinkageName = MDS->getName().empty() ? MDS->getLinkageName() : "";
+    DISubprogram *Declaration = nullptr;
+    auto *Type = cast_or_null<DISubroutineType>(map(MDS->getType()));
+    DITypeRef ContainingType(map(MDS->getContainingType()));
+    auto *Unit = cast_or_null<DICompileUnit>(map(MDS->getUnit()));
+    auto Variables = nullptr;
+    auto TemplateParams = nullptr;
+
+    // Make a distinct DISubprogram, for situations that warrent it.
+    auto distinctMDSubprogram = [&]() {
+      return DISubprogram::getDistinct(
+          MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
+          FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
+          MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
+          MDS->getVirtuality(), MDS->getVirtualIndex(),
+          MDS->getThisAdjustment(), MDS->getFlags(), MDS->isOptimized(), Unit,
+          TemplateParams, Declaration, Variables);
+    };
+
+    if (MDS->isDistinct())
+      return distinctMDSubprogram();
+
+    auto *NewMDS = DISubprogram::get(
+        MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
+        FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
+        MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
+        MDS->getVirtuality(), MDS->getVirtualIndex(), MDS->getThisAdjustment(),
+        MDS->getFlags(), MDS->isOptimized(), Unit, TemplateParams, Declaration,
+        Variables);
+
+    StringRef OldLinkageName = MDS->getLinkageName();
+
+    // See if we need to make a distinct one.
+    auto OrigLinkage = NewToLinkageName.find(NewMDS);
+    if (OrigLinkage != NewToLinkageName.end()) {
+      if (OrigLinkage->second == OldLinkageName)
+        // We're good.
+        return NewMDS;
+
+      // Otherwise, need to make a distinct one.
+      // TODO: Query the map to see if we already have one.
+      return distinctMDSubprogram();
+    }
+
+    NewToLinkageName.insert({NewMDS, MDS->getLinkageName()});
+    return NewMDS;
+  }
+
+  /// Create a new compile unit, to replace the one given
+  DICompileUnit *getReplacementCU(DICompileUnit *CU) {
+    // Drop skeleton CUs.
+    if (CU->getDWOId())
+      return nullptr;
+
+    auto *File = cast_or_null<DIFile>(map(CU->getFile()));
+    MDTuple *EnumTypes = nullptr;
+    MDTuple *RetainedTypes = nullptr;
+    MDTuple *GlobalVariables = nullptr;
+    MDTuple *ImportedEntities = nullptr;
+    return DICompileUnit::getDistinct(
+        CU->getContext(), CU->getSourceLanguage(), File, CU->getProducer(),
+        CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
+        CU->getSplitDebugFilename(), DICompileUnit::LineTablesOnly, EnumTypes,
+        RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros(),
+        CU->getDWOId(), CU->getSplitDebugInlining());
+  }
+
+  DILocation *getReplacementMDLocation(DILocation *MLD) {
+    auto *Scope = map(MLD->getScope());
+    auto *InlinedAt = map(MLD->getInlinedAt());
+    if (MLD->isDistinct())
+      return DILocation::getDistinct(MLD->getContext(), MLD->getLine(),
+                                     MLD->getColumn(), Scope, InlinedAt);
+    return DILocation::get(MLD->getContext(), MLD->getLine(), MLD->getColumn(),
+                           Scope, InlinedAt);
+  }
+
+  /// Create a new generic MDNode, to replace the one given
+  MDNode *getReplacementMDNode(MDNode *N) {
+    SmallVector<Metadata *, 8> Ops;
+    Ops.reserve(N->getNumOperands());
+    for (auto &I : N->operands())
+      if (I)
+        Ops.push_back(map(I));
+    auto *Ret = MDNode::get(N->getContext(), Ops);
+    return Ret;
+  }
+
+  /// Attempt to re-map N to a newly created node.
+  void remap(MDNode *N) {
+    if (Replacements.count(N))
+      return;
+
+    auto doRemap = [&](MDNode *N) -> MDNode * {
+      if (!N)
+        return nullptr;
+      if (auto *MDSub = dyn_cast<DISubprogram>(N)) {
+        remap(MDSub->getUnit());
+        return getReplacementSubprogram(MDSub);
+      }
+      if (isa<DISubroutineType>(N))
+        return EmptySubroutineType;
+      if (auto *CU = dyn_cast<DICompileUnit>(N))
+        return getReplacementCU(CU);
+      if (isa<DIFile>(N))
+        return N;
+      if (auto *MDLB = dyn_cast<DILexicalBlockBase>(N))
+        // Remap to our referenced scope (recursively).
+        return mapNode(MDLB->getScope());
+      if (auto *MLD = dyn_cast<DILocation>(N))
+        return getReplacementMDLocation(MLD);
+
+      // Otherwise, if we see these, just drop them now. Not strictly necessary,
+      // but this speeds things up a little.
+      if (isa<DINode>(N))
+        return nullptr;
+
+      return getReplacementMDNode(N);
+    };
+    Replacements[N] = doRemap(N);
+  }
+
+  /// Do the remapping traversal.
+  void traverse(MDNode *);
+};
+
+} // Anonymous namespace.
+
+void DebugTypeInfoRemoval::traverse(MDNode *N) {
+  if (!N || Replacements.count(N))
+    return;
+
+  // To avoid cycles, as well as for efficiency sake, we will sometimes prune
+  // parts of the graph.
+  auto prune = [](MDNode *Parent, MDNode *Child) {
+    if (auto *MDS = dyn_cast<DISubprogram>(Parent))
+      return Child == MDS->getVariables().get();
+    return false;
+  };
+
+  SmallVector<MDNode *, 16> ToVisit;
+  DenseSet<MDNode *> Opened;
+
+  // Visit each node starting at N in post order, and map them.
+  ToVisit.push_back(N);
+  while (!ToVisit.empty()) {
+    auto *N = ToVisit.back();
+    if (!Opened.insert(N).second) {
+      // Close it.
+      remap(N);
+      ToVisit.pop_back();
+      continue;
+    }
+    for (auto &I : N->operands())
+      if (auto *MDN = dyn_cast_or_null<MDNode>(I))
+        if (!Opened.count(MDN) && !Replacements.count(MDN) && !prune(N, MDN) &&
+            !isa<DICompileUnit>(MDN))
+          ToVisit.push_back(MDN);
+  }
+}
+
+bool llvm::stripNonLineTableDebugInfo(Module &M) {
+  bool Changed = false;
+
+  // First off, delete the debug intrinsics.
+  auto RemoveUses = [&](StringRef Name) {
+    if (auto *DbgVal = M.getFunction(Name)) {
+      while (!DbgVal->use_empty())
+        cast<Instruction>(DbgVal->user_back())->eraseFromParent();
+      DbgVal->eraseFromParent();
+      Changed = true;
+    }
+  };
+  RemoveUses("llvm.dbg.declare");
+  RemoveUses("llvm.dbg.value");
+
+  // Delete non-CU debug info named metadata nodes.
+  for (auto NMI = M.named_metadata_begin(), NME = M.named_metadata_end();
+       NMI != NME;) {
+    NamedMDNode *NMD = &*NMI;
+    ++NMI;
+    // Specifically keep dbg.cu around.
+    if (NMD->getName() == "llvm.dbg.cu")
+      continue;
+  }
+
+  // Drop all dbg attachments from global variables.
+  for (auto &GV : M.globals())
+    GV.eraseMetadata(LLVMContext::MD_dbg);
+
+  DebugTypeInfoRemoval Mapper(M.getContext());
+  auto remap = [&](llvm::MDNode *Node) -> llvm::MDNode * {
+    if (!Node)
+      return nullptr;
+    Mapper.traverseAndRemap(Node);
+    auto *NewNode = Mapper.mapNode(Node);
+    Changed |= Node != NewNode;
+    Node = NewNode;
+    return NewNode;
+  };
+
+  // Rewrite the DebugLocs to be equivalent to what
+  // -gline-tables-only would have created.
+  for (auto &F : M) {
+    if (auto *SP = F.getSubprogram()) {
+      Mapper.traverseAndRemap(SP);
+      auto *NewSP = cast<DISubprogram>(Mapper.mapNode(SP));
+      Changed |= SP != NewSP;
+      F.setSubprogram(NewSP);
+    }
+    for (auto &BB : F) {
+      for (auto &I : BB) {
+        if (I.getDebugLoc() == DebugLoc())
+          continue;
+
+        // Make a replacement.
+        auto &DL = I.getDebugLoc();
+        auto *Scope = DL.getScope();
+        MDNode *InlinedAt = DL.getInlinedAt();
+        Scope = remap(Scope);
+        InlinedAt = remap(InlinedAt);
+        I.setDebugLoc(
+            DebugLoc::get(DL.getLine(), DL.getCol(), Scope, InlinedAt));
+      }
+    }
+  }
+
+  // Create a new llvm.dbg.cu, which is equivalent to the one
+  // -gline-tables-only would have created.
+  for (auto &NMD : M.getNamedMDList()) {
+    SmallVector<MDNode *, 8> Ops;
+    for (MDNode *Op : NMD.operands())
+      Ops.push_back(remap(Op));
+ 
+    if (!Changed)
+      continue;
+ 
+    NMD.clearOperands();
+    for (auto *Op : Ops)
+      if (Op)
+        NMD.addOperand(Op);
+  }
+  return Changed;
+}
+
 unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
   if (auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
           M.getModuleFlag("Debug Info Version")))

Modified: llvm/trunk/lib/IR/Metadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Metadata.cpp (original)
+++ llvm/trunk/lib/IR/Metadata.cpp Tue Oct 25 13:44:13 2016
@@ -1054,7 +1054,7 @@ void NamedMDNode::setOperand(unsigned I,
 
 void NamedMDNode::eraseFromParent() { getParent()->eraseNamedMetadata(this); }
 
-void NamedMDNode::dropAllReferences() { getNMDOps(Operands).clear(); }
+void NamedMDNode::clearOperands() { getNMDOps(Operands).clear(); }
 
 StringRef NamedMDNode::getName() const { return StringRef(Name); }
 

Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Tue Oct 25 13:44:13 2016
@@ -43,6 +43,7 @@ add_llvm_library(LLVMTransformUtils
   SimplifyInstructions.cpp
   SimplifyLibCalls.cpp
   SplitModule.cpp
+  StripNonLineTableDebugInfo.cpp
   SymbolRewriter.cpp
   UnifyFunctionExitNodes.cpp
   Utils.cpp

Added: llvm/trunk/lib/Transforms/Utils/StripNonLineTableDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/StripNonLineTableDebugInfo.cpp?rev=285094&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/StripNonLineTableDebugInfo.cpp (added)
+++ llvm/trunk/lib/Transforms/Utils/StripNonLineTableDebugInfo.cpp Tue Oct 25 13:44:13 2016
@@ -0,0 +1,42 @@
+//===- StripNonLineTableDebugInfo.cpp -- Strip parts of Debug Info --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/IPO.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/Pass.h"
+using namespace llvm;
+
+namespace {
+
+/// This pass strips all debug info that is not related line tables.
+/// The result will be the same as if the program where compiled with
+/// -gline-tables-only.
+struct StripNonLineTableDebugInfo : public ModulePass {
+  static char ID; // Pass identification, replacement for typeid
+  StripNonLineTableDebugInfo() : ModulePass(ID) {
+    initializeStripNonLineTableDebugInfoPass(*PassRegistry::getPassRegistry());
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  bool runOnModule(Module &M) override {
+    return llvm::stripNonLineTableDebugInfo(M);
+  }
+};
+}
+
+char StripNonLineTableDebugInfo::ID = 0;
+INITIALIZE_PASS(StripNonLineTableDebugInfo, "strip-nonlinetable-debuginfo",
+                "Strip all debug info except linetables", false, false)
+
+ModulePass *llvm::createStripNonLineTableDebugInfoPass() {
+  return new StripNonLineTableDebugInfo();
+}

Modified: llvm/trunk/lib/Transforms/Utils/Utils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Utils.cpp?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Utils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Utils.cpp Tue Oct 25 13:44:13 2016
@@ -31,6 +31,7 @@ void llvm::initializeTransformUtils(Pass
   initializeLowerSwitchPass(Registry);
   initializeNameAnonGlobalLegacyPassPass(Registry);
   initializePromoteLegacyPassPass(Registry);
+  initializeStripNonLineTableDebugInfoPass(Registry);
   initializeUnifyFunctionExitNodesPass(Registry);
   initializeInstSimplifierPass(Registry);
   initializeMetaRenamerPass(Registry);

Modified: llvm/trunk/test/BugPoint/metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/BugPoint/metadata.ll?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/test/BugPoint/metadata.ll (original)
+++ llvm/trunk/test/BugPoint/metadata.ll Tue Oct 25 13:44:13 2016
@@ -1,10 +1,22 @@
-; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove > /dev/null
-; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
 ; REQUIRES: loadable_module
-
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo -disable-strip-debug-types > /dev/null
+; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
+;
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-nodebug -bugpoint-crashcalls -silence-passes -disable-namedmd-remove > /dev/null
+; RUN: llvm-dis %t-nodebug-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NODEBUG
+;
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo > /dev/null
+; RUN: llvm-dis %t-notype-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NOTYPE
+;
 ; Bugpoint should keep the call's metadata attached to the call.
 
 ; CHECK: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
+; NODEBUG: call void @foo(), !attach ![[CALL:[0-9]+]]
+; NOTYPE: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
+; NODEBUG-NOT: call void @foo(), !attach ![[CALL:[0-9]+]]
+; NOTYPE-NOT: !DIBasicType
+; NOTYPE: !DICompileUnit
+; NOTYPE-NOT: !DIBasicType
 ; CHECK-DAG: ![[LOC]] = !DILocation(line: 104, column: 105, scope: ![[SCOPE:[0-9]+]])
 ; CHECK-DAG: ![[SCOPE]] = distinct !DISubprogram(name: "test",{{.*}}file: ![[FILE:[0-9]+]]
 ; CHECK-DAG: ![[FILE]] = !DIFile(filename: "source.c", directory: "/dir")
@@ -32,7 +44,7 @@ declare void @foo()
 !4 = !{!"filler"}
 
 !8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !15)
-!9 = distinct !DISubprogram(name: "test", file: !15, unit: !8)
+!9 = distinct !DISubprogram(name: "test", file: !15, type: !18, unit: !8)
 !10 = !DILocation(line: 100, column: 101, scope: !9)
 !11 = !DILocation(line: 102, column: 103, scope: !9)
 !12 = !DILocation(line: 104, column: 105, scope: !9)
@@ -41,3 +53,6 @@ declare void @foo()
 !15 = !DIFile(filename: "source.c", directory: "/dir")
 !16 = !{}
 !17 = !{i32 1, !"Debug Info Version", i32 3}
+!18 = !DISubroutineType(types: !19)
+!19 = !{!20, !20}
+!20 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)

Modified: llvm/trunk/test/BugPoint/named-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/BugPoint/named-md.ll?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/test/BugPoint/named-md.ll (original)
+++ llvm/trunk/test/BugPoint/named-md.ll Tue Oct 25 13:44:13 2016
@@ -1,4 +1,4 @@
-; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
+; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes -disable-strip-debuginfo > /dev/null
 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
 ; RUN-DISABLE: bugpoint -disable-namedmd-remove -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
 ; RUN-DISABLE: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll?rev=285094&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll Tue Oct 25 13:44:13 2016
@@ -0,0 +1,92 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o %t.ll
+; RUN: cat %t.ll | FileCheck %s
+; RUN: cat %t.ll | FileCheck %s --check-prefix=CHECK-NEG
+;
+; This test provides coverage for setting the containing type of a DISubprogram.
+;
+; Generated an reduced from:
+; struct A {
+;   virtual ~A();
+; };
+; struct B : A {};
+; B b;
+
+source_filename = "t.cpp"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+%struct.B = type { %struct.A }
+%struct.A = type { i32 (...)** }
+
+; CHECK: @b = global
+; CHECK-NOT: !dbg
+ at b = global %struct.B zeroinitializer, align 8, !dbg !0
+
+declare void @_ZN1BC2Ev(%struct.B*) unnamed_addr
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+
+; Function Attrs: inlinehint nounwind ssp uwtable
+; CHECK: define
+define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr #1 align 2 !dbg !24 {
+entry:
+  %this.addr = alloca %struct.B*, align 8
+  store %struct.B* %this, %struct.B** %this.addr, align 8
+  ; CHECK-NOT: @llvm.dbg.declare
+  call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !29, metadata !31), !dbg !32
+  %this1 = load %struct.B*, %struct.B** %this.addr, align 8
+  ; CHECK: call void @_ZN1BC2Ev(%struct.B* %this1){{.*}} !dbg !
+  call void @_ZN1BC2Ev(%struct.B* %this1) #2, !dbg !33
+  ret void, !dbg !33
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { inlinehint nounwind ssp uwtable }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!20, !21, !22}
+!llvm.ident = !{!23}
+
+; CHECK-NEG-NOT: !DI{{Basic|Composite|Derived}}Type
+
+!0 = distinct !DIGlobalVariable(name: "b", scope: !1, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true)
+!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "t.cpp", directory: "/")
+!3 = !{}
+!4 = !{!0}
+!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !2, line: 4, size: 64, align: 64, elements: !6, vtableHolder: !8, identifier: "_ZTS1B")
+!6 = !{!7}
+!7 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !5, baseType: !8)
+!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !2, line: 1, size: 64, align: 64, elements: !9, vtableHolder: !8, identifier: "_ZTS1A")
+!9 = !{!10, !16}
+!10 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !2, file: !2, baseType: !11, size: 64, flags: DIFlagArtificial)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !13, size: 64)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!15}
+!15 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+; Only referenced by the type system.
+; CHECK-NEG-NOT: !DISubprogram(name: "~A"
+!16 = !DISubprogram(name: "~A", scope: !8, file: !2, line: 2, type: !17, isLocal: false, isDefinition: false, scopeLine: 2, containingType: !8, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, flags: DIFlagPrototyped, isOptimized: false)
+!17 = !DISubroutineType(types: !18)
+!18 = !{null, !19}
+!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!20 = !{i32 2, !"Dwarf Version", i32 4}
+!21 = !{i32 2, !"Debug Info Version", i32 3}
+!22 = !{i32 1, !"PIC Level", i32 2}
+!23 = !{!"clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)"}
+; CHECK: !DISubprogram(name: "B", scope: ![[FILE:.*]], file: ![[FILE]],
+; CHECK-NOT: containingType:
+!24 = distinct !DISubprogram(name: "B", linkageName: "_ZN1BC1Ev", scope: !5, file: !2, line: 4, type: !25, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !1, declaration: !28, variables: !3)
+!25 = !DISubroutineType(types: !26)
+!26 = !{null, !27}
+!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+; CHECK-NEG-NOT: !DISubprogram(name: "B", {{.*}}, isDefinition: false
+!28 = !DISubprogram(name: "B", scope: !5, type: !25, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!29 = !DILocalVariable(name: "this", arg: 1, scope: !24, type: !30, flags: DIFlagArtificial | DIFlagObjectPointer)
+!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64)
+!31 = !DIExpression()
+!32 = !DILocation(line: 0, scope: !24)
+!33 = !DILocation(line: 4, column: 8, scope: !24)

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll?rev=285094&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll Tue Oct 25 13:44:13 2016
@@ -0,0 +1,24 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+!llvm.dbg.cu = !{!2, !6}
+!llvm.gcov = !{!3}
+!llvm.module.flags = !{!7}
+
+!1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
+; The first CU is used for the line table, the second one is a module skeleton
+; and should be stripped.
+; CHECK: !llvm.dbg.cu = !{![[CU:[0-9]+]]}
+; CHECK: ![[CU]] = distinct !DICompileUnit({{.*}}"abc.debug"{{.*}}LineTablesOnly
+; CHECK-NOT: retainedTypes:
+; CHECK-SAME: )
+; CHECK-NOT: DICompositeType
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
+                             isOptimized: true, flags: "-O2", runtimeVersion: 2,
+                             splitDebugFilename: "abc.debug", emissionKind: FullDebug,
+                             retainedTypes: !4)
+!3 = !{!"path/to/file.o", !2}
+!4 = !{!5}
+!5 = !DICompositeType(tag: DW_TAG_structure_type, file: !1, identifier: "ThisWillBeStripped")
+!6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
+                             splitDebugFilename: "abc.dwo", emissionKind: FullDebug,
+                             dwoId: 1234)
+!7 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll?rev=285094&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll Tue Oct 25 13:44:13 2016
@@ -0,0 +1,36 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+; CHECK: define void @f() !dbg ![[F:[0-9]+]]
+define void @f() !dbg !4 {
+entry:
+  %i = alloca i32, align 4
+  ; CHECK-NOT: llvm.dbg.declare
+  call void @llvm.dbg.declare(metadata i32* %i, metadata !11, metadata !13), !dbg !14
+  store i32 42, i32* %i, align 4, !dbg !14
+  ret void, !dbg !15
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2)
+!1 = !DIFile(filename: "f.c", directory: "/")
+!2 = !{}
+; CHECK: ![[F]] = distinct !DISubprogram(name: "f"
+; CHECK-NOT: variables:
+; CHECK-NOT: distinct !DISubprogram(name: "f"
+!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = !{i32 2, !"Dwarf Version", i32 2}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"PIC Level", i32 2}
+!10 = !{!"LLVM"}
+!11 = !DILocalVariable(name: "i", scope: !4, file: !1, line: 1, type: !12)
+!12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!13 = !DIExpression()
+!14 = !DILocation(line: 1, column: 16, scope: !4)
+!15 = !DILocation(line: 1, column: 24, scope: !4)

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll?rev=285094&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll Tue Oct 25 13:44:13 2016
@@ -0,0 +1,22 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+; Test that subroutine types are downgraded to (void)().
+define internal i32 @"__hidden#2878_"() #0 !dbg !12 {
+  ret i32 0, !dbg !634
+}
+!llvm.dbg.cu = !{!18}
+!llvm.module.flags = !{!482}
+!5 = !{}
+!2 = !{!12}
+; CHECK-NOT: DICompositeType
+; CHECK: distinct !DISubprogram(name: "f", {{.*}}, type: ![[FNTY:[0-9]+]]
+; CHECK: ![[FNTY]] = !DISubroutineType(types: ![[VOID:[0-9]+]])
+; CHECK: ![[VOID]] = !{}
+; CHECK-NOT: DICompositeType
+!12 = distinct !DISubprogram(name: "f", scope: !16, file: !16, line: 133, type: !13, isLocal: true, isDefinition: true, scopeLine: 133, flags: DIFlagPrototyped, isOptimized: true, unit: !18, variables: !5)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!17}
+!16 = !DIFile(filename: "f.m", directory: "/")
+!17 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e", scope: !18, file: !16, line: 13, size: 32, align: 32, flags: DIFlagFwdDecl)
+!18 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !16, producer: "clang", isOptimized: true, runtimeVersion: 2, emissionKind: 1, enums: !14, retainedTypes: !14, globals: !5, imports: !5)
+!482 = !{i32 2, !"Debug Info Version", i32 3}
+!634 = !DILocation(line: 143, column: 5, scope: !12)

Modified: llvm/trunk/tools/bugpoint/CrashDebugger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/bugpoint/CrashDebugger.cpp?rev=285094&r1=285093&r2=285094&view=diff
==============================================================================
--- llvm/trunk/tools/bugpoint/CrashDebugger.cpp (original)
+++ llvm/trunk/tools/bugpoint/CrashDebugger.cpp Tue Oct 25 13:44:13 2016
@@ -19,6 +19,7 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -54,6 +55,12 @@ cl::opt<bool> DontReducePassList("disabl
 cl::opt<bool> NoNamedMDRM("disable-namedmd-remove",
                           cl::desc("Do not remove global named metadata"),
                           cl::init(false));
+cl::opt<bool> NoStripDebugInfo("disable-strip-debuginfo",
+                               cl::desc("Do not strip debug info metadata"),
+                               cl::init(false));
+cl::opt<bool> NoStripDebugTypeInfo("disable-strip-debug-types",
+                               cl::desc("Do not strip debug type info metadata"),
+                               cl::init(false));
 cl::opt<bool> VerboseErrors("verbose-errors",
                             cl::desc("Print the output of crashing program"),
                             cl::init(false));
@@ -1123,6 +1130,22 @@ static Error DebugACrash(BugDriver &BD,
     if (Error E = ReduceInsts(BD, TestFn))
       return E;
 
+  // Attempt to strip debug info metadata.
+  auto stripMetadata = [&](std::function<bool(Module &)> strip) {
+    std::unique_ptr<Module> M = CloneModule(BD.getProgram());
+    strip(*M);
+    if (TestFn(BD, M.get()))
+      BD.setNewProgram(M.release());
+  };
+  if (!NoStripDebugInfo && !BugpointIsInterrupted) {
+    outs() << "\n*** Attempting to strip the debug info: ";
+    stripMetadata(StripDebugInfo);
+  }
+  if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {
+    outs() << "\n*** Attempting to strip the debug type info: ";
+    stripMetadata(stripNonLineTableDebugInfo);
+  }
+
   if (!NoNamedMDRM) {
     if (!BugpointIsInterrupted) {
       // Try to reduce the amount of global metadata (particularly debug info),




More information about the llvm-commits mailing list