Skip to content

Commit

Permalink
[New PM][PassInstrumentation] IR printing support for New Pass Manager
Browse files Browse the repository at this point in the history
Implementing -print-before-all/-print-after-all/-filter-print-func support
through PassInstrumentation callbacks.

- PrintIR routines implement printing callbacks.

- StandardInstrumentations class provides a central place to manage all
  the "standard" in-tree pass instrumentations. Currently it registers
  PrintIR callbacks.

Reviewers: chandlerc, paquette, philip.pfaffe
Differential Revision: https://reviews.llvm.org/D50923

llvm-svn: 342896
  • Loading branch information
Fedor Sergeev committed Sep 24, 2018
1 parent 8284b19 commit 662e568
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 43 deletions.
16 changes: 16 additions & 0 deletions llvm/include/llvm/IR/IRPrintingPasses.h
Expand Up @@ -58,6 +58,22 @@ void printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name);
/// Return true if a pass is for IR printing.
bool isIRPrintingPass(Pass *P);

/// isFunctionInPrintList - returns true if a function should be printed via
// debugging options like -print-after-all/-print-before-all.
// Tells if the function IR should be printed by PrinterPass.
extern bool isFunctionInPrintList(StringRef FunctionName);

/// forcePrintModuleIR - returns true if IR printing passes should
// be printing module IR (even for local-pass printers e.g. function-pass)
// to provide more context, as enabled by debugging option -print-module-scope
// Tells if IR printer should be printing module IR
extern bool forcePrintModuleIR();

extern bool shouldPrintBeforePass();
extern bool shouldPrintBeforePass(StringRef);
extern bool shouldPrintAfterPass();
extern bool shouldPrintAfterPass(StringRef);

/// Pass for printing a Module as LLVM's text IR assembly.
///
/// Note: This pass is for use with the new pass manager. Use the create...Pass
Expand Down
11 changes: 0 additions & 11 deletions llvm/include/llvm/Pass.h
Expand Up @@ -356,17 +356,6 @@ class BasicBlockPass : public Pass {
/// This is the storage for the -time-passes option.
extern bool TimePassesIsEnabled;

/// isFunctionInPrintList - returns true if a function should be printed via
// debugging options like -print-after-all/-print-before-all.
// Tells if the function IR should be printed by PrinterPass.
extern bool isFunctionInPrintList(StringRef FunctionName);

/// forcePrintModuleIR - returns true if IR printing passes should
// be printing module IR (even for local-pass printers e.g. function-pass)
// to provide more context, as enabled by debugging option -print-module-scope
// Tells if IR printer should be printing module IR
extern bool forcePrintModuleIR();

} // end namespace llvm

// Include support files that contain important APIs commonly used by Passes,
Expand Down
34 changes: 34 additions & 0 deletions llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -0,0 +1,34 @@
//===- StandardInstrumentations.h ------------------------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This header defines a class that provides bookkeeping for all standard
/// (i.e in-tree) pass instrumentations.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
#define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H

#include "llvm/IR/PassInstrumentation.h"

namespace llvm {

/// This class provides an interface to register all the standard pass
/// instrumentations and manages their state (if any).
class StandardInstrumentations {
// for now we do not have instrumentations with state
public:
StandardInstrumentations() = default;

void registerCallbacks(PassInstrumentationCallbacks &PIC);
};
} // namespace llvm

#endif
1 change: 1 addition & 0 deletions llvm/lib/Analysis/CallGraphSCCPass.cpp
Expand Up @@ -22,6 +22,7 @@
#include "llvm/Analysis/CallGraph.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManagers.h"
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/LoopInfo.cpp
Expand Up @@ -26,6 +26,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp
Expand Up @@ -15,6 +15,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

Expand Down
28 changes: 16 additions & 12 deletions llvm/lib/IR/LegacyPassManager.cpp
Expand Up @@ -100,27 +100,31 @@ static cl::list<std::string>
/// This is a helper to determine whether to print IR before or
/// after a pass.

static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI,
bool llvm::shouldPrintBeforePass() {
return PrintBeforeAll || !PrintBefore.empty();
}

bool llvm::shouldPrintAfterPass() {
return PrintAfterAll || !PrintAfter.empty();
}

static bool ShouldPrintBeforeOrAfterPass(StringRef PassID,
PassOptionList &PassesToPrint) {
for (auto *PassInf : PassesToPrint) {
if (PassInf)
if (PassInf->getPassArgument() == PI->getPassArgument()) {
if (PassInf->getPassArgument() == PassID) {
return true;
}
}
return false;
}

/// This is a utility to check whether a pass should have IR dumped
/// before it.
static bool ShouldPrintBeforePass(const PassInfo *PI) {
return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore);
bool llvm::shouldPrintBeforePass(StringRef PassID) {
return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PassID, PrintBefore);
}

/// This is a utility to check whether a pass should have IR dumped
/// after it.
static bool ShouldPrintAfterPass(const PassInfo *PI) {
return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
bool llvm::shouldPrintAfterPass(StringRef PassID) {
return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PassID, PrintAfter);
}

bool llvm::forcePrintModuleIR() { return PrintModuleScope; }
Expand Down Expand Up @@ -780,7 +784,7 @@ void PMTopLevelManager::schedulePass(Pass *P) {
return;
}

if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) {
if (PI && !PI->isAnalysis() && shouldPrintBeforePass(PI->getPassArgument())) {
Pass *PP = P->createPrinterPass(
dbgs(), ("*** IR Dump Before " + P->getPassName() + " ***").str());
PP->assignPassManager(activeStack, getTopLevelPassManagerType());
Expand All @@ -789,7 +793,7 @@ void PMTopLevelManager::schedulePass(Pass *P) {
// Add the requested pass to the best available pass manager.
P->assignPassManager(activeStack, getTopLevelPassManagerType());

if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) {
if (PI && !PI->isAnalysis() && shouldPrintAfterPass(PI->getPassArgument())) {
Pass *PP = P->createPrinterPass(
dbgs(), ("*** IR Dump After " + P->getPassName() + " ***").str());
PP->assignPassManager(activeStack, getTopLevelPassManagerType());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/CMakeLists.txt
Expand Up @@ -5,6 +5,7 @@ endif()
add_llvm_library(LLVMPasses
PassBuilder.cpp
PassPlugin.cpp
StandardInstrumentations.cpp

ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes
Expand Down
115 changes: 115 additions & 0 deletions llvm/lib/Passes/StandardInstrumentations.cpp
@@ -0,0 +1,115 @@
//===- 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) {
if (any_isa<const CallGraphSCC *>(IR) ||
any_isa<const LazyCallGraph::SCC *>(IR))
return;

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 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);
}
27 changes: 16 additions & 11 deletions llvm/test/Other/loop-pass-printer.ll
Expand Up @@ -5,48 +5,53 @@
; RUN: -loop-deletion -print-before=loop-deletion \
; RUN: | FileCheck %s -check-prefix=DEL
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes='loop(loop-deletion)' -print-before-all \
; RUN: | FileCheck %s -check-prefix=DEL
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -loop-unroll -print-after=loop-unroll -filter-print-funcs=bar \
; RUN: | FileCheck %s -check-prefix=BAR -check-prefix=BAR-OLD
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes='require<opt-remark-emit>,loop(unroll-full)' -print-after-all -filter-print-funcs=bar \
; RUN: | FileCheck %s -check-prefix=BAR
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -loop-unroll -print-after=loop-unroll -filter-print-funcs=foo -print-module-scope \
; RUN: | FileCheck %s -check-prefix=FOO-MODULE -check-prefix=FOO-MODULE-OLD
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes='require<opt-remark-emit>,loop(unroll-full)' -print-after-all -filter-print-funcs=foo -print-module-scope \
; RUN: | FileCheck %s -check-prefix=FOO-MODULE

; DEL: IR Dump Before
; DEL-SAME: dead loops
; DEL: IR Dump Before {{Delete dead loops|LoopDeletionPass}}
; DEL: ; Preheader:
; DEL-NEXT: %idx = alloca i32, align 4
; DEL: ; Loop:
; DEL-NEXT: loop:
; DEL: cont:
; DEL: ; Exit blocks
; DEL: done:
; DEL: IR Dump Before
; DEL-SAME: dead loops
; DEL: IR Dump Before {{Delete dead loops|LoopDeletionPass}}
; DEL: ; Preheader:
; DEL-NEXT: br label %loop
; DEL: ; Loop:
; DEL-NEXT: loop:
; DEL: ; Exit blocks
; DEL: end:

; BAR: IR Dump After
; BAR-SAME: Unroll
; BAR: IR Dump After {{Unroll|LoopFullUnrollPass}}
; BAR: ; Preheader:
; BAR-NEXT: br label %loop
; BAR: ; Loop:
; BAR-NEXT: loop:
; BAR: ; Exit blocks
; BAR: end:
; BAR-NOT: IR Dump
; BAR-NOT: ; Loop
; BAR-OLD-NOT: IR Dump
; BAR-OLD-NOT: ; Loop

; FOO-MODULE: IR Dump After
; FOO-MODULE-SAME: Unroll
; FOO-MODULE: IR Dump After {{Unroll|LoopFullUnrollPass}}
; FOO-MODULE-SAME: loop: %loop
; FOO-MODULE-NEXT: ModuleID =
; FOO-MODULE: define void @foo
; FOO-MODULE: define void @bar
; FOO-MODULE-NOT: IR Dump
; FOO-MODULE-OLD-NOT: IR Dump

define void @foo(){
%idx = alloca i32, align 4
Expand Down
12 changes: 9 additions & 3 deletions llvm/test/Other/print-module-scope.ll
Expand Up @@ -7,10 +7,16 @@
; RUN: -simplifycfg -print-after=simplifycfg -print-module-scope \
; RUN: | FileCheck %s -check-prefix=CFG
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=simplify-cfg -print-after-all -print-module-scope \
; RUN: | FileCheck %s -check-prefix=CFG
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -simplifycfg -print-after=simplifycfg -filter-print-funcs=foo -print-module-scope \
; RUN: | FileCheck %s -check-prefix=FOO
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=simplify-cfg -print-after-all -filter-print-funcs=foo -print-module-scope \
; RUN: | FileCheck %s -check-prefix=FOO

; CFG: IR Dump After
; CFG: IR Dump After {{Simplify the CFG|SimplifyCFGPass}}
; CFG-SAME: function: foo
; CFG-NEXT: ModuleID =
; CFG: define void @foo
Expand All @@ -23,7 +29,7 @@
; CFG: define void @bar
; CFG: declare void @baz

; FOO: IR Dump After
; FOO: IR Dump After {{Simplify the CFG|SimplifyCFGPass}}
; FOO-NOT: function: bar
; FOO-SAME: function: foo
; FOO-NEXT: ModuleID =
Expand Down Expand Up @@ -52,4 +58,4 @@ attributes #1 = { nounwind readnone ssp "use-soft-float"="false" }

; FOO: attributes #{{[0-9]}} = { nounwind readnone ssp "use-soft-float"="false" }

; FOO-NOT: IR Dump
; FOO-NOT: IR Dump After {{Simplify the CFG|SimplifyCFGPass}}

0 comments on commit 662e568

Please sign in to comment.