forked from OSchip/llvm-project
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:
parent
f9aba9a5af
commit
053dbb939d
|
@ -127,6 +127,9 @@ postscript or some other suitable format.
|
||||||
This pass, only available in ``opt``, prints the control flow graph into a
|
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
|
``.dot`` graph. This graph can then be processed with the :program:`dot` tool
|
||||||
to convert it to postscript or some other suitable format.
|
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)
|
``-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
|
``.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
|
with the :program:`dot` tool to convert it to postscript or some other suitable
|
||||||
format.
|
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
|
``-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.
|
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)
|
``-view-cfg-only``: View CFG of function (with no function bodies)
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
|
|
||||||
Displays the control flow graph using the GraphViz tool, but omitting function
|
Displays the control flow graph using the GraphViz tool, but omitting function
|
||||||
bodies.
|
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-dom``: View dominance tree of function
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
|
@ -100,6 +100,8 @@ struct CFGViewerLegacyPass : public FunctionPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnFunction(Function &F) override {
|
bool runOnFunction(Function &F) override {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return false;
|
||||||
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
||||||
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
|
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
|
||||||
|
@ -115,13 +117,15 @@ struct CFGViewerLegacyPass : public FunctionPass {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
char CFGViewerLegacyPass::ID = 0;
|
char CFGViewerLegacyPass::ID = 0;
|
||||||
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false,
|
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false,
|
||||||
true)
|
true)
|
||||||
|
|
||||||
PreservedAnalyses CFGViewerPass::run(Function &F, FunctionAnalysisManager &AM) {
|
PreservedAnalyses CFGViewerPass::run(Function &F, FunctionAnalysisManager &AM) {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return PreservedAnalyses::all();
|
||||||
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
||||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
||||||
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
|
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
|
||||||
|
@ -136,6 +140,8 @@ struct CFGOnlyViewerLegacyPass : public FunctionPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnFunction(Function &F) override {
|
bool runOnFunction(Function &F) override {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return false;
|
||||||
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
||||||
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
||||||
|
@ -151,7 +157,7 @@ struct CFGOnlyViewerLegacyPass : public FunctionPass {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
char CFGOnlyViewerLegacyPass::ID = 0;
|
char CFGOnlyViewerLegacyPass::ID = 0;
|
||||||
INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
|
INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
|
||||||
|
@ -159,6 +165,8 @@ INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
|
||||||
|
|
||||||
PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
|
PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
|
||||||
FunctionAnalysisManager &AM) {
|
FunctionAnalysisManager &AM) {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return PreservedAnalyses::all();
|
||||||
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
||||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
||||||
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
||||||
|
@ -173,6 +181,8 @@ struct CFGPrinterLegacyPass : public FunctionPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnFunction(Function &F) override {
|
bool runOnFunction(Function &F) override {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return false;
|
||||||
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
||||||
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
|
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
|
||||||
|
@ -188,7 +198,7 @@ struct CFGPrinterLegacyPass : public FunctionPass {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
char CFGPrinterLegacyPass::ID = 0;
|
char CFGPrinterLegacyPass::ID = 0;
|
||||||
INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
|
INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
|
||||||
|
@ -196,6 +206,8 @@ INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
|
||||||
|
|
||||||
PreservedAnalyses CFGPrinterPass::run(Function &F,
|
PreservedAnalyses CFGPrinterPass::run(Function &F,
|
||||||
FunctionAnalysisManager &AM) {
|
FunctionAnalysisManager &AM) {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return PreservedAnalyses::all();
|
||||||
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
||||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
||||||
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
|
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI));
|
||||||
|
@ -210,6 +222,8 @@ struct CFGOnlyPrinterLegacyPass : public FunctionPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnFunction(Function &F) override {
|
bool runOnFunction(Function &F) override {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return false;
|
||||||
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
|
||||||
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
||||||
|
@ -224,7 +238,7 @@ struct CFGOnlyPrinterLegacyPass : public FunctionPass {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
char CFGOnlyPrinterLegacyPass::ID = 0;
|
char CFGOnlyPrinterLegacyPass::ID = 0;
|
||||||
INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
|
INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
|
||||||
|
@ -233,6 +247,8 @@ INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
|
||||||
|
|
||||||
PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
|
PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
|
||||||
FunctionAnalysisManager &AM) {
|
FunctionAnalysisManager &AM) {
|
||||||
|
if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
|
||||||
|
return PreservedAnalyses::all();
|
||||||
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
|
||||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
|
||||||
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue