Use `-cfg-func-name` value as filter for `-view-cfg`, etc.

Currently the value is only used when calling `F->viewCFG()` which is missing out on its potential and usefulness.
So I added the check to the printer passes as well.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D102011
This commit is contained in:
Joachim Meyer 2021-05-06 20:18:11 +02:00
parent f9aba9a5af
commit 053dbb939d
3 changed files with 72 additions and 4 deletions

View File

@ -127,6 +127,9 @@ postscript or some other suitable format.
This pass, only available in ``opt``, prints the control flow graph into a
``.dot`` graph. This graph can then be processed with the :program:`dot` tool
to convert it to postscript or some other suitable format.
Additionally the ``-cfg-func-name=<substring>`` option can be used to filter the
functions that are printed. All functions that contain the specified substring
will be printed.
``-dot-cfg-only``: Print CFG of function to "dot" file (with no function bodies)
--------------------------------------------------------------------------------
@ -135,6 +138,9 @@ This pass, only available in ``opt``, prints the control flow graph into a
``.dot`` graph, omitting the function bodies. This graph can then be processed
with the :program:`dot` tool to convert it to postscript or some other suitable
format.
Additionally the ``-cfg-func-name=<substring>`` option can be used to filter the
functions that are printed. All functions that contain the specified substring
will be printed.
``-dot-dom``: Print dominance tree of function to "dot" file
------------------------------------------------------------
@ -1192,12 +1198,18 @@ instead just tries to ensure that code is well-formed.
-----------------------------------
Displays the control flow graph using the GraphViz tool.
Additionally the ``-cfg-func-name=<substring>`` option can be used to filter the
functions that are displayed. All functions that contain the specified substring
will be displayed.
``-view-cfg-only``: View CFG of function (with no function bodies)
------------------------------------------------------------------
Displays the control flow graph using the GraphViz tool, but omitting function
bodies.
Additionally the ``-cfg-func-name=<substring>`` option can be used to filter the
functions that are displayed. All functions that contain the specified substring
will be displayed.
``-view-dom``: View dominance tree of function
----------------------------------------------

View File

@ -100,6 +100,8 @@ struct CFGViewerLegacyPass : public FunctionPass {
}
bool runOnFunction(Function &F) override {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return false;
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
@ -115,13 +117,15 @@ struct CFGViewerLegacyPass : public FunctionPass {
AU.setPreservesAll();
}
};
}
} // namespace
char CFGViewerLegacyPass::ID = 0;
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false,
true)
PreservedAnalyses CFGViewerPass::run(Function &F, FunctionAnalysisManager &AM) {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return PreservedAnalyses::all();
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
@ -136,6 +140,8 @@ struct CFGOnlyViewerLegacyPass : public FunctionPass {
}
bool runOnFunction(Function &F) override {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return false;
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
@ -151,7 +157,7 @@ struct CFGOnlyViewerLegacyPass : public FunctionPass {
AU.setPreservesAll();
}
};
}
} // namespace
char CFGOnlyViewerLegacyPass::ID = 0;
INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
@ -159,6 +165,8 @@ INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
FunctionAnalysisManager &AM) {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return PreservedAnalyses::all();
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
@ -173,6 +181,8 @@ struct CFGPrinterLegacyPass : public FunctionPass {
}
bool runOnFunction(Function &F) override {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return false;
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
@ -188,7 +198,7 @@ struct CFGPrinterLegacyPass : public FunctionPass {
AU.setPreservesAll();
}
};
}
} // namespace
char CFGPrinterLegacyPass::ID = 0;
INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
@ -196,6 +206,8 @@ INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
PreservedAnalyses CFGPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return PreservedAnalyses::all();
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
@ -210,6 +222,8 @@ struct CFGOnlyPrinterLegacyPass : public FunctionPass {
}
bool runOnFunction(Function &F) override {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return false;
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
@ -224,7 +238,7 @@ struct CFGOnlyPrinterLegacyPass : public FunctionPass {
AU.setPreservesAll();
}
};
}
} // namespace
char CFGOnlyPrinterLegacyPass::ID = 0;
INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
@ -233,6 +247,8 @@ INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
return PreservedAnalyses::all();
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);

View File

@ -0,0 +1,40 @@
; RUN: rm -f %t.other.dot %t-only.other.dot
;; Both f and func are dumped because their names contain the pattern 'f' as a substring.
; RUN: opt < %s -dot-cfg -cfg-dot-filename-prefix=%t -cfg-func-name=f 2>/dev/null
; RUN: FileCheck %s -input-file=%t.f.dot -check-prefix=F
; RUN: FileCheck %s -input-file=%t.func.dot -check-prefix=Func
; RUN: not test -f %t.other.dot
; RUN: opt < %s -dot-cfg-only -cfg-dot-filename-prefix=%t-only -cfg-func-name=f 2>/dev/null
; RUN: FileCheck %s -input-file=%t-only.f.dot -check-prefix=F
; RUN: FileCheck %s -input-file=%t-only.func.dot -check-prefix=Func
; RUN: not test -f %t-only.other.dot
; F: digraph "CFG for 'f' function"
define void @f(i32) {
entry:
%check = icmp sgt i32 %0, 0
br i1 %check, label %if, label %exit
if: ; preds = %entry
br label %exit
exit: ; preds = %entry, %if
ret void
}
; Func: digraph "CFG for 'func' function"
define void @func(i32) {
entry:
%check = icmp sgt i32 %0, 0
br label %exit
exit: ; preds = %entry
ret void
}
define void @other(i32) {
entry:
%check = icmp sgt i32 %0, 0
br label %exit
exit: ; preds = %entry
ret void
}