summaryrefslogtreecommitdiff
path: root/tools/opt
diff options
context:
space:
mode:
Diffstat (limited to 'tools/opt')
-rw-r--r--tools/opt/CMakeLists.txt3
-rw-r--r--tools/opt/Debugify.cpp212
-rw-r--r--tools/opt/NewPMDriver.cpp55
-rw-r--r--tools/opt/NewPMDriver.h8
-rw-r--r--tools/opt/PassPrinters.cpp9
-rw-r--r--tools/opt/PassPrinters.h8
-rw-r--r--tools/opt/opt.cpp43
7 files changed, 307 insertions, 31 deletions
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
index 518396e36028..dedc25143cf4 100644
--- a/tools/opt/CMakeLists.txt
+++ b/tools/opt/CMakeLists.txt
@@ -25,6 +25,7 @@ set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(opt
AnalysisWrappers.cpp
BreakpointPrinter.cpp
+ Debugify.cpp
GraphPrinters.cpp
NewPMDriver.cpp
PassPrinters.cpp
@@ -37,5 +38,5 @@ add_llvm_tool(opt
export_executable_symbols(opt)
if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
- target_link_libraries(opt Polly)
+ target_link_libraries(opt PRIVATE Polly)
endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
diff --git a/tools/opt/Debugify.cpp b/tools/opt/Debugify.cpp
new file mode 100644
index 000000000000..40ee545c098d
--- /dev/null
+++ b/tools/opt/Debugify.cpp
@@ -0,0 +1,212 @@
+//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This pass attaches synthetic debug info to everything. It can be used
+/// to create targeted tests for debug info preservation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO.h"
+
+using namespace llvm;
+
+namespace {
+
+bool applyDebugifyMetadata(Module &M) {
+ // Skip modules with debug info.
+ if (M.getNamedMetadata("llvm.dbg.cu")) {
+ errs() << "Debugify: Skipping module with debug info\n";
+ return false;
+ }
+
+ DIBuilder DIB(M);
+ LLVMContext &Ctx = M.getContext();
+
+ // Get a DIType which corresponds to Ty.
+ DenseMap<uint64_t, DIType *> TypeCache;
+ auto getCachedDIType = [&](Type *Ty) -> DIType * {
+ uint64_t Size = M.getDataLayout().getTypeAllocSizeInBits(Ty);
+ DIType *&DTy = TypeCache[Size];
+ if (!DTy) {
+ std::string Name = "ty" + utostr(Size);
+ DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned);
+ }
+ return DTy;
+ };
+
+ unsigned NextLine = 1;
+ unsigned NextVar = 1;
+ auto File = DIB.createFile(M.getName(), "/");
+ auto CU =
+ DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"),
+ "debugify", /*isOptimized=*/true, "", 0);
+
+ // Visit each instruction.
+ for (Function &F : M) {
+ if (F.isDeclaration())
+ continue;
+
+ auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
+ bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage();
+ auto SP =
+ DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType,
+ IsLocalToUnit, F.hasExactDefinition(), NextLine,
+ DINode::FlagZero, /*isOptimized=*/true);
+ F.setSubprogram(SP);
+ for (BasicBlock &BB : F) {
+ // Attach debug locations.
+ for (Instruction &I : BB)
+ I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP));
+
+ // Attach debug values.
+ for (Instruction &I : BB) {
+ // Skip void-valued instructions.
+ if (I.getType()->isVoidTy())
+ continue;
+
+ // Skip the terminator instruction and any just-inserted intrinsics.
+ if (isa<TerminatorInst>(&I) || isa<DbgValueInst>(&I))
+ break;
+
+ std::string Name = utostr(NextVar++);
+ const DILocation *Loc = I.getDebugLoc().get();
+ auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(),
+ getCachedDIType(I.getType()),
+ /*AlwaysPreserve=*/true);
+ DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc,
+ BB.getTerminator());
+ }
+ }
+ DIB.finalizeSubprogram(SP);
+ }
+ DIB.finalize();
+
+ // Track the number of distinct lines and variables.
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify");
+ auto *IntTy = Type::getInt32Ty(Ctx);
+ auto addDebugifyOperand = [&](unsigned N) {
+ NMD->addOperand(MDNode::get(
+ Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N))));
+ };
+ addDebugifyOperand(NextLine - 1); // Original number of lines.
+ addDebugifyOperand(NextVar - 1); // Original number of variables.
+ return true;
+}
+
+void checkDebugifyMetadata(Module &M) {
+ // Skip modules without debugify metadata.
+ NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
+ if (!NMD)
+ return;
+
+ auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
+ return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
+ ->getZExtValue();
+ };
+ unsigned OriginalNumLines = getDebugifyOperand(0);
+ unsigned OriginalNumVars = getDebugifyOperand(1);
+ bool HasErrors = false;
+
+ // Find missing lines.
+ BitVector MissingLines{OriginalNumLines, true};
+ for (Function &F : M) {
+ for (Instruction &I : instructions(F)) {
+ if (isa<DbgValueInst>(&I))
+ continue;
+
+ auto DL = I.getDebugLoc();
+ if (DL) {
+ MissingLines.reset(DL.getLine() - 1);
+ continue;
+ }
+
+ outs() << "ERROR: Instruction with empty DebugLoc -- ";
+ I.print(outs());
+ outs() << "\n";
+ HasErrors = true;
+ }
+ }
+ for (unsigned Idx : MissingLines.set_bits())
+ outs() << "WARNING: Missing line " << Idx + 1 << "\n";
+
+ // Find missing variables.
+ BitVector MissingVars{OriginalNumVars, true};
+ for (Function &F : M) {
+ for (Instruction &I : instructions(F)) {
+ auto *DVI = dyn_cast<DbgValueInst>(&I);
+ if (!DVI)
+ continue;
+
+ unsigned Var = ~0U;
+ (void)to_integer(DVI->getVariable()->getName(), Var, 10);
+ assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable");
+ MissingVars.reset(Var - 1);
+ }
+ }
+ for (unsigned Idx : MissingVars.set_bits())
+ outs() << "ERROR: Missing variable " << Idx + 1 << "\n";
+ HasErrors |= MissingVars.count() > 0;
+
+ outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n";
+}
+
+/// Attach synthetic debug info to everything.
+struct DebugifyPass : public ModulePass {
+ bool runOnModule(Module &M) override { return applyDebugifyMetadata(M); }
+
+ DebugifyPass() : ModulePass(ID) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ static char ID; // Pass identification.
+};
+
+/// Check debug info inserted by -debugify for completeness.
+struct CheckDebugifyPass : public ModulePass {
+ bool runOnModule(Module &M) override {
+ checkDebugifyMetadata(M);
+ return false;
+ }
+
+ CheckDebugifyPass() : ModulePass(ID) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ static char ID; // Pass identification.
+};
+
+} // end anonymous namespace
+
+char DebugifyPass::ID = 0;
+static RegisterPass<DebugifyPass> X("debugify",
+ "Attach debug info to everything");
+
+char CheckDebugifyPass::ID = 0;
+static RegisterPass<CheckDebugifyPass> Y("check-debugify",
+ "Check debug info from -debugify");
diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp
index 94242d795aae..a3f16f2538c4 100644
--- a/tools/opt/NewPMDriver.cpp
+++ b/tools/opt/NewPMDriver.cpp
@@ -18,6 +18,7 @@
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Config/config.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
@@ -81,6 +82,22 @@ static cl::opt<std::string> VectorizerStartEPPipeline(
cl::desc("A textual description of the function pass pipeline inserted at "
"the VectorizerStart extension point into default pipelines"),
cl::Hidden);
+enum PGOKind { NoPGO, InstrGen, InstrUse, SampleUse };
+static cl::opt<PGOKind> PGOKindFlag(
+ "pgo-kind", cl::init(NoPGO), cl::Hidden,
+ cl::desc("The kind of profile guided optimization"),
+ cl::values(clEnumValN(NoPGO, "nopgo", "Do not use PGO."),
+ clEnumValN(InstrGen, "new-pm-pgo-instr-gen-pipeline",
+ "Instrument the IR to generate profile."),
+ clEnumValN(InstrUse, "new-pm-pgo-instr-use-pipeline",
+ "Use instrumented profile to guide PGO."),
+ clEnumValN(SampleUse, "new-pm-pgo-sample-use-pipeline",
+ "Use sampled profile to guide PGO.")));
+static cl::opt<std::string> ProfileFile(
+ "profile-file", cl::desc("Path to the profile."), cl::Hidden);
+static cl::opt<bool> DebugInfoForProfiling(
+ "new-pm-debug-info-for-profiling", cl::init(false), cl::Hidden,
+ cl::desc("Emit special debug info to enable PGO profile generation."));
/// @}}
template <typename PassManagerT>
@@ -144,18 +161,46 @@ static void registerEPCallbacks(PassBuilder &PB, bool VerifyEachPass,
});
}
+#ifdef LINK_POLLY_INTO_TOOLS
+namespace polly {
+void RegisterPollyPasses(PassBuilder &);
+}
+#endif
+
bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
- tool_output_file *Out,
- tool_output_file *ThinLTOLinkOut,
+ ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut,
+ ToolOutputFile *OptRemarkFile,
StringRef PassPipeline, OutputKind OK,
VerifierKind VK,
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder,
bool EmitSummaryIndex, bool EmitModuleHash) {
bool VerifyEachPass = VK == VK_VerifyEachPass;
- PassBuilder PB(TM);
+
+ Optional<PGOOptions> P;
+ switch (PGOKindFlag) {
+ case InstrGen:
+ P = PGOOptions(ProfileFile, "", "", true);
+ break;
+ case InstrUse:
+ P = PGOOptions("", ProfileFile, "", false);
+ break;
+ case SampleUse:
+ P = PGOOptions("", "", ProfileFile, false);
+ break;
+ case NoPGO:
+ if (DebugInfoForProfiling)
+ P = PGOOptions("", "", "", false, true);
+ else
+ P = None;
+ }
+ PassBuilder PB(TM, P);
registerEPCallbacks(PB, VerifyEachPass, DebugPM);
+#ifdef LINK_POLLY_INTO_TOOLS
+ polly::RegisterPollyPasses(PB);
+#endif
+
// Specially handle the alias analysis manager so that we can register
// a custom pipeline of AA passes with it.
AAManager AA;
@@ -221,5 +266,9 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut)
ThinLTOLinkOut->keep();
}
+
+ if (OptRemarkFile)
+ OptRemarkFile->keep();
+
return true;
}
diff --git a/tools/opt/NewPMDriver.h b/tools/opt/NewPMDriver.h
index 8012e0a025c9..e5490deaeaf5 100644
--- a/tools/opt/NewPMDriver.h
+++ b/tools/opt/NewPMDriver.h
@@ -26,7 +26,7 @@ class StringRef;
class LLVMContext;
class Module;
class TargetMachine;
-class tool_output_file;
+class ToolOutputFile;
namespace opt_tool {
enum OutputKind {
@@ -52,9 +52,9 @@ enum VerifierKind {
/// ThinLTOLinkOut is only used when OK is OK_OutputThinLTOBitcode, and can be
/// nullptr.
bool runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
- tool_output_file *Out, tool_output_file *ThinLinkOut,
- StringRef PassPipeline, opt_tool::OutputKind OK,
- opt_tool::VerifierKind VK,
+ ToolOutputFile *Out, ToolOutputFile *ThinLinkOut,
+ ToolOutputFile *OptRemarkFile, StringRef PassPipeline,
+ opt_tool::OutputKind OK, opt_tool::VerifierKind VK,
bool ShouldPreserveAssemblyUseListOrder,
bool ShouldPreserveBitcodeUseListOrder,
bool EmitSummaryIndex, bool EmitModuleHash);
diff --git a/tools/opt/PassPrinters.cpp b/tools/opt/PassPrinters.cpp
index 65a53038fc50..f52b52080949 100644
--- a/tools/opt/PassPrinters.cpp
+++ b/tools/opt/PassPrinters.cpp
@@ -11,12 +11,18 @@
/// \brief Utilities to print analysis info for various kinds of passes.
///
//===----------------------------------------------------------------------===//
+
#include "PassPrinters.h"
+#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionPass.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
#include <string>
using namespace llvm;
@@ -226,7 +232,8 @@ struct BasicBlockPassPrinter : public BasicBlockPass {
};
char BasicBlockPassPrinter::ID = 0;
-}
+
+} // end anonymous namespace
FunctionPass *llvm::createFunctionPassPrinter(const PassInfo *PI,
raw_ostream &OS, bool Quiet) {
diff --git a/tools/opt/PassPrinters.h b/tools/opt/PassPrinters.h
index cf46ef9e36d2..14b6e43d18e0 100644
--- a/tools/opt/PassPrinters.h
+++ b/tools/opt/PassPrinters.h
@@ -1,4 +1,4 @@
-//===- PassPrinters.h - Utilities to print analysis info for passes -------===//
+//=- PassPrinters.h - Utilities to print analysis info for passes -*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@@ -11,6 +11,7 @@
/// \brief Utilities to print analysis info for various kinds of passes.
///
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_TOOLS_OPT_PASSPRINTERS_H
#define LLVM_TOOLS_OPT_PASSPRINTERS_H
@@ -22,8 +23,8 @@ class FunctionPass;
class ModulePass;
class LoopPass;
class PassInfo;
-class RegionPass;
class raw_ostream;
+class RegionPass;
FunctionPass *createFunctionPassPrinter(const PassInfo *PI, raw_ostream &out,
bool Quiet);
@@ -42,6 +43,7 @@ RegionPass *createRegionPassPrinter(const PassInfo *PI, raw_ostream &out,
BasicBlockPass *createBasicBlockPassPrinter(const PassInfo *PI,
raw_ostream &out, bool Quiet);
-}
+
+} // end namespace llvm
#endif // LLVM_TOOLS_OPT_PASSPRINTERS_H
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 24cce58047f1..5bc00ea35ae5 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -23,7 +23,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/CommandFlags.def"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
@@ -349,7 +349,7 @@ static TargetMachine* GetTargetMachine(Triple TheTriple, StringRef CPUStr,
return TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr,
FeaturesStr, Options, getRelocModel(),
- CMModel, GetCodeGenOptLevel());
+ getCodeModel(), GetCodeGenOptLevel());
}
#ifdef LINK_POLLY_INTO_TOOLS
@@ -391,6 +391,7 @@ int main(int argc, char **argv) {
initializeTarget(Registry);
// For codegen passes, only passes that do IR to IR transformation are
// supported.
+ initializeExpandMemCmpPassPass(Registry);
initializeScalarizeMaskedMemIntrinPass(Registry);
initializeCodeGenPreparePass(Registry);
initializeAtomicExpandPass(Registry);
@@ -402,9 +403,11 @@ int main(int argc, char **argv) {
initializePreISelIntrinsicLoweringLegacyPassPass(Registry);
initializeGlobalMergePass(Registry);
initializeInterleavedAccessPass(Registry);
- initializeCountingFunctionInserterPass(Registry);
+ initializeEntryExitInstrumenterPass(Registry);
+ initializePostInlineEntryExitInstrumenterPass(Registry);
initializeUnreachableBlockElimLegacyPassPass(Registry);
initializeExpandReductionsPass(Registry);
+ initializeWriteBitcodePassPass(Registry);
#ifdef LINK_POLLY_INTO_TOOLS
polly::initializePollyPasses(Registry);
@@ -430,21 +433,22 @@ int main(int argc, char **argv) {
if (PassRemarksHotnessThreshold)
Context.setDiagnosticsHotnessThreshold(PassRemarksHotnessThreshold);
- std::unique_ptr<tool_output_file> YamlFile;
+ std::unique_ptr<ToolOutputFile> OptRemarkFile;
if (RemarksFilename != "") {
std::error_code EC;
- YamlFile = llvm::make_unique<tool_output_file>(RemarksFilename, EC,
- sys::fs::F_None);
+ OptRemarkFile =
+ llvm::make_unique<ToolOutputFile>(RemarksFilename, EC, sys::fs::F_None);
if (EC) {
errs() << EC.message() << '\n';
return 1;
}
Context.setDiagnosticsOutputFile(
- llvm::make_unique<yaml::Output>(YamlFile->os()));
+ llvm::make_unique<yaml::Output>(OptRemarkFile->os()));
}
// Load the input module...
- std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
+ std::unique_ptr<Module> M =
+ parseIRFile(InputFilename, Err, Context, !NoVerify);
if (!M) {
Err.print(argv[0], errs());
@@ -471,8 +475,8 @@ int main(int argc, char **argv) {
M->setDataLayout(ClDataLayout);
// Figure out what stream we are supposed to write to...
- std::unique_ptr<tool_output_file> Out;
- std::unique_ptr<tool_output_file> ThinLinkOut;
+ std::unique_ptr<ToolOutputFile> Out;
+ std::unique_ptr<ToolOutputFile> ThinLinkOut;
if (NoOutput) {
if (!OutputFilename.empty())
errs() << "WARNING: The -o (output filename) option is ignored when\n"
@@ -483,7 +487,7 @@ int main(int argc, char **argv) {
OutputFilename = "-";
std::error_code EC;
- Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None));
+ Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::F_None));
if (EC) {
errs() << EC.message() << '\n';
return 1;
@@ -491,7 +495,7 @@ int main(int argc, char **argv) {
if (!ThinLinkBitcodeFile.empty()) {
ThinLinkOut.reset(
- new tool_output_file(ThinLinkBitcodeFile, EC, sys::fs::F_None));
+ new ToolOutputFile(ThinLinkBitcodeFile, EC, sys::fs::F_None));
if (EC) {
errs() << EC.message() << '\n';
return 1;
@@ -540,7 +544,8 @@ int main(int argc, char **argv) {
// string. Hand off the rest of the functionality to the new code for that
// layer.
return runPassPipeline(argv[0], *M, TM.get(), Out.get(), ThinLinkOut.get(),
- PassPipeline, OK, VK, PreserveAssemblyUseListOrder,
+ OptRemarkFile.get(), PassPipeline, OK, VK,
+ PreserveAssemblyUseListOrder,
PreserveBitcodeUseListOrder, EmitSummaryIndex,
EmitModuleHash)
? 0
@@ -579,8 +584,8 @@ int main(int argc, char **argv) {
OutputFilename = "-";
std::error_code EC;
- Out = llvm::make_unique<tool_output_file>(OutputFilename, EC,
- sys::fs::F_None);
+ Out = llvm::make_unique<ToolOutputFile>(OutputFilename, EC,
+ sys::fs::F_None);
if (EC) {
errs() << EC.message() << '\n';
return 1;
@@ -767,8 +772,8 @@ int main(int argc, char **argv) {
"the compile-twice option\n";
Out->os() << BOS->str();
Out->keep();
- if (YamlFile)
- YamlFile->keep();
+ if (OptRemarkFile)
+ OptRemarkFile->keep();
return 1;
}
Out->os() << BOS->str();
@@ -778,8 +783,8 @@ int main(int argc, char **argv) {
if (!NoOutput || PrintBreakpoints)
Out->keep();
- if (YamlFile)
- YamlFile->keep();
+ if (OptRemarkFile)
+ OptRemarkFile->keep();
if (ThinLinkOut)
ThinLinkOut->keep();