diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -127,6 +127,9 @@
 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 @@
 ``.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 @@
 -----------------------------------
 
 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
 ----------------------------------------------
diff --git a/llvm/lib/Analysis/CFGPrinter.cpp b/llvm/lib/Analysis/CFGPrinter.cpp
--- a/llvm/lib/Analysis/CFGPrinter.cpp
+++ b/llvm/lib/Analysis/CFGPrinter.cpp
@@ -100,6 +100,8 @@
   }
 
   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 @@
     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 @@
   }
 
   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 @@
     AU.setPreservesAll();
   }
 };
-}
+} // namespace
 
 char CFGOnlyViewerLegacyPass::ID = 0;
 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
@@ -159,6 +165,8 @@
 
 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 @@
   }
 
   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 @@
     AU.setPreservesAll();
   }
 };
-}
+} // namespace
 
 char CFGPrinterLegacyPass::ID = 0;
 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
@@ -196,6 +206,8 @@
 
 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 @@
   }
 
   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 @@
     AU.setPreservesAll();
   }
 };
-}
+} // namespace
 
 char CFGOnlyPrinterLegacyPass::ID = 0;
 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
@@ -233,6 +247,8 @@
 
 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);
diff --git a/llvm/test/Other/cfg-printer-filter.ll b/llvm/test/Other/cfg-printer-filter.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Other/cfg-printer-filter.ll
@@ -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
+}