Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/PrintPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ std::vector<std::string> printAfterPasses();
// Returns true if we should always print the entire module.
bool forcePrintModuleIR();

// Returns true if we should print the entire function for loop passes.
bool forcePrintFuncIR();

// Return true if -filter-passes is empty or contains the pass name.
bool isPassInPrintList(StringRef PassName);
bool isFilterPassesEmpty();
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Analysis/LoopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,18 @@ void llvm::printLoop(Loop &L, raw_ostream &OS, const std::string &Banner) {
return;
}

if (forcePrintFuncIR()) {
// handling -print-loop-func-scope.
// -print-module-scope overrides this.
OS << Banner << " (loop: ";
L.getHeader()->printAsOperand(OS, false);
OS << ")\n";

// printing whole function.
OS << *L.getHeader()->getParent();
return;
}

OS << Banner;

auto *PreHeader = L.getLoopPreheader();
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/IR/PrintPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ static cl::opt<bool>
"always print a module IR"),
cl::init(false), cl::Hidden);

static cl::opt<bool> LoopPrintFuncScope(
"print-loop-func-scope",
cl::desc("When printing IR for print-[before|after]{-all} "
"for a loop pass, always print function IR"),
cl::init(false), cl::Hidden);

// See the description for -print-changed for an explanation of the use
// of this option.
static cl::list<std::string> FilterPasses(
Expand Down Expand Up @@ -141,6 +147,8 @@ std::vector<std::string> llvm::printAfterPasses() {

bool llvm::forcePrintModuleIR() { return PrintModuleScope; }

bool llvm::forcePrintFuncIR() { return LoopPrintFuncScope; }

bool llvm::isPassInPrintList(StringRef PassName) {
static std::unordered_set<std::string> Set(FilterPasses.begin(),
FilterPasses.end());
Expand Down
75 changes: 75 additions & 0 deletions llvm/test/Other/print-loop-func-scope.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
; This test documents how the IR dumped for loop passes differs with -print-loop-func-scope
; and -print-module-scope
; - Without -print-loop-func-scope, dumps only the loop, with 3 sections- preheader,
; loop, and exit blocks
; - With -print-loop-func-scope, dumps only the function which contains the loop
; - With -print-module-scope, dumps the entire module containing the loop, and disregards
; the -print-loop-func-scope flag.

; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=licm -print-after=licm \
; RUN: | FileCheck %s -check-prefix=VANILLA
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=licm -print-after=licm -print-loop-func-scope \
; RUN: | FileCheck %s -check-prefix=LOOPFUNC
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=licm -print-after=licm -print-module-scope \
; RUN: | FileCheck %s -check-prefix=MODULE
; RUN: opt < %s 2>&1 -disable-output \
; RUN: -passes=licm -print-after=licm -print-module-scope -print-loop-func-scope\
; RUN: | FileCheck %s -check-prefix=MODULEWITHLOOP

; VANILLA: IR Dump After LICMPass
; VANILLA-NOT: define void @foo
; VANILLA: Preheader:
; VANILLA: Loop:
; VANILLA: Exit blocks

; LOOPFUNC: IR Dump After LICMPass
; LOOPFUNC: (loop:
; LOOPFUNC: define void @foo
; LOOPFUNC-NOT: Preheader:
; LOOPFUNC-NOT: Loop:
; LOOPFUNC-NOT: Exit blocks

; MODULE: IR Dump After LICMPass
; MODULE: ModuleID =
; MODULE: define void @foo
; MODULE-NOT: Preheader:
; MODULE-NOT: Loop:
; MODULE-NOT: Exit blocks
; MODULE: define void @bar
; MODULE: declare void @baz(i32)

; MODULEWITHLOOP: IR Dump After LICMPass
; MODULEWITHLOOP: ModuleID =
; MODULEWITHLOOP: define void @foo
; MODULEWITHLOOP-NOT: Preheader:
; MODULEWITHLOOP-NOT: Loop:
; MODULEWITHLOOP-NOT: Exit blocks
; MODULEWITHLOOP: define void @bar
; MODULEWITHLOOP: declare void @baz(i32)

define void @foo(i32 %n) {
entry:
br label %loop_cond

loop_cond:
%i = phi i32 [ 0, %entry ], [ %i_next, %loop_body ]
%cmp = icmp slt i32 %i, %n
br i1 %cmp, label %loop_body, label %loop_end

loop_body:
call void @baz(i32 %i)
%i_next = add i32 %i, 1
br label %loop_cond

loop_end:
ret void
}

define void @bar() {
ret void
}

declare void @baz(i32)
Loading