diff options
| -rw-r--r-- | llvm/include/llvm/IR/IRPrintingPasses.h | 16 | ||||
| -rw-r--r-- | llvm/include/llvm/Pass.h | 11 | ||||
| -rw-r--r-- | llvm/include/llvm/Passes/StandardInstrumentations.h | 34 | ||||
| -rw-r--r-- | llvm/lib/Analysis/CallGraphSCCPass.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/Analysis/LoopInfo.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/IR/LegacyPassManager.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/Passes/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/Passes/StandardInstrumentations.cpp | 115 | ||||
| -rw-r--r-- | llvm/test/Other/loop-pass-printer.ll | 27 | ||||
| -rw-r--r-- | llvm/test/Other/print-module-scope.ll | 12 | ||||
| -rw-r--r-- | llvm/test/Other/printer.ll | 23 | ||||
| -rw-r--r-- | llvm/tools/opt/NewPMDriver.cpp | 9 | 
13 files changed, 236 insertions, 43 deletions
diff --git a/llvm/include/llvm/IR/IRPrintingPasses.h b/llvm/include/llvm/IR/IRPrintingPasses.h index e4ac5d4d88a..75f80567dbd 100644 --- a/llvm/include/llvm/IR/IRPrintingPasses.h +++ b/llvm/include/llvm/IR/IRPrintingPasses.h @@ -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 diff --git a/llvm/include/llvm/Pass.h b/llvm/include/llvm/Pass.h index d65347d611e..5935a0853d3 100644 --- a/llvm/include/llvm/Pass.h +++ b/llvm/include/llvm/Pass.h @@ -356,17 +356,6 @@ protected:  /// 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, diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h new file mode 100644 index 00000000000..3770d1ac309 --- /dev/null +++ b/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 diff --git a/llvm/lib/Analysis/CallGraphSCCPass.cpp b/llvm/lib/Analysis/CallGraphSCCPass.cpp index 3e9226f91de..80d0427529a 100644 --- a/llvm/lib/Analysis/CallGraphSCCPass.cpp +++ b/llvm/lib/Analysis/CallGraphSCCPass.cpp @@ -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" diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 07f72addc81..99ff25a3fd3 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -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" diff --git a/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp b/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp index 55d9defced3..9c3288e02db 100644 --- a/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp +++ b/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp @@ -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" diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp index 3b0c49a4cab..01d14f17bba 100644 --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -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; } @@ -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()); @@ -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()); diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt index 468fd070a91..d1b873c3fd7 100644 --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -5,6 +5,7 @@ endif()  add_llvm_library(LLVMPasses    PassBuilder.cpp    PassPlugin.cpp +  StandardInstrumentations.cpp    ADDITIONAL_HEADER_DIRS    ${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp new file mode 100644 index 00000000000..6abd39c61ac --- /dev/null +++ b/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); +} diff --git a/llvm/test/Other/loop-pass-printer.ll b/llvm/test/Other/loop-pass-printer.ll index bedcf164ace..ba752264586 100644 --- a/llvm/test/Other/loop-pass-printer.ll +++ b/llvm/test/Other/loop-pass-printer.ll @@ -5,14 +5,22 @@  ; 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: @@ -20,8 +28,7 @@  ; 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: @@ -29,24 +36,22 @@  ; 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 diff --git a/llvm/test/Other/print-module-scope.ll b/llvm/test/Other/print-module-scope.ll index 0e9c4d59cc3..a6f744657b6 100644 --- a/llvm/test/Other/print-module-scope.ll +++ b/llvm/test/Other/print-module-scope.ll @@ -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 @@ -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 = @@ -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}} diff --git a/llvm/test/Other/printer.ll b/llvm/test/Other/printer.ll index ac1abd70495..9785a17b228 100644 --- a/llvm/test/Other/printer.ll +++ b/llvm/test/Other/printer.ll @@ -1,4 +1,5 @@ -; 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  } @@ -7,7 +8,21 @@ define void @foo(){    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 diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index a91d4cb5f9c..55ca23cd6f3 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -13,8 +13,8 @@  ///  //===----------------------------------------------------------------------===// -#include "Debugify.h"  #include "NewPMDriver.h" +#include "Debugify.h"  #include "PassPrinters.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/Analysis/AliasAnalysis.h" @@ -29,6 +29,7 @@  #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" @@ -213,7 +214,11 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,        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  | 

