blob: 48d36e5a01e58ad9f9335dca6be6fb3bbe5875c8 [file] [log] [blame]
//===- Standard pass instrumentations handling ----------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file defines IR-printing pass instrumentation callbacks as well as
/// StandardInstrumentations class that manages standard pass instrumentations.
///
//===----------------------------------------------------------------------===//
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
namespace PrintIR {
//===----------------------------------------------------------------------===//
// IR-printing instrumentation
//===----------------------------------------------------------------------===//
/// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
/// llvm::Any and does actual print job.
void unwrapAndPrint(StringRef Banner, Any IR) {
SmallString<40> Extra{"\n"};
const Module *M = nullptr;
if (any_isa<const Module *>(IR)) {
M = any_cast<const Module *>(IR);
} else if (any_isa<const Function *>(IR)) {
const Function *F = any_cast<const Function *>(IR);
if (!llvm::isFunctionInPrintList(F->getName()))
return;
if (!llvm::forcePrintModuleIR()) {
dbgs() << Banner << Extra << static_cast<const Value &>(*F);
return;
}
M = F->getParent();
Extra = formatv(" (function: {0})\n", F->getName());
} else if (any_isa<const LazyCallGraph::SCC *>(IR)) {
const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR);
assert(C);
if (!llvm::forcePrintModuleIR()) {
Extra = formatv(" (scc: {0})\n", C->getName());
bool BannerPrinted = false;
for (const LazyCallGraph::Node &N : *C) {
const Function &F = N.getFunction();
if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
if (!BannerPrinted) {
dbgs() << Banner << Extra;
BannerPrinted = true;
}
F.print(dbgs());
}
}
return;
}
for (const LazyCallGraph::Node &N : *C) {
const Function &F = N.getFunction();
if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
M = F.getParent();
break;
}
}
if (!M)
return;
Extra = formatv(" (for scc: {0})\n", C->getName());
} else if (any_isa<const Loop *>(IR)) {
const Loop *L = any_cast<const Loop *>(IR);
const Function *F = L->getHeader()->getParent();
if (!isFunctionInPrintList(F->getName()))
return;
if (!llvm::forcePrintModuleIR()) {
llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner);
return;
}
M = F->getParent();
{
std::string LoopName;
raw_string_ostream ss(LoopName);
L->getHeader()->printAsOperand(ss, false);
Extra = formatv(" (loop: {0})\n", ss.str());
}
}
if (M) {
dbgs() << Banner << Extra;
M->print(dbgs(), nullptr, false);
} else {
llvm_unreachable("Unknown wrapped IR type");
}
}
bool printBeforePass(StringRef PassID, Any IR) {
if (!llvm::shouldPrintBeforePass(PassID))
return true;
if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
return true;
SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
unwrapAndPrint(Banner, IR);
return true;
}
void printAfterPass(StringRef PassID, Any IR) {
if (!llvm::shouldPrintAfterPass(PassID))
return;
if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
return;
SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
unwrapAndPrint(Banner, IR);
return;
}
} // namespace PrintIR
} // namespace
void StandardInstrumentations::registerCallbacks(
PassInstrumentationCallbacks &PIC) {
if (llvm::shouldPrintBeforePass())
PIC.registerBeforePassCallback(PrintIR::printBeforePass);
if (llvm::shouldPrintAfterPass())
PIC.registerAfterPassCallback(PrintIR::printAfterPass);
TimePasses.registerCallbacks(PIC);
}