diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -63,20 +63,26 @@ } }; + /// Check if \p ID corresponds to a debug info intrinsic. + static inline bool isDbgInfoIntrinsic(Intrinsic::ID ID) { + switch (ID) { + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + case Intrinsic::dbg_addr: + case Intrinsic::dbg_label: + return true; + default: + return false; + } + } + /// This is the common base class for debug info intrinsics. class DbgInfoIntrinsic : public IntrinsicInst { public: /// \name Casting methods /// @{ static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - case Intrinsic::dbg_addr: - case Intrinsic::dbg_label: - return true; - default: return false; - } + return isDbgInfoIntrinsic(I->getIntrinsicID()); } static bool classof(const Value *V) { return isa(V) && classof(cast(V)); diff --git a/llvm/include/llvm/Transforms/Utils/Debugify.h b/llvm/include/llvm/Transforms/Utils/Debugify.h --- a/llvm/include/llvm/Transforms/Utils/Debugify.h +++ b/llvm/include/llvm/Transforms/Utils/Debugify.h @@ -31,6 +31,12 @@ bool applyDebugifyMetadata( Module &M, iterator_range Functions, StringRef Banner, std::function ApplyToMF); + +/// Strip out all of the metadata and debug info inserted by debugify. If no +/// llvm.debugify module-level named metadata is present, this is a no-op. +/// Returns true if any change was made. +bool stripDebugifyMetadata(Module &M); + } // namespace llvm llvm::ModulePass *createDebugifyModulePass(); diff --git a/llvm/lib/Analysis/CallGraph.cpp b/llvm/lib/Analysis/CallGraph.cpp --- a/llvm/lib/Analysis/CallGraph.cpp +++ b/llvm/lib/Analysis/CallGraph.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" @@ -31,9 +32,10 @@ CallGraph::CallGraph(Module &M) : M(M), ExternalCallingNode(getOrInsertFunction(nullptr)), CallsExternalNode(std::make_unique(nullptr)) { - // Add every function to the call graph. + // Add every interesting function to the call graph. for (Function &F : M) - addToCallGraph(&F); + if (!isDbgInfoIntrinsic(F.getIntrinsicID())) + addToCallGraph(&F); } CallGraph::CallGraph(CallGraph &&Arg) diff --git a/llvm/lib/CodeGen/MachineStripDebug.cpp b/llvm/lib/CodeGen/MachineStripDebug.cpp --- a/llvm/lib/CodeGen/MachineStripDebug.cpp +++ b/llvm/lib/CodeGen/MachineStripDebug.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/Utils/Debugify.h" #define DEBUG_TYPE "mir-strip-debug" @@ -73,33 +74,7 @@ } } - Changed |= StripDebugInfo(M); - - NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); - if (NMD) { - NMD->eraseFromParent(); - Changed |= true; - } - - NMD = M.getModuleFlagsMetadata(); - if (NMD) { - // There must be an easier way to remove an operand from a NamedMDNode. - SmallVector Flags; - for (MDNode *Flag : NMD->operands()) - Flags.push_back(Flag); - NMD->clearOperands(); - for (MDNode *Flag : Flags) { - MDString *Key = dyn_cast_or_null(Flag->getOperand(1)); - if (Key->getString() == "Debug Info Version") { - Changed |= true; - continue; - } - NMD->addOperand(Flag); - } - // If we left it empty we might as well remove it. - if (NMD->getNumOperands() == 0) - NMD->eraseFromParent(); - } + Changed |= stripDebugifyMetadata(M); return Changed; } diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -176,6 +176,52 @@ return true; } +bool llvm::stripDebugifyMetadata(Module &M) { + bool Changed = false; + + // Remove the llvm.debugify module-level named metadata. + NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify"); + if (DebugifyMD) { + M.eraseNamedMetadata(DebugifyMD); + Changed = true; + } + + // Strip out all debug intrinsics and supporting metadata (subprograms, types, + // variables, etc). + Changed |= StripDebugInfo(M); + + // Strip out the dead dbg.value prototype. + Function *DbgValF = M.getFunction("llvm.dbg.value"); + if (DbgValF) { + assert(DbgValF->isDeclaration() && DbgValF->use_empty() && + "Not all debug info stripped?"); + DbgValF->eraseFromParent(); + Changed = true; + } + + // Strip out the module-level Debug Info Version metadata. + // FIXME: There must be an easier way to remove an operand from a NamedMDNode. + NamedMDNode *NMD = M.getModuleFlagsMetadata(); + assert(NMD && "debugify metadata present without Debug Info Version set?"); + SmallVector Flags; + for (MDNode *Flag : NMD->operands()) + Flags.push_back(Flag); + NMD->clearOperands(); + for (MDNode *Flag : Flags) { + MDString *Key = dyn_cast_or_null(Flag->getOperand(1)); + if (Key->getString() == "Debug Info Version") { + Changed = true; + continue; + } + NMD->addOperand(Flag); + } + // If we left it empty we might as well remove it. + if (NMD->getNumOperands() == 0) + NMD->eraseFromParent(); + + return Changed; +} + namespace { /// Return true if a mis-sized diagnostic is issued for \p DVI. bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) { @@ -305,12 +351,9 @@ dbg() << " [" << NameOfWrappedPass << "]"; dbg() << ": " << (HasErrors ? "FAIL" : "PASS") << '\n'; - // Strip the Debugify Metadata if required. - if (Strip) { - StripDebugInfo(M); - M.eraseNamedMetadata(NMD); - return true; - } + // Strip debugify metadata if required. + if (Strip) + return stripDebugifyMetadata(M); return false; } diff --git a/llvm/test/DebugInfo/debugify-each.ll b/llvm/test/DebugInfo/debugify-each.ll --- a/llvm/test/DebugInfo/debugify-each.ll +++ b/llvm/test/DebugInfo/debugify-each.ll @@ -18,19 +18,13 @@ ; Check that stripped textual IR compares equal before and after applying ; debugify. -; RUN: opt -O1 < %s -S -o - | \ -; RUN: opt -strip -strip-dead-prototypes -strip-named-metadata -S -o %t.before -; RUN: opt -O1 -debugify-each < %s -S -o - | \ -; RUN: opt -strip -strip-dead-prototypes -strip-named-metadata -S -o %t.after +; RUN: opt -O1 < %s -S -o %t.before +; RUN: opt -O1 -debugify-each < %s -S -o %t.after ; RUN: diff %t.before %t.after ; Check that stripped IR compares equal before and after applying debugify. -; RUN: opt -O1 < %s | \ -; RUN: opt -strip -strip-dead-prototypes -strip-named-metadata | \ -; RUN: llvm-dis -o %t.before -; RUN: opt -O1 -debugify-each < %s | \ -; RUN: opt -strip -strip-dead-prototypes -strip-named-metadata | \ -; RUN: llvm-dis -o %t.after +; RUN: opt -O1 < %s | llvm-dis -o %t.before +; RUN: opt -O1 -debugify-each < %s | llvm-dis -o %t.after ; RUN: diff %t.before %t.after define void @foo(i32 %arg) {