/// 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
/// 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,
--- /dev/null
+//===- 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
#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"
#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"
#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"
/// 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; }
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());
// 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());
add_llvm_library(LLVMPasses
PassBuilder.cpp
PassPlugin.cpp
+ StandardInstrumentations.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes
--- /dev/null
+//===- 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);
+}
; 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: 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: ; 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
; 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
; 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 =
; FOO: attributes #{{[0-9]}} = { nounwind readnone ssp "use-soft-float"="false" }
-; FOO-NOT: IR Dump
+; FOO-NOT: IR Dump After {{Simplify the CFG|SimplifyCFGPass}}
-; RUN: opt -mem2reg -instcombine -print-after-all -S < %s 2>&1 | FileCheck %s
+; RUN: opt -mem2reg -instcombine -print-after-all -disable-output < %s 2>&1 | FileCheck %s
+; RUN: opt -passes='mem2reg,instcombine' -print-after-all -disable-output < %s 2>&1 | FileCheck %s
define void @tester(){
ret void
}
ret void
}
-;CHECK: IR Dump After Promote Memory to Register
-;CHECK: IR Dump After Combine redundant instructions
-;CHECK: IR Dump After Module Verifier
+;CHECK-NOT: IR Dump After PassManager
+;CHECK-NOT: IR Dump After ModuleToFunctionPassAdaptor
+;
+;CHECK: *** IR Dump After {{Promote Memory to Register|PromotePass}}
+;CHECK: define void @tester
+;CHECK-NOT: define void @foo
+;CHECK: *** IR Dump After {{Combine redundant instructions|InstCombinePass}}
+;CHECK: define void @tester
+;CHECK-NOT: define void @foo
+;CHECK: *** IR Dump After {{Promote Memory to Register|PromotePass}}
+;CHECK: define void @foo
+;CHECK-NOT: define void @tester
+;CHECK: *** IR Dump After {{Combine redundant instructions|InstCombinePass}}
+;CHECK: define void @foo
+;CHECK-NOT: define void @tester
+;CHECK: *** IR Dump After {{Module Verifier|VerifierPass}}
+;
;CHECK-NOT: IR Dump After Print Module IR
///
//===----------------------------------------------------------------------===//
-#include "Debugify.h"
#include "NewPMDriver.h"
+#include "Debugify.h"
#include "PassPrinters.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
else
P = None;
}
- PassBuilder PB(TM, P);
+ PassInstrumentationCallbacks PIC;
+ StandardInstrumentations SI;
+ SI.registerCallbacks(PIC);
+
+ PassBuilder PB(TM, P, &PIC);
registerEPCallbacks(PB, VerifyEachPass, DebugPM);
// Load requested pass plugins and let them register pass builder callbacks