[flang-commits] [flang] [flang][NFC] Refactor to remove .inc file containing shared code (PR #109874)

Tarun Prabhu via flang-commits flang-commits at lists.llvm.org
Wed Sep 25 10:21:11 PDT 2024


https://github.com/tarunprabhu updated https://github.com/llvm/llvm-project/pull/109874

>From 51a60d173f15bdbdaafd2a927f372789fde3bbce Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu at gmail.com>
Date: Tue, 24 Sep 2024 16:03:24 -0600
Subject: [PATCH 1/4] [flang] Refactor to remove .inc file containing shared
 code

Remove flang/include/flang/Tools/CLOptions.inc - which was included as is in -
several places. Move the code in it to header and source files which are used
used in the "standard" way. Some minor cleanup such as removing trailing
whitespace and excessive newlines and reordering entries alphabetically for
files that were modified along the way. Update the documentation that
referenced CLOptions.inc.
---
 flang/docs/FlangDriver.md                     |   2 +-
 flang/include/flang/Common/CommandLineOpts.h  |  60 +++
 .../flang/Optimizer/Passes/Pipelines.h        | 128 +++++
 flang/include/flang/Tools/CLOptions.inc       | 438 ------------------
 flang/lib/Common/CMakeLists.txt               |   5 +-
 flang/lib/Common/CommandLineOpts.cpp          |  67 +++
 flang/lib/Frontend/CMakeLists.txt             |   1 +
 flang/lib/Frontend/FrontendActions.cpp        |   3 +-
 flang/lib/Optimizer/CMakeLists.txt            |   5 +-
 flang/lib/Optimizer/Passes/CMakeLists.txt     |  21 +
 flang/lib/Optimizer/Passes/Pipelines.cpp      | 330 +++++++++++++
 flang/tools/bbc/CMakeLists.txt                |   1 +
 flang/tools/bbc/bbc.cpp                       |   3 +-
 flang/tools/tco/CMakeLists.txt                |   2 +
 flang/tools/tco/tco.cpp                       |   3 +-
 15 files changed, 622 insertions(+), 447 deletions(-)
 create mode 100644 flang/include/flang/Common/CommandLineOpts.h
 create mode 100644 flang/include/flang/Optimizer/Passes/Pipelines.h
 delete mode 100644 flang/include/flang/Tools/CLOptions.inc
 create mode 100644 flang/lib/Common/CommandLineOpts.cpp
 create mode 100644 flang/lib/Optimizer/Passes/CMakeLists.txt
 create mode 100644 flang/lib/Optimizer/Passes/Pipelines.cpp

diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index e1c11062125028..815c26a28dfdfa 100644
--- a/flang/docs/FlangDriver.md
+++ b/flang/docs/FlangDriver.md
@@ -521,7 +521,7 @@ e.g. during the semantic checks.
 ## FIR Optimizer Pass Pipeline Extension Points
 
 The default FIR optimizer pass pipeline `createDefaultFIROptimizerPassPipeline`
-in `flang/include/flang/Tools/CLOptions.inc` contains extension point callback
+in `flang/lib/Optimizer/Passes/Pipelines.cpp` contains extension point callback
 invocations `invokeFIROptEarlyEPCallbacks`, `invokeFIRInlinerCallback`, and
 `invokeFIROptLastEPCallbacks` for Flang drivers to be able to insert additonal
 passes at different points of the default pass pipeline. An example use of these
diff --git a/flang/include/flang/Common/CommandLineOpts.h b/flang/include/flang/Common/CommandLineOpts.h
new file mode 100644
index 00000000000000..72674b2b809c24
--- /dev/null
+++ b/flang/include/flang/Common/CommandLineOpts.h
@@ -0,0 +1,60 @@
+//===-- CommandLineOptions.h -- shared command line options -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/// This file declares some shared command-line options that can be used when
+/// debugging the test tools.
+
+#ifndef FORTRAN_COMMON_COMMANDLINEOPTS_H
+#define FORTRAN_COMMON_COMMANDLINEOPTS_H
+
+#include "llvm/Frontend/Debug/Options.h"
+#include "llvm/Passes/OptimizationLevel.h"
+#include "llvm/Support/CommandLine.h"
+
+/// Shared option in tools to control whether dynamically sized array
+/// allocations should always be on the heap.
+extern llvm::cl::opt<bool> dynamicArrayStackToHeapAllocation;
+
+/// Shared option in tools to set a maximum value for the number of elements in
+/// a compile-time sized array that can be allocated on the stack.
+extern llvm::cl::opt<std::size_t> arrayStackAllocationThreshold;
+
+/// Shared option in tools to ignore missing runtime type descriptor objects
+/// when translating FIR to LLVM. The resulting program will crash if the
+/// runtime needs the derived type descriptors, this is only a debug option to
+/// allow compiling manually written FIR programs involving derived types
+/// without having to write the derived type descriptors which are normally
+/// generated by the frontend.
+extern llvm::cl::opt<bool> ignoreMissingTypeDescriptors;
+
+/// Default optimization level used to create Flang pass pipeline is O0.
+extern llvm::OptimizationLevel defaultOptLevel;
+
+extern llvm::codegenoptions::DebugInfoKind noDebugInfo;
+
+/// Optimizer Passes
+extern llvm::cl::opt<bool> disableCfgConversion;
+extern llvm::cl::opt<bool> disableFirAvc;
+extern llvm::cl::opt<bool> disableFirMao;
+
+extern llvm::cl::opt<bool> disableFirAliasTags;
+extern llvm::cl::opt<bool> useOldAliasTags;
+
+/// CodeGen Passes
+extern llvm::cl::opt<bool> disableCodeGenRewrite;
+extern llvm::cl::opt<bool> disableTargetRewrite;
+extern llvm::cl::opt<bool> disableDebugInfo;
+extern llvm::cl::opt<bool> disableFirToLlvmIr;
+extern llvm::cl::opt<bool> disableLlvmIrToLlvm;
+extern llvm::cl::opt<bool> disableBoxedProcedureRewrite;
+
+extern llvm::cl::opt<bool> disableExternalNameConversion;
+extern llvm::cl::opt<bool> enableConstantArgumentGlobalisation;
+extern llvm::cl::opt<bool> disableCompilerGeneratedNamesConversion;
+
+#endif // FORTRAN_COMMON_COMMANDLINE_OPTS_H
diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
new file mode 100644
index 00000000000000..8980bfbb90e9a0
--- /dev/null
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -0,0 +1,128 @@
+//===-- Pipelines.h -- FIR pass pipelines -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/// This file declares some utilties to setup FIR pass pipelines. These are
+/// common to flang and the test tools.
+
+#ifndef FORTRAN_OPTIMIZER_PASSES_PIPELINES_H
+#define FORTRAN_OPTIMIZER_PASSES_PIPELINES_H
+
+#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/CodeGen/CodeGen.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
+#include "flang/Optimizer/OpenMP/Passes.h"
+#include "flang/Optimizer/Transforms/Passes.h"
+#include "flang/Tools/CrossToolHelpers.h"
+#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
+#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Pass/PassManager.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "mlir/Transforms/Passes.h"
+#include "llvm/Frontend/Debug/Options.h"
+#include "llvm/Passes/OptimizationLevel.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace {
+
+using PassConstructor = std::unique_ptr<mlir::Pass>();
+
+template <typename OP>
+void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) {
+  pm.addNestedPass<OP>(ctor());
+}
+
+template <typename OP, typename... OPS,
+          typename = std::enable_if_t<sizeof...(OPS) != 0>>
+void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) {
+  addNestedPassToOps<OP>(pm, ctor);
+  addNestedPassToOps<OPS...>(pm, ctor);
+}
+
+/// Generic for adding a pass to the pass manager if it is not disabled.
+template <typename F>
+void addPassConditionally(mlir::PassManager &pm, llvm::cl::opt<bool> &disabled,
+                          F ctor) {
+  if (!disabled)
+    pm.addPass(ctor());
+}
+
+template <typename OP, typename F>
+void addNestedPassConditionally(mlir::PassManager &pm,
+                                llvm::cl::opt<bool> &disabled, F ctor) {
+  if (!disabled)
+    pm.addNestedPass<OP>(ctor());
+}
+
+} // namespace
+
+namespace fir {
+
+void addDebugInfoPass(mlir::PassManager &pm,
+                      llvm::codegenoptions::DebugInfoKind debugLevel,
+                      llvm::OptimizationLevel optLevel,
+                      llvm::StringRef inputFilename);
+
+void addFIRToLLVMPass(mlir::PassManager &pm,
+                      const MLIRToLLVMPassPipelineConfig &config);
+
+void addLLVMDialectToLLVMPass(mlir::PassManager &pm, llvm::raw_ostream &output);
+
+/// Use inliner extension point callback to register the default inliner pass.
+void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config);
+
+/// Create a pass pipeline for running default optimization passes for
+/// incremental conversion of FIR.
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
+                                           MLIRToLLVMPassPipelineConfig &pc);
+
+/// Create a pass pipeline for lowering from HLFIR to FIR
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+/// \param optLevel - optimization level used for creating FIR optimization
+///   passes pipeline
+void createHLFIRToFIRPassPipeline(
+    mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel);
+
+/// Create a pass pipeline for handling certain OpenMP transformations needed
+/// prior to FIR lowering.
+///
+/// WARNING: These passes must be run immediately after the lowering to ensure
+/// that the FIR is correct with respect to OpenMP operations/attributes.
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition.
+/// \param isTargetDevice - Whether code is being generated for a target device
+/// rather than the host device.
+void createOpenMPFIRPassPipeline(mlir::PassManager &pm, bool isTargetDevice);
+
+#if !defined(FLANG_EXCLUDE_CODEGEN)
+void createDebugPasses(mlir::PassManager &pm,
+                       llvm::codegenoptions::DebugInfoKind debugLevel,
+                       llvm::OptimizationLevel OptLevel,
+                       llvm::StringRef inputFilename);
+
+void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
+                                         MLIRToLLVMPassPipelineConfig config,
+                                         llvm::StringRef inputFilename = {});
+
+/// Create a pass pipeline for lowering from MLIR to LLVM IR
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+/// \param optLevel - optimization level used for creating FIR optimization
+///   passes pipeline
+void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
+                                  MLIRToLLVMPassPipelineConfig &config,
+                                  llvm::StringRef inputFilename = {});
+#undef FLANG_EXCLUDE_CODEGEN
+#endif
+
+} // namespace fir
+
+#endif // FORTRAN_OPTIMIZER_PASSES_PIPELINES_H
diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
deleted file mode 100644
index 04b7f0ba370b86..00000000000000
--- a/flang/include/flang/Tools/CLOptions.inc
+++ /dev/null
@@ -1,438 +0,0 @@
-//===-- CLOptions.inc -- command line options -------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-/// This file defines some shared command-line options that can be used when
-/// debugging the test tools. This file must be included into the tool.
-
-#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
-#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
-#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
-#include "mlir/Pass/PassManager.h"
-#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
-#include "mlir/Transforms/Passes.h"
-#include "flang/Optimizer/CodeGen/CodeGen.h"
-#include "flang/Optimizer/HLFIR/Passes.h"
-#include "flang/Optimizer/OpenMP/Passes.h"
-#include "flang/Optimizer/Transforms/Passes.h"
-#include "llvm/Passes/OptimizationLevel.h"
-#include "llvm/Support/CommandLine.h"
-#include <type_traits>
-
-#define DisableOption(DOName, DOOption, DODescription) \
-  static llvm::cl::opt<bool> disable##DOName("disable-" DOOption, \
-      llvm::cl::desc("disable " DODescription " pass"), llvm::cl::init(false), \
-      llvm::cl::Hidden)
-#define EnableOption(EOName, EOOption, EODescription) \
-  static llvm::cl::opt<bool> enable##EOName("enable-" EOOption, \
-      llvm::cl::desc("enable " EODescription " pass"), llvm::cl::init(false), \
-      llvm::cl::Hidden)
-
-/// Shared option in tools to control whether dynamically sized array
-/// allocations should always be on the heap.
-static llvm::cl::opt<bool> dynamicArrayStackToHeapAllocation(
-    "fdynamic-heap-array",
-    llvm::cl::desc("place all array allocations of dynamic size on the heap"),
-    llvm::cl::init(false), llvm::cl::Hidden);
-
-/// Shared option in tools to set a maximum value for the number of elements in
-/// a compile-time sized array that can be allocated on the stack.
-static llvm::cl::opt<std::size_t> arrayStackAllocationThreshold(
-    "fstack-array-size",
-    llvm::cl::desc(
-        "place all array allocations more than <size> elements on the heap"),
-    llvm::cl::init(~static_cast<std::size_t>(0)), llvm::cl::Hidden);
-
-/// Shared option in tools to ignore missing runtime type descriptor objects
-/// when translating FIR to LLVM. The resulting program will crash if the
-/// runtime needs the derived type descriptors, this is only a debug option to
-/// allow compiling manually written FIR programs involving derived types
-/// without having to write the derived type descriptors which are normally
-/// generated by the frontend.
-static llvm::cl::opt<bool> ignoreMissingTypeDescriptors(
-    "ignore-missing-type-desc",
-    llvm::cl::desc("ignore failures to find derived type descriptors when "
-                   "translating FIR to LLVM"),
-    llvm::cl::init(false), llvm::cl::Hidden);
-
-namespace {
-/// Default optimization level used to create Flang pass pipeline is O0.
-const static llvm::OptimizationLevel &defaultOptLevel{
-    llvm::OptimizationLevel::O0};
-
-const static llvm::codegenoptions::DebugInfoKind &NoDebugInfo{
-    llvm::codegenoptions::NoDebugInfo};
-
-/// Optimizer Passes
-DisableOption(CfgConversion, "cfg-conversion", "disable FIR to CFG pass");
-DisableOption(FirAvc, "avc", "array value copy analysis and transformation");
-DisableOption(
-    FirMao, "memory-allocation-opt", "memory allocation optimization");
-
-DisableOption(FirAliasTags, "fir-alias-tags", "fir alias analysis");
-static llvm::cl::opt<bool> useOldAliasTags("use-old-alias-tags",
-    llvm::cl::desc("Use a single TBAA tree for all functions and do not use "
-                   "the FIR alias tags pass"),
-    llvm::cl::init(false), llvm::cl::Hidden);
-
-/// CodeGen Passes
-#if !defined(FLANG_EXCLUDE_CODEGEN)
-DisableOption(CodeGenRewrite, "codegen-rewrite", "rewrite FIR for codegen");
-DisableOption(TargetRewrite, "target-rewrite", "rewrite FIR for target");
-DisableOption(DebugInfo, "debug-info", "Add debug info");
-DisableOption(FirToLlvmIr, "fir-to-llvmir", "FIR to LLVM-IR dialect");
-DisableOption(LlvmIrToLlvm, "llvm", "conversion to LLVM");
-DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite",
-    "rewrite boxed procedures");
-#endif
-
-DisableOption(ExternalNameConversion, "external-name-interop",
-    "convert names with external convention");
-EnableOption(ConstantArgumentGlobalisation, "constant-argument-globalisation",
-    "the local constant argument to global constant conversion");
-DisableOption(CompilerGeneratedNamesConversion, "compiler-generated-names",
-    "replace special symbols in compiler generated names");
-
-using PassConstructor = std::unique_ptr<mlir::Pass>();
-
-template <typename OP>
-void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) {
-  pm.addNestedPass<OP>(ctor());
-}
-
-template <typename OP, typename... OPS,
-    typename = std::enable_if_t<sizeof...(OPS) != 0>>
-void addNestedPassToOps(mlir::PassManager &pm, PassConstructor ctor) {
-  addNestedPassToOps<OP>(pm, ctor);
-  addNestedPassToOps<OPS...>(pm, ctor);
-}
-
-void addNestedPassToAllTopLevelOperations(
-    mlir::PassManager &pm, PassConstructor ctor) {
-  addNestedPassToOps<mlir::func::FuncOp, mlir::omp::DeclareReductionOp,
-      mlir::omp::PrivateClauseOp, fir::GlobalOp>(pm, ctor);
-}
-
-void addNestedPassToAllTopLevelOperationsConditionally(mlir::PassManager &pm,
-    llvm::cl::opt<bool> &disabled, PassConstructor ctor) {
-  if (!disabled)
-    addNestedPassToAllTopLevelOperations(pm, ctor);
-}
-
-/// Generic for adding a pass to the pass manager if it is not disabled.
-template <typename F>
-void addPassConditionally(
-    mlir::PassManager &pm, llvm::cl::opt<bool> &disabled, F ctor) {
-  if (!disabled)
-    pm.addPass(ctor());
-}
-
-template <typename OP, typename F>
-void addNestedPassConditionally(
-    mlir::PassManager &pm, llvm::cl::opt<bool> &disabled, F ctor) {
-  if (!disabled)
-    pm.addNestedPass<OP>(ctor());
-}
-
-} // namespace
-
-namespace fir {
-
-/// Add MLIR Canonicalizer pass with region simplification disabled.
-/// FIR does not support the promotion of some SSA value to block arguments (or
-/// into arith.select operands) that may be done by mlir block merging in the
-/// region simplification (e.g., !fir.shape<> SSA values are not supported as
-/// block arguments).
-/// Aside from the fir.shape issue, moving some abstract SSA value into block
-/// arguments may have a heavy cost since it forces their code generation that
-/// may be expensive (array temporary). The MLIR pass does not take these
-/// extra costs into account when doing block merging.
-static void addCanonicalizerPassWithoutRegionSimplification(
-    mlir::OpPassManager &pm) {
-  mlir::GreedyRewriteConfig config;
-  config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
-  pm.addPass(mlir::createCanonicalizerPass(config));
-}
-
-inline void addCfgConversionPass(
-    mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) {
-  if (config.NSWOnLoopVarInc)
-    addNestedPassToAllTopLevelOperationsConditionally(
-        pm, disableCfgConversion, fir::createCFGConversionPassWithNSW);
-  else
-    addNestedPassToAllTopLevelOperationsConditionally(
-        pm, disableCfgConversion, fir::createCFGConversion);
-}
-
-inline void addAVC(
-    mlir::PassManager &pm, const llvm::OptimizationLevel &optLevel) {
-  ArrayValueCopyOptions options;
-  options.optimizeConflicts = optLevel.isOptimizingForSpeed();
-  addNestedPassConditionally<mlir::func::FuncOp>(
-      pm, disableFirAvc, [&]() { return createArrayValueCopyPass(options); });
-}
-
-inline void addMemoryAllocationOpt(mlir::PassManager &pm) {
-  addNestedPassConditionally<mlir::func::FuncOp>(pm, disableFirMao, [&]() {
-    return fir::createMemoryAllocationOpt(
-        {dynamicArrayStackToHeapAllocation, arrayStackAllocationThreshold});
-  });
-}
-
-#if !defined(FLANG_EXCLUDE_CODEGEN)
-inline void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) {
-  fir::CodeGenRewriteOptions options;
-  options.preserveDeclare = preserveDeclare;
-  addPassConditionally(pm, disableCodeGenRewrite,
-      [&]() { return fir::createCodeGenRewrite(options); });
-}
-
-inline void addTargetRewritePass(mlir::PassManager &pm) {
-  addPassConditionally(pm, disableTargetRewrite,
-      []() { return fir::createTargetRewritePass(); });
-}
-
-inline mlir::LLVM::DIEmissionKind getEmissionKind(
-    llvm::codegenoptions::DebugInfoKind kind) {
-  switch (kind) {
-  case llvm::codegenoptions::DebugInfoKind::FullDebugInfo:
-    return mlir::LLVM::DIEmissionKind::Full;
-  case llvm::codegenoptions::DebugInfoKind::DebugLineTablesOnly:
-    return mlir::LLVM::DIEmissionKind::LineTablesOnly;
-  default:
-    return mlir::LLVM::DIEmissionKind::None;
-  }
-}
-
-inline void addDebugInfoPass(mlir::PassManager &pm,
-    llvm::codegenoptions::DebugInfoKind debugLevel,
-    llvm::OptimizationLevel optLevel, llvm::StringRef inputFilename) {
-  fir::AddDebugInfoOptions options;
-  options.debugLevel = getEmissionKind(debugLevel);
-  options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
-  options.inputFilename = inputFilename;
-  addPassConditionally(pm, disableDebugInfo,
-      [&]() { return fir::createAddDebugInfoPass(options); });
-}
-
-inline void addFIRToLLVMPass(
-    mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) {
-  fir::FIRToLLVMPassOptions options;
-  options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
-  options.applyTBAA = config.AliasAnalysis;
-  options.forceUnifiedTBAATree = useOldAliasTags;
-  options.typeDescriptorsRenamedForAssembly =
-      !disableCompilerGeneratedNamesConversion;
-  addPassConditionally(pm, disableFirToLlvmIr,
-      [&]() { return fir::createFIRToLLVMPass(options); });
-  // The dialect conversion framework may leave dead unrealized_conversion_cast
-  // ops behind, so run reconcile-unrealized-casts to clean them up.
-  addPassConditionally(pm, disableFirToLlvmIr,
-      [&]() { return mlir::createReconcileUnrealizedCastsPass(); });
-}
-
-inline void addLLVMDialectToLLVMPass(
-    mlir::PassManager &pm, llvm::raw_ostream &output) {
-  addPassConditionally(pm, disableLlvmIrToLlvm,
-      [&]() { return fir::createLLVMDialectToLLVMPass(output); });
-}
-
-inline void addBoxedProcedurePass(mlir::PassManager &pm) {
-  addPassConditionally(pm, disableBoxedProcedureRewrite,
-      [&]() { return fir::createBoxedProcedurePass(); });
-}
-#endif
-
-inline void addExternalNameConversionPass(
-    mlir::PassManager &pm, bool appendUnderscore = true) {
-  addPassConditionally(pm, disableExternalNameConversion,
-      [&]() { return fir::createExternalNameConversion({appendUnderscore}); });
-}
-
-inline void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm) {
-  addPassConditionally(pm, disableCompilerGeneratedNamesConversion,
-      [&]() { return fir::createCompilerGeneratedNamesConversion(); });
-}
-
-// Use inliner extension point callback to register the default inliner pass.
-inline void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config) {
-  config.registerFIRInlinerCallback(
-      [](mlir::PassManager &pm, llvm::OptimizationLevel level) {
-        llvm::StringMap<mlir::OpPassManager> pipelines;
-        // The default inliner pass adds the canonicalizer pass with the default
-        // configuration.
-        pm.addPass(mlir::createInlinerPass(
-            pipelines, addCanonicalizerPassWithoutRegionSimplification));
-      });
-}
-
-/// Create a pass pipeline for running default optimization passes for
-/// incremental conversion of FIR.
-///
-/// \param pm - MLIR pass manager that will hold the pipeline definition
-inline void createDefaultFIROptimizerPassPipeline(
-    mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig &pc) {
-  // Early Optimizer EP Callback
-  pc.invokeFIROptEarlyEPCallbacks(pm, pc.OptLevel);
-
-  // simplify the IR
-  mlir::GreedyRewriteConfig config;
-  config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
-  pm.addPass(mlir::createCSEPass());
-  fir::addAVC(pm, pc.OptLevel);
-  addNestedPassToAllTopLevelOperations(pm, fir::createCharacterConversion);
-  pm.addPass(mlir::createCanonicalizerPass(config));
-  pm.addPass(fir::createSimplifyRegionLite());
-  if (pc.OptLevel.isOptimizingForSpeed()) {
-    // These passes may increase code size.
-    pm.addPass(fir::createSimplifyIntrinsics());
-    pm.addPass(fir::createAlgebraicSimplificationPass(config));
-    if (enableConstantArgumentGlobalisation)
-      pm.addPass(fir::createConstantArgumentGlobalisationOpt());
-  }
-
-  if (pc.LoopVersioning)
-    pm.addPass(fir::createLoopVersioning());
-
-  pm.addPass(mlir::createCSEPass());
-
-  if (pc.StackArrays)
-    pm.addPass(fir::createStackArrays());
-  else
-    fir::addMemoryAllocationOpt(pm);
-
-  // FIR Inliner Callback
-  pc.invokeFIRInlinerCallback(pm, pc.OptLevel);
-
-  pm.addPass(fir::createSimplifyRegionLite());
-  pm.addPass(mlir::createCSEPass());
-
-  // Polymorphic types
-  pm.addPass(fir::createPolymorphicOpConversion());
-  pm.addPass(fir::createAssumedRankOpConversion());
-
-  if (pc.AliasAnalysis && !disableFirAliasTags && !useOldAliasTags)
-    pm.addPass(fir::createAddAliasTags());
-
-  addNestedPassToAllTopLevelOperations(pm, fir::createStackReclaim);
-  // convert control flow to CFG form
-  fir::addCfgConversionPass(pm, pc);
-  pm.addPass(mlir::createConvertSCFToCFPass());
-
-  pm.addPass(mlir::createCanonicalizerPass(config));
-  pm.addPass(fir::createSimplifyRegionLite());
-  pm.addPass(mlir::createCSEPass());
-
-  // Last Optimizer EP Callback
-  pc.invokeFIROptLastEPCallbacks(pm, pc.OptLevel);
-}
-
-/// Create a pass pipeline for lowering from HLFIR to FIR
-///
-/// \param pm - MLIR pass manager that will hold the pipeline definition
-/// \param optLevel - optimization level used for creating FIR optimization
-///   passes pipeline
-inline void createHLFIRToFIRPassPipeline(
-    mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) {
-  if (optLevel.isOptimizingForSpeed()) {
-    addCanonicalizerPassWithoutRegionSimplification(pm);
-    addNestedPassToAllTopLevelOperations(
-        pm, hlfir::createSimplifyHLFIRIntrinsics);
-  }
-  addNestedPassToAllTopLevelOperations(pm, hlfir::createInlineElementals);
-  if (optLevel.isOptimizingForSpeed()) {
-    addCanonicalizerPassWithoutRegionSimplification(pm);
-    pm.addPass(mlir::createCSEPass());
-    addNestedPassToAllTopLevelOperations(
-        pm, hlfir::createOptimizedBufferization);
-  }
-  pm.addPass(hlfir::createLowerHLFIROrderedAssignments());
-  pm.addPass(hlfir::createLowerHLFIRIntrinsics());
-  pm.addPass(hlfir::createBufferizeHLFIR());
-  pm.addPass(hlfir::createConvertHLFIRtoFIR());
-}
-
-/// Create a pass pipeline for handling certain OpenMP transformations needed
-/// prior to FIR lowering.
-///
-/// WARNING: These passes must be run immediately after the lowering to ensure
-/// that the FIR is correct with respect to OpenMP operations/attributes.
-///
-/// \param pm - MLIR pass manager that will hold the pipeline definition.
-/// \param isTargetDevice - Whether code is being generated for a target device
-/// rather than the host device.
-inline void createOpenMPFIRPassPipeline(
-    mlir::PassManager &pm, bool isTargetDevice) {
-  pm.addPass(flangomp::createMapInfoFinalizationPass());
-  pm.addPass(flangomp::createMarkDeclareTargetPass());
-  if (isTargetDevice)
-    pm.addPass(flangomp::createFunctionFilteringPass());
-}
-
-#if !defined(FLANG_EXCLUDE_CODEGEN)
-inline void createDebugPasses(mlir::PassManager &pm,
-    llvm::codegenoptions::DebugInfoKind debugLevel,
-    llvm::OptimizationLevel OptLevel, llvm::StringRef inputFilename) {
-  if (debugLevel != llvm::codegenoptions::NoDebugInfo)
-    addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename);
-}
-
-inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
-    MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) {
-  fir::addBoxedProcedurePass(pm);
-  addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt);
-  fir::addCodeGenRewritePass(
-      pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
-  fir::addTargetRewritePass(pm);
-  fir::addCompilerGeneratedNamesConversionPass(pm);
-  fir::addExternalNameConversionPass(pm, config.Underscoring);
-  fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);
-
-  if (config.VScaleMin != 0)
-    pm.addPass(fir::createVScaleAttr({{config.VScaleMin, config.VScaleMax}}));
-
-  // Add function attributes
-  mlir::LLVM::framePointerKind::FramePointerKind framePointerKind;
-
-  if (config.FramePointerKind != llvm::FramePointerKind::None ||
-      config.NoInfsFPMath || config.NoNaNsFPMath || config.ApproxFuncFPMath ||
-      config.NoSignedZerosFPMath || config.UnsafeFPMath) {
-    if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf)
-      framePointerKind =
-          mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf;
-    else if (config.FramePointerKind == llvm::FramePointerKind::All)
-      framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::All;
-    else
-      framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::None;
-
-    pm.addPass(fir::createFunctionAttr({framePointerKind, config.NoInfsFPMath,
-        config.NoNaNsFPMath, config.ApproxFuncFPMath,
-        config.NoSignedZerosFPMath, config.UnsafeFPMath}));
-  }
-
-  fir::addFIRToLLVMPass(pm, config);
-}
-
-/// Create a pass pipeline for lowering from MLIR to LLVM IR
-///
-/// \param pm - MLIR pass manager that will hold the pipeline definition
-/// \param optLevel - optimization level used for creating FIR optimization
-///   passes pipeline
-inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
-    MLIRToLLVMPassPipelineConfig &config, llvm::StringRef inputFilename = {}) {
-  fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel);
-
-  // Add default optimizer pass pipeline.
-  fir::createDefaultFIROptimizerPassPipeline(pm, config);
-
-  // Add codegen pass pipeline.
-  fir::createDefaultFIRCodeGenPassPipeline(pm, config, inputFilename);
-}
-#undef FLANG_EXCLUDE_CODEGEN
-#endif
-
-} // namespace fir
diff --git a/flang/lib/Common/CMakeLists.txt b/flang/lib/Common/CMakeLists.txt
index c6f818ad27cd19..6e5bdfa2f6236b 100644
--- a/flang/lib/Common/CMakeLists.txt
+++ b/flang/lib/Common/CMakeLists.txt
@@ -12,7 +12,7 @@ endif()
 if(flang_vc AND LLVM_APPEND_VC_REV)
   set(flang_source_dir ${FLANG_SOURCE_DIR})
 endif()
- 
+
 # Create custom target to generate the VC revision include.
 add_custom_command(OUTPUT "${version_inc}"
   DEPENDS "${llvm_vc}" "${flang_vc}" "${generate_vcs_version_script}"
@@ -34,8 +34,8 @@ if(FLANG_VENDOR)
     PROPERTIES COMPILE_DEFINITIONS "FLANG_VENDOR=\"${FLANG_VENDOR} \"")
 endif()
 
-
 add_flang_library(FortranCommon
+  CommandLineOpts.cpp
   Fortran.cpp
   Fortran-features.cpp
   default-kinds.cpp
@@ -44,5 +44,6 @@ add_flang_library(FortranCommon
   ${version_inc}
 
   LINK_COMPONENTS
+  Passes
   Support
 )
diff --git a/flang/lib/Common/CommandLineOpts.cpp b/flang/lib/Common/CommandLineOpts.cpp
new file mode 100644
index 00000000000000..f77863bd77525d
--- /dev/null
+++ b/flang/lib/Common/CommandLineOpts.cpp
@@ -0,0 +1,67 @@
+//===-- CommandLineOpts.cpp -- shared command line options ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/// This file defines some shared command-line options that can be used when
+/// debugging the test tools.
+
+#include "flang/Common/CommandLineOpts.h"
+
+using namespace llvm;
+
+#define DisableOption(DOName, DOOption, DODescription) \
+  cl::opt<bool> disable##DOName("disable-" DOOption, \
+      cl::desc("disable " DODescription " pass"), cl::init(false), cl::Hidden)
+#define EnableOption(EOName, EOOption, EODescription) \
+  cl::opt<bool> enable##EOName("enable-" EOOption, \
+      cl::desc("enable " EODescription " pass"), cl::init(false), cl::Hidden)
+
+cl::opt<bool> dynamicArrayStackToHeapAllocation("fdynamic-heap-array",
+    cl::desc("place all array allocations of dynamic size on the heap"),
+    cl::init(false), cl::Hidden);
+
+cl::opt<std::size_t> arrayStackAllocationThreshold("fstack-array-size",
+    cl::desc(
+        "place all array allocations more than <size> elements on the heap"),
+    cl::init(~static_cast<std::size_t>(0)), cl::Hidden);
+
+cl::opt<bool> ignoreMissingTypeDescriptors("ignore-missing-type-desc",
+    cl::desc("ignore failures to find derived type descriptors when "
+             "translating FIR to LLVM"),
+    cl::init(false), cl::Hidden);
+
+OptimizationLevel defaultOptLevel{OptimizationLevel::O0};
+
+codegenoptions::DebugInfoKind noDebugInfo{codegenoptions::NoDebugInfo};
+
+/// Optimizer Passes
+DisableOption(CfgConversion, "cfg-conversion", "disable FIR to CFG pass");
+DisableOption(FirAvc, "avc", "array value copy analysis and transformation");
+DisableOption(
+    FirMao, "memory-allocation-opt", "memory allocation optimization");
+
+DisableOption(FirAliasTags, "fir-alias-tags", "fir alias analysis");
+cl::opt<bool> useOldAliasTags("use-old-alias-tags",
+    cl::desc("Use a single TBAA tree for all functions and do not use "
+             "the FIR alias tags pass"),
+    cl::init(false), cl::Hidden);
+
+/// CodeGen Passes
+DisableOption(CodeGenRewrite, "codegen-rewrite", "rewrite FIR for codegen");
+DisableOption(TargetRewrite, "target-rewrite", "rewrite FIR for target");
+DisableOption(DebugInfo, "debug-info", "Add debug info");
+DisableOption(FirToLlvmIr, "fir-to-llvmir", "FIR to LLVM-IR dialect");
+DisableOption(LlvmIrToLlvm, "llvm", "conversion to LLVM");
+DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite",
+    "rewrite boxed procedures");
+
+DisableOption(ExternalNameConversion, "external-name-interop",
+    "convert names with external convention");
+EnableOption(ConstantArgumentGlobalisation, "constant-argument-globalisation",
+    "the local constant argument to global constant conversion");
+DisableOption(CompilerGeneratedNamesConversion, "compiler-generated-names",
+    "replace special symbols in compiler generated names");
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index ecdcc73d61ec1f..412435fec4ad1d 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -35,6 +35,7 @@ add_flang_library(flangFrontend
   FIRSupport
   FIRBuilder
   FIRCodeGen
+  FIRPasses
   FIRTransforms
   HLFIRDialect
   HLFIRTransforms
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 267c3ceb44f33e..4a52edc436e0ed 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -21,6 +21,7 @@
 #include "flang/Lower/Support/Verifier.h"
 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 #include "flang/Optimizer/Support/DataLayout.h"
 #include "flang/Optimizer/Support/InitFIR.h"
 #include "flang/Optimizer/Support/Utils.h"
@@ -77,8 +78,6 @@
 #include <memory>
 #include <system_error>
 
-#include "flang/Tools/CLOptions.inc"
-
 namespace llvm {
 extern cl::opt<bool> PrintPipelinePasses;
 } // namespace llvm
diff --git a/flang/lib/Optimizer/CMakeLists.txt b/flang/lib/Optimizer/CMakeLists.txt
index dd153ac33c0fbb..5354d7181e6516 100644
--- a/flang/lib/Optimizer/CMakeLists.txt
+++ b/flang/lib/Optimizer/CMakeLists.txt
@@ -1,8 +1,9 @@
+add_subdirectory(Analysis)
 add_subdirectory(Builder)
 add_subdirectory(CodeGen)
 add_subdirectory(Dialect)
 add_subdirectory(HLFIR)
+add_subdirectory(OpenMP)
+add_subdirectory(Passes)
 add_subdirectory(Support)
 add_subdirectory(Transforms)
-add_subdirectory(Analysis)
-add_subdirectory(OpenMP)
diff --git a/flang/lib/Optimizer/Passes/CMakeLists.txt b/flang/lib/Optimizer/Passes/CMakeLists.txt
new file mode 100644
index 00000000000000..b40885572b4c81
--- /dev/null
+++ b/flang/lib/Optimizer/Passes/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_flang_library(FIRPasses
+  Pipelines.cpp
+
+  DEPENDS
+  FortranCommon
+
+  LINK_LIBS
+  FIRCodeGen
+  FIRTransforms
+  FlangOpenMPTransforms
+  FortranCommon
+  HLFIRTransforms
+  MLIRPass
+  MLIRReconcileUnrealizedCasts
+  MLIRSCFToControlFlow
+  MLIRSupport
+  MLIRTransforms
+
+  LINK_COMPONENTS
+  Passes
+)
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
new file mode 100644
index 00000000000000..722c0db357281c
--- /dev/null
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -0,0 +1,330 @@
+//===-- Pipelines.cpp -- FIR pass pipelines ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/// This file defines some utilties to setup FIR pass pipelines. These are
+/// common to flang and the test tools.
+
+#include "flang/Optimizer/Passes/Pipelines.h"
+
+namespace {
+
+static void addNestedPassToAllTopLevelOperations(mlir::PassManager &pm,
+                                                 PassConstructor ctor) {
+  addNestedPassToOps<mlir::func::FuncOp, mlir::omp::DeclareReductionOp,
+                     mlir::omp::PrivateClauseOp, fir::GlobalOp>(pm, ctor);
+}
+
+static void
+addNestedPassToAllTopLevelOperationsConditionally(mlir::PassManager &pm,
+                                                  llvm::cl::opt<bool> &disabled,
+                                                  PassConstructor ctor) {
+  if (!disabled)
+    addNestedPassToAllTopLevelOperations(pm, ctor);
+}
+
+} // namespace
+
+namespace fir {
+
+// Add MLIR Canonicalizer pass with region simplification disabled.
+// FIR does not support the promotion of some SSA value to block arguments (or
+// into arith.select operands) that may be done by mlir block merging in the
+// region simplification (e.g., !fir.shape<> SSA values are not supported as
+// block arguments).
+// Aside from the fir.shape issue, moving some abstract SSA value into block
+// arguments may have a heavy cost since it forces their code generation that
+// may be expensive (array temporary). The MLIR pass does not take these
+// extra costs into account when doing block merging.
+static void
+addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm) {
+  mlir::GreedyRewriteConfig config;
+  config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
+  pm.addPass(mlir::createCanonicalizerPass(config));
+}
+
+static void addCfgConversionPass(mlir::PassManager &pm,
+                                 const MLIRToLLVMPassPipelineConfig &config) {
+  if (config.NSWOnLoopVarInc)
+    addNestedPassToAllTopLevelOperationsConditionally(
+        pm, disableCfgConversion, fir::createCFGConversionPassWithNSW);
+  else
+    addNestedPassToAllTopLevelOperationsConditionally(pm, disableCfgConversion,
+                                                      fir::createCFGConversion);
+}
+
+static void addAVC(mlir::PassManager &pm,
+                   const llvm::OptimizationLevel &optLevel) {
+  ArrayValueCopyOptions options;
+  options.optimizeConflicts = optLevel.isOptimizingForSpeed();
+  addNestedPassConditionally<mlir::func::FuncOp>(
+      pm, disableFirAvc, [&]() { return createArrayValueCopyPass(options); });
+}
+
+static void addMemoryAllocationOpt(mlir::PassManager &pm) {
+  addNestedPassConditionally<mlir::func::FuncOp>(pm, disableFirMao, [&]() {
+    return fir::createMemoryAllocationOpt(
+        {dynamicArrayStackToHeapAllocation, arrayStackAllocationThreshold});
+  });
+}
+
+static void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) {
+  fir::CodeGenRewriteOptions options;
+  options.preserveDeclare = preserveDeclare;
+  addPassConditionally(pm, disableCodeGenRewrite,
+                       [&]() { return fir::createCodeGenRewrite(options); });
+}
+
+static void addTargetRewritePass(mlir::PassManager &pm) {
+  addPassConditionally(pm, disableTargetRewrite,
+                       []() { return fir::createTargetRewritePass(); });
+}
+
+static mlir::LLVM::DIEmissionKind
+getEmissionKind(llvm::codegenoptions::DebugInfoKind kind) {
+  switch (kind) {
+  case llvm::codegenoptions::DebugInfoKind::FullDebugInfo:
+    return mlir::LLVM::DIEmissionKind::Full;
+  case llvm::codegenoptions::DebugInfoKind::DebugLineTablesOnly:
+    return mlir::LLVM::DIEmissionKind::LineTablesOnly;
+  default:
+    return mlir::LLVM::DIEmissionKind::None;
+  }
+}
+
+void addDebugInfoPass(mlir::PassManager &pm,
+                      llvm::codegenoptions::DebugInfoKind debugLevel,
+                      llvm::OptimizationLevel optLevel,
+                      llvm::StringRef inputFilename) {
+  fir::AddDebugInfoOptions options;
+  options.debugLevel = getEmissionKind(debugLevel);
+  options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
+  options.inputFilename = inputFilename;
+  addPassConditionally(pm, disableDebugInfo,
+                       [&]() { return fir::createAddDebugInfoPass(options); });
+}
+
+void addFIRToLLVMPass(mlir::PassManager &pm,
+                      const MLIRToLLVMPassPipelineConfig &config) {
+  fir::FIRToLLVMPassOptions options;
+  options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
+  options.applyTBAA = config.AliasAnalysis;
+  options.forceUnifiedTBAATree = useOldAliasTags;
+  options.typeDescriptorsRenamedForAssembly =
+      !disableCompilerGeneratedNamesConversion;
+  addPassConditionally(pm, disableFirToLlvmIr,
+                       [&]() { return fir::createFIRToLLVMPass(options); });
+  // The dialect conversion framework may leave dead unrealized_conversion_cast
+  // ops behind, so run reconcile-unrealized-casts to clean them up.
+  addPassConditionally(pm, disableFirToLlvmIr, [&]() {
+    return mlir::createReconcileUnrealizedCastsPass();
+  });
+}
+
+void addLLVMDialectToLLVMPass(mlir::PassManager &pm,
+                              llvm::raw_ostream &output) {
+  addPassConditionally(pm, disableLlvmIrToLlvm, [&]() {
+    return fir::createLLVMDialectToLLVMPass(output);
+  });
+}
+
+static void addBoxedProcedurePass(mlir::PassManager &pm) {
+  addPassConditionally(pm, disableBoxedProcedureRewrite,
+                       [&]() { return fir::createBoxedProcedurePass(); });
+}
+
+static void addExternalNameConversionPass(mlir::PassManager &pm,
+                                          bool appendUnderscore = true) {
+  addPassConditionally(pm, disableExternalNameConversion, [&]() {
+    return fir::createExternalNameConversion({appendUnderscore});
+  });
+}
+
+static void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm) {
+  addPassConditionally(pm, disableCompilerGeneratedNamesConversion, [&]() {
+    return fir::createCompilerGeneratedNamesConversion();
+  });
+}
+
+// Use inliner extension point callback to register the default inliner pass.
+void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config) {
+  config.registerFIRInlinerCallback(
+      [](mlir::PassManager &pm, llvm::OptimizationLevel level) {
+        llvm::StringMap<mlir::OpPassManager> pipelines;
+        // The default inliner pass adds the canonicalizer pass with the default
+        // configuration.
+        pm.addPass(mlir::createInlinerPass(
+            pipelines, addCanonicalizerPassWithoutRegionSimplification));
+      });
+}
+
+/// Create a pass pipeline for running default optimization passes for
+/// incremental conversion of FIR.
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
+                                           MLIRToLLVMPassPipelineConfig &pc) {
+  // Early Optimizer EP Callback
+  pc.invokeFIROptEarlyEPCallbacks(pm, pc.OptLevel);
+
+  // simplify the IR
+  mlir::GreedyRewriteConfig config;
+  config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
+  pm.addPass(mlir::createCSEPass());
+  fir::addAVC(pm, pc.OptLevel);
+  addNestedPassToAllTopLevelOperations(pm, fir::createCharacterConversion);
+  pm.addPass(mlir::createCanonicalizerPass(config));
+  pm.addPass(fir::createSimplifyRegionLite());
+  if (pc.OptLevel.isOptimizingForSpeed()) {
+    // These passes may increase code size.
+    pm.addPass(fir::createSimplifyIntrinsics());
+    pm.addPass(fir::createAlgebraicSimplificationPass(config));
+    if (enableConstantArgumentGlobalisation)
+      pm.addPass(fir::createConstantArgumentGlobalisationOpt());
+  }
+
+  if (pc.LoopVersioning)
+    pm.addPass(fir::createLoopVersioning());
+
+  pm.addPass(mlir::createCSEPass());
+
+  if (pc.StackArrays)
+    pm.addPass(fir::createStackArrays());
+  else
+    fir::addMemoryAllocationOpt(pm);
+
+  // FIR Inliner Callback
+  pc.invokeFIRInlinerCallback(pm, pc.OptLevel);
+
+  pm.addPass(fir::createSimplifyRegionLite());
+  pm.addPass(mlir::createCSEPass());
+
+  // Polymorphic types
+  pm.addPass(fir::createPolymorphicOpConversion());
+  pm.addPass(fir::createAssumedRankOpConversion());
+
+  if (pc.AliasAnalysis && !disableFirAliasTags && !useOldAliasTags)
+    pm.addPass(fir::createAddAliasTags());
+
+  addNestedPassToAllTopLevelOperations(pm, fir::createStackReclaim);
+  // convert control flow to CFG form
+  fir::addCfgConversionPass(pm, pc);
+  pm.addPass(mlir::createConvertSCFToCFPass());
+
+  pm.addPass(mlir::createCanonicalizerPass(config));
+  pm.addPass(fir::createSimplifyRegionLite());
+  pm.addPass(mlir::createCSEPass());
+
+  // Last Optimizer EP Callback
+  pc.invokeFIROptLastEPCallbacks(pm, pc.OptLevel);
+}
+
+/// Create a pass pipeline for lowering from HLFIR to FIR
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+/// \param optLevel - optimization level used for creating FIR optimization
+///   passes pipeline
+void createHLFIRToFIRPassPipeline(mlir::PassManager &pm,
+                                  llvm::OptimizationLevel optLevel) {
+  if (optLevel.isOptimizingForSpeed()) {
+    addCanonicalizerPassWithoutRegionSimplification(pm);
+    addNestedPassToAllTopLevelOperations(pm,
+                                         hlfir::createSimplifyHLFIRIntrinsics);
+  }
+  addNestedPassToAllTopLevelOperations(pm, hlfir::createInlineElementals);
+  if (optLevel.isOptimizingForSpeed()) {
+    addCanonicalizerPassWithoutRegionSimplification(pm);
+    pm.addPass(mlir::createCSEPass());
+    addNestedPassToAllTopLevelOperations(pm,
+                                         hlfir::createOptimizedBufferization);
+  }
+  pm.addPass(hlfir::createLowerHLFIROrderedAssignments());
+  pm.addPass(hlfir::createLowerHLFIRIntrinsics());
+  pm.addPass(hlfir::createBufferizeHLFIR());
+  pm.addPass(hlfir::createConvertHLFIRtoFIR());
+}
+
+/// Create a pass pipeline for handling certain OpenMP transformations needed
+/// prior to FIR lowering.
+///
+/// WARNING: These passes must be run immediately after the lowering to ensure
+/// that the FIR is correct with respect to OpenMP operations/attributes.
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition.
+/// \param isTargetDevice - Whether code is being generated for a target device
+/// rather than the host device.
+void createOpenMPFIRPassPipeline(mlir::PassManager &pm, bool isTargetDevice) {
+  pm.addPass(flangomp::createMapInfoFinalizationPass());
+  pm.addPass(flangomp::createMarkDeclareTargetPass());
+  if (isTargetDevice)
+    pm.addPass(flangomp::createFunctionFilteringPass());
+}
+
+void createDebugPasses(mlir::PassManager &pm,
+                       llvm::codegenoptions::DebugInfoKind debugLevel,
+                       llvm::OptimizationLevel OptLevel,
+                       llvm::StringRef inputFilename) {
+  if (debugLevel != llvm::codegenoptions::NoDebugInfo)
+    addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename);
+}
+
+void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
+                                         MLIRToLLVMPassPipelineConfig config,
+                                         llvm::StringRef inputFilename) {
+  fir::addBoxedProcedurePass(pm);
+  addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt);
+  fir::addCodeGenRewritePass(
+      pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
+  fir::addTargetRewritePass(pm);
+  fir::addCompilerGeneratedNamesConversionPass(pm);
+  fir::addExternalNameConversionPass(pm, config.Underscoring);
+  fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);
+
+  if (config.VScaleMin != 0)
+    pm.addPass(fir::createVScaleAttr({{config.VScaleMin, config.VScaleMax}}));
+
+  // Add function attributes
+  mlir::LLVM::framePointerKind::FramePointerKind framePointerKind;
+
+  if (config.FramePointerKind != llvm::FramePointerKind::None ||
+      config.NoInfsFPMath || config.NoNaNsFPMath || config.ApproxFuncFPMath ||
+      config.NoSignedZerosFPMath || config.UnsafeFPMath) {
+    if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf)
+      framePointerKind =
+          mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf;
+    else if (config.FramePointerKind == llvm::FramePointerKind::All)
+      framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::All;
+    else
+      framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::None;
+
+    pm.addPass(fir::createFunctionAttr(
+        {framePointerKind, config.NoInfsFPMath, config.NoNaNsFPMath,
+         config.ApproxFuncFPMath, config.NoSignedZerosFPMath,
+         config.UnsafeFPMath}));
+  }
+
+  fir::addFIRToLLVMPass(pm, config);
+}
+
+/// Create a pass pipeline for lowering from MLIR to LLVM IR
+///
+/// \param pm - MLIR pass manager that will hold the pipeline definition
+/// \param optLevel - optimization level used for creating FIR optimization
+///   passes pipeline
+void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
+                                  MLIRToLLVMPassPipelineConfig &config,
+                                  llvm::StringRef inputFilename) {
+  fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel);
+
+  // Add default optimizer pass pipeline.
+  fir::createDefaultFIROptimizerPassPipeline(pm, config);
+
+  // Add codegen pass pipeline.
+  fir::createDefaultFIRCodeGenPassPipeline(pm, config, inputFilename);
+}
+
+} // namespace fir
diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt
index 69316d4dc61de3..178745bbb24617 100644
--- a/flang/tools/bbc/CMakeLists.txt
+++ b/flang/tools/bbc/CMakeLists.txt
@@ -20,6 +20,7 @@ CUFAttrs
 CUFDialect
 FIRDialect
 FIRDialectSupport
+FIRPasses
 FIRSupport
 FIRTransforms
 FIRBuilder
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index dcff4503f16571..19d18001c5e1ec 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -233,7 +233,8 @@ static llvm::cl::opt<bool>
            llvm::cl::init(false));
 
 #define FLANG_EXCLUDE_CODEGEN
-#include "flang/Tools/CLOptions.inc"
+#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 
 //===----------------------------------------------------------------------===//
 
diff --git a/flang/tools/tco/CMakeLists.txt b/flang/tools/tco/CMakeLists.txt
index 698a398547c773..8abd3740f3e5bd 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -12,12 +12,14 @@ target_link_libraries(tco PRIVATE
   FIRCodeGen
   FIRDialect
   FIRDialectSupport
+  FIRPasses
   FIRSupport
   FIRTransforms
   FIRBuilder
   HLFIRDialect
   HLFIRTransforms
   FlangOpenMPTransforms
+  FortranCommon
   ${dialect_libs}
   ${extension_libs}
   MLIRIR
diff --git a/flang/tools/tco/tco.cpp b/flang/tools/tco/tco.cpp
index a8c64333109aeb..2b6e240e483b25 100644
--- a/flang/tools/tco/tco.cpp
+++ b/flang/tools/tco/tco.cpp
@@ -70,7 +70,8 @@ static cl::opt<bool> codeGenLLVM(
     cl::desc("Run only CodeGen passes and translate FIR to LLVM IR"),
     cl::init(false));
 
-#include "flang/Tools/CLOptions.inc"
+#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 
 static void printModule(mlir::ModuleOp mod, raw_ostream &output) {
   output << mod << '\n';

>From 2b6ee2140e2d325d294a843531fe447c14571bea Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu at gmail.com>
Date: Wed, 25 Sep 2024 09:26:15 -0600
Subject: [PATCH 2/4] Address reviewer comments.

Move CommandLineOpts from flang/Common to flang/Optimizer/Passes
Rename the library to flangPasses from FIRPasses.
Expose the API from namespace fir that was available with the old CLOptions.inc
file.
Fix indentation in CMakeLists.txt.
---
 .../Passes}/CommandLineOpts.h                 |  8 +--
 .../flang/Optimizer/Passes/Pipelines.h        | 34 +++++++++++-
 flang/lib/Common/CMakeLists.txt               |  2 -
 flang/lib/Frontend/CMakeLists.txt             |  2 +-
 flang/lib/Optimizer/Passes/CMakeLists.txt     |  3 +-
 .../Passes}/CommandLineOpts.cpp               |  2 +-
 flang/lib/Optimizer/Passes/Pipelines.cpp      | 35 +++++-------
 flang/tools/bbc/CMakeLists.txt                | 54 +++++++++----------
 flang/tools/bbc/bbc.cpp                       |  2 +-
 flang/tools/tco/CMakeLists.txt                |  2 +-
 flang/tools/tco/tco.cpp                       |  2 +-
 11 files changed, 83 insertions(+), 63 deletions(-)
 rename flang/include/flang/{Common => Optimizer/Passes}/CommandLineOpts.h (91%)
 rename flang/lib/{Common => Optimizer/Passes}/CommandLineOpts.cpp (98%)

diff --git a/flang/include/flang/Common/CommandLineOpts.h b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
similarity index 91%
rename from flang/include/flang/Common/CommandLineOpts.h
rename to flang/include/flang/Optimizer/Passes/CommandLineOpts.h
index 72674b2b809c24..1cfaf285e75e64 100644
--- a/flang/include/flang/Common/CommandLineOpts.h
+++ b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
@@ -1,4 +1,4 @@
-//===-- CommandLineOptions.h -- shared command line options -----*- C++ -*-===//
+//===-- CommandLineOpts.h -- shared command line options --------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,8 +9,8 @@
 /// This file declares some shared command-line options that can be used when
 /// debugging the test tools.
 
-#ifndef FORTRAN_COMMON_COMMANDLINEOPTS_H
-#define FORTRAN_COMMON_COMMANDLINEOPTS_H
+#ifndef FORTRAN_OPTIMIZER_PASSES_COMMANDLINEOPTS_H
+#define FORTRAN_OPTIMIZER_PASSES_COMMANDLINEOPTS_H
 
 #include "llvm/Frontend/Debug/Options.h"
 #include "llvm/Passes/OptimizationLevel.h"
@@ -57,4 +57,4 @@ extern llvm::cl::opt<bool> disableExternalNameConversion;
 extern llvm::cl::opt<bool> enableConstantArgumentGlobalisation;
 extern llvm::cl::opt<bool> disableCompilerGeneratedNamesConversion;
 
-#endif // FORTRAN_COMMON_COMMANDLINE_OPTS_H
+#endif // FORTRAN_OPTIMIZER_PASSES_COMMANDLINE_OPTS_H
diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
index 8980bfbb90e9a0..4214b594723329 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -12,10 +12,10 @@
 #ifndef FORTRAN_OPTIMIZER_PASSES_PIPELINES_H
 #define FORTRAN_OPTIMIZER_PASSES_PIPELINES_H
 
-#include "flang/Common/CommandLineOpts.h"
 #include "flang/Optimizer/CodeGen/CodeGen.h"
 #include "flang/Optimizer/HLFIR/Passes.h"
 #include "flang/Optimizer/OpenMP/Passes.h"
+#include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 #include "flang/Tools/CrossToolHelpers.h"
 #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
@@ -63,6 +63,38 @@ void addNestedPassConditionally(mlir::PassManager &pm,
 
 namespace fir {
 
+/// Add MLIR Canonicalizer pass with region simplification disabled.
+/// FIR does not support the promotion of some SSA value to block arguments (or
+/// into arith.select operands) that may be done by mlir block merging in the
+/// region simplification (e.g., !fir.shape<> SSA values are not supported as
+/// block arguments).
+/// Aside from the fir.shape issue, moving some abstract SSA value into block
+/// arguments may have a heavy cost since it forces their code generation that
+/// may be expensive (array temporary). The MLIR pass does not take these
+/// extra costs into account when doing block merging.
+void addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm);
+
+void addCfgConversionPass(mlir::PassManager &pm,
+                          const MLIRToLLVMPassPipelineConfig &config);
+
+void addAVC(mlir::PassManager &pm, const llvm::OptimizationLevel &optLevel);
+
+void addMemoryAllocationOpt(mlir::PassManager &pm);
+
+void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare);
+
+void addTargetRewritePass(mlir::PassManager &pm);
+
+mlir::LLVM::DIEmissionKind
+getEmissionKind(llvm::codegenoptions::DebugInfoKind kind);
+
+void addBoxedProcedurePass(mlir::PassManager &pm);
+
+void addExternalNameConversionPass(mlir::PassManager &pm,
+                                   bool appendUnderscore = true);
+
+void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm);
+
 void addDebugInfoPass(mlir::PassManager &pm,
                       llvm::codegenoptions::DebugInfoKind debugLevel,
                       llvm::OptimizationLevel optLevel,
diff --git a/flang/lib/Common/CMakeLists.txt b/flang/lib/Common/CMakeLists.txt
index 6e5bdfa2f6236b..6579e9cdf82491 100644
--- a/flang/lib/Common/CMakeLists.txt
+++ b/flang/lib/Common/CMakeLists.txt
@@ -35,7 +35,6 @@ if(FLANG_VENDOR)
 endif()
 
 add_flang_library(FortranCommon
-  CommandLineOpts.cpp
   Fortran.cpp
   Fortran-features.cpp
   default-kinds.cpp
@@ -44,6 +43,5 @@ add_flang_library(FortranCommon
   ${version_inc}
 
   LINK_COMPONENTS
-  Passes
   Support
 )
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 412435fec4ad1d..ebfdb14b534bb4 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -35,10 +35,10 @@ add_flang_library(flangFrontend
   FIRSupport
   FIRBuilder
   FIRCodeGen
-  FIRPasses
   FIRTransforms
   HLFIRDialect
   HLFIRTransforms
+  flangPasses
   FlangOpenMPTransforms
   MLIRTransforms
   MLIRBuiltinToLLVMIRTranslation
diff --git a/flang/lib/Optimizer/Passes/CMakeLists.txt b/flang/lib/Optimizer/Passes/CMakeLists.txt
index b40885572b4c81..3df988940e005f 100644
--- a/flang/lib/Optimizer/Passes/CMakeLists.txt
+++ b/flang/lib/Optimizer/Passes/CMakeLists.txt
@@ -1,4 +1,5 @@
-add_flang_library(FIRPasses
+add_flang_library(flangPasses
+  CommandLineOpts.cpp
   Pipelines.cpp
 
   DEPENDS
diff --git a/flang/lib/Common/CommandLineOpts.cpp b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
similarity index 98%
rename from flang/lib/Common/CommandLineOpts.cpp
rename to flang/lib/Optimizer/Passes/CommandLineOpts.cpp
index f77863bd77525d..a01b039c27e602 100644
--- a/flang/lib/Common/CommandLineOpts.cpp
+++ b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
@@ -9,7 +9,7 @@
 /// This file defines some shared command-line options that can be used when
 /// debugging the test tools.
 
-#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/CommandLineOpts.h"
 
 using namespace llvm;
 
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 722c0db357281c..21c2f4874e49f3 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -31,24 +31,14 @@ addNestedPassToAllTopLevelOperationsConditionally(mlir::PassManager &pm,
 
 namespace fir {
 
-// Add MLIR Canonicalizer pass with region simplification disabled.
-// FIR does not support the promotion of some SSA value to block arguments (or
-// into arith.select operands) that may be done by mlir block merging in the
-// region simplification (e.g., !fir.shape<> SSA values are not supported as
-// block arguments).
-// Aside from the fir.shape issue, moving some abstract SSA value into block
-// arguments may have a heavy cost since it forces their code generation that
-// may be expensive (array temporary). The MLIR pass does not take these
-// extra costs into account when doing block merging.
-static void
-addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm) {
+void addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm) {
   mlir::GreedyRewriteConfig config;
   config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
   pm.addPass(mlir::createCanonicalizerPass(config));
 }
 
-static void addCfgConversionPass(mlir::PassManager &pm,
-                                 const MLIRToLLVMPassPipelineConfig &config) {
+void addCfgConversionPass(mlir::PassManager &pm,
+                          const MLIRToLLVMPassPipelineConfig &config) {
   if (config.NSWOnLoopVarInc)
     addNestedPassToAllTopLevelOperationsConditionally(
         pm, disableCfgConversion, fir::createCFGConversionPassWithNSW);
@@ -57,34 +47,33 @@ static void addCfgConversionPass(mlir::PassManager &pm,
                                                       fir::createCFGConversion);
 }
 
-static void addAVC(mlir::PassManager &pm,
-                   const llvm::OptimizationLevel &optLevel) {
+void addAVC(mlir::PassManager &pm, const llvm::OptimizationLevel &optLevel) {
   ArrayValueCopyOptions options;
   options.optimizeConflicts = optLevel.isOptimizingForSpeed();
   addNestedPassConditionally<mlir::func::FuncOp>(
       pm, disableFirAvc, [&]() { return createArrayValueCopyPass(options); });
 }
 
-static void addMemoryAllocationOpt(mlir::PassManager &pm) {
+void addMemoryAllocationOpt(mlir::PassManager &pm) {
   addNestedPassConditionally<mlir::func::FuncOp>(pm, disableFirMao, [&]() {
     return fir::createMemoryAllocationOpt(
         {dynamicArrayStackToHeapAllocation, arrayStackAllocationThreshold});
   });
 }
 
-static void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) {
+void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) {
   fir::CodeGenRewriteOptions options;
   options.preserveDeclare = preserveDeclare;
   addPassConditionally(pm, disableCodeGenRewrite,
                        [&]() { return fir::createCodeGenRewrite(options); });
 }
 
-static void addTargetRewritePass(mlir::PassManager &pm) {
+void addTargetRewritePass(mlir::PassManager &pm) {
   addPassConditionally(pm, disableTargetRewrite,
                        []() { return fir::createTargetRewritePass(); });
 }
 
-static mlir::LLVM::DIEmissionKind
+mlir::LLVM::DIEmissionKind
 getEmissionKind(llvm::codegenoptions::DebugInfoKind kind) {
   switch (kind) {
   case llvm::codegenoptions::DebugInfoKind::FullDebugInfo:
@@ -132,19 +121,19 @@ void addLLVMDialectToLLVMPass(mlir::PassManager &pm,
   });
 }
 
-static void addBoxedProcedurePass(mlir::PassManager &pm) {
+void addBoxedProcedurePass(mlir::PassManager &pm) {
   addPassConditionally(pm, disableBoxedProcedureRewrite,
                        [&]() { return fir::createBoxedProcedurePass(); });
 }
 
-static void addExternalNameConversionPass(mlir::PassManager &pm,
-                                          bool appendUnderscore = true) {
+void addExternalNameConversionPass(mlir::PassManager &pm,
+                                          bool appendUnderscore) {
   addPassConditionally(pm, disableExternalNameConversion, [&]() {
     return fir::createExternalNameConversion({appendUnderscore});
   });
 }
 
-static void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm) {
+void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm) {
   addPassConditionally(pm, disableCompilerGeneratedNamesConversion, [&]() {
     return fir::createCompilerGeneratedNamesConversion();
   });
diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt
index 178745bbb24617..18fa7ac1d6cdc9 100644
--- a/flang/tools/bbc/CMakeLists.txt
+++ b/flang/tools/bbc/CMakeLists.txt
@@ -1,14 +1,14 @@
 set(LLVM_LINK_COMPONENTS
-Passes
-AllTargetsCodeGens
-AllTargetsDescs
-AllTargetsInfos
-TargetParser
+  Passes
+  AllTargetsCodeGens
+  AllTargetsDescs
+  AllTargetsInfos
+  TargetParser
 )
 
 add_flang_tool(bbc bbc.cpp
-DEPENDS
-FIROptCodeGenPassIncGen
+  DEPENDS
+  FIROptCodeGenPassIncGen
 )
 
 llvm_update_compile_flags(bbc)
@@ -16,24 +16,24 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
 get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
 
 target_link_libraries(bbc PRIVATE
-CUFAttrs
-CUFDialect
-FIRDialect
-FIRDialectSupport
-FIRPasses
-FIRSupport
-FIRTransforms
-FIRBuilder
-HLFIRDialect
-HLFIRTransforms
-FlangOpenMPTransforms
-${dialect_libs}
-${extension_libs}
-MLIRAffineToStandard
-MLIRSCFToControlFlow
-FortranCommon
-FortranParser
-FortranEvaluate
-FortranSemantics
-FortranLower
+  CUFAttrs
+  CUFDialect
+  FIRDialect
+  FIRDialectSupport
+  FIRSupport
+  FIRTransforms
+  FIRBuilder
+  HLFIRDialect
+  HLFIRTransforms
+  flangPasses
+  FlangOpenMPTransforms
+  ${dialect_libs}
+  ${extension_libs}
+  MLIRAffineToStandard
+  MLIRSCFToControlFlow
+  FortranCommon
+  FortranParser
+  FortranEvaluate
+  FortranSemantics
+  FortranLower
 )
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 19d18001c5e1ec..ac3de35319106f 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -233,7 +233,7 @@ static llvm::cl::opt<bool>
            llvm::cl::init(false));
 
 #define FLANG_EXCLUDE_CODEGEN
-#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Passes/Pipelines.h"
 
 //===----------------------------------------------------------------------===//
diff --git a/flang/tools/tco/CMakeLists.txt b/flang/tools/tco/CMakeLists.txt
index 8abd3740f3e5bd..aac80437ee11d9 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -12,12 +12,12 @@ target_link_libraries(tco PRIVATE
   FIRCodeGen
   FIRDialect
   FIRDialectSupport
-  FIRPasses
   FIRSupport
   FIRTransforms
   FIRBuilder
   HLFIRDialect
   HLFIRTransforms
+  flangPasses
   FlangOpenMPTransforms
   FortranCommon
   ${dialect_libs}
diff --git a/flang/tools/tco/tco.cpp b/flang/tools/tco/tco.cpp
index 2b6e240e483b25..5c373c4e85258c 100644
--- a/flang/tools/tco/tco.cpp
+++ b/flang/tools/tco/tco.cpp
@@ -70,7 +70,7 @@ static cl::opt<bool> codeGenLLVM(
     cl::desc("Run only CodeGen passes and translate FIR to LLVM IR"),
     cl::init(false));
 
-#include "flang/Common/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Passes/Pipelines.h"
 
 static void printModule(mlir::ModuleOp mod, raw_ostream &output) {

>From a33d57007a010e4de1cc5a8164ea00b6ddef5a5b Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu at gmail.com>
Date: Wed, 25 Sep 2024 09:56:34 -0600
Subject: [PATCH 3/4] Run clang-format

---
 .../lib/Optimizer/Passes/CommandLineOpts.cpp  | 38 +++++++++++--------
 flang/lib/Optimizer/Passes/Pipelines.cpp      |  2 +-
 2 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
index a01b039c27e602..f95a280883cbaf 100644
--- a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
+++ b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
@@ -13,23 +13,28 @@
 
 using namespace llvm;
 
-#define DisableOption(DOName, DOOption, DODescription) \
-  cl::opt<bool> disable##DOName("disable-" DOOption, \
-      cl::desc("disable " DODescription " pass"), cl::init(false), cl::Hidden)
-#define EnableOption(EOName, EOOption, EODescription) \
-  cl::opt<bool> enable##EOName("enable-" EOOption, \
-      cl::desc("enable " EODescription " pass"), cl::init(false), cl::Hidden)
+#define DisableOption(DOName, DOOption, DODescription)                         \
+  cl::opt<bool> disable##DOName("disable-" DOOption,                           \
+                                cl::desc("disable " DODescription " pass"),    \
+                                cl::init(false), cl::Hidden)
+#define EnableOption(EOName, EOOption, EODescription)                          \
+  cl::opt<bool> enable##EOName("enable-" EOOption,                             \
+                               cl::desc("enable " EODescription " pass"),      \
+                               cl::init(false), cl::Hidden)
 
-cl::opt<bool> dynamicArrayStackToHeapAllocation("fdynamic-heap-array",
+cl::opt<bool> dynamicArrayStackToHeapAllocation(
+    "fdynamic-heap-array",
     cl::desc("place all array allocations of dynamic size on the heap"),
     cl::init(false), cl::Hidden);
 
-cl::opt<std::size_t> arrayStackAllocationThreshold("fstack-array-size",
+cl::opt<std::size_t> arrayStackAllocationThreshold(
+    "fstack-array-size",
     cl::desc(
         "place all array allocations more than <size> elements on the heap"),
     cl::init(~static_cast<std::size_t>(0)), cl::Hidden);
 
-cl::opt<bool> ignoreMissingTypeDescriptors("ignore-missing-type-desc",
+cl::opt<bool> ignoreMissingTypeDescriptors(
+    "ignore-missing-type-desc",
     cl::desc("ignore failures to find derived type descriptors when "
              "translating FIR to LLVM"),
     cl::init(false), cl::Hidden);
@@ -41,11 +46,12 @@ codegenoptions::DebugInfoKind noDebugInfo{codegenoptions::NoDebugInfo};
 /// Optimizer Passes
 DisableOption(CfgConversion, "cfg-conversion", "disable FIR to CFG pass");
 DisableOption(FirAvc, "avc", "array value copy analysis and transformation");
-DisableOption(
-    FirMao, "memory-allocation-opt", "memory allocation optimization");
+DisableOption(FirMao, "memory-allocation-opt",
+              "memory allocation optimization");
 
 DisableOption(FirAliasTags, "fir-alias-tags", "fir alias analysis");
-cl::opt<bool> useOldAliasTags("use-old-alias-tags",
+cl::opt<bool> useOldAliasTags(
+    "use-old-alias-tags",
     cl::desc("Use a single TBAA tree for all functions and do not use "
              "the FIR alias tags pass"),
     cl::init(false), cl::Hidden);
@@ -57,11 +63,11 @@ DisableOption(DebugInfo, "debug-info", "Add debug info");
 DisableOption(FirToLlvmIr, "fir-to-llvmir", "FIR to LLVM-IR dialect");
 DisableOption(LlvmIrToLlvm, "llvm", "conversion to LLVM");
 DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite",
-    "rewrite boxed procedures");
+              "rewrite boxed procedures");
 
 DisableOption(ExternalNameConversion, "external-name-interop",
-    "convert names with external convention");
+              "convert names with external convention");
 EnableOption(ConstantArgumentGlobalisation, "constant-argument-globalisation",
-    "the local constant argument to global constant conversion");
+             "the local constant argument to global constant conversion");
 DisableOption(CompilerGeneratedNamesConversion, "compiler-generated-names",
-    "replace special symbols in compiler generated names");
+              "replace special symbols in compiler generated names");
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 21c2f4874e49f3..c82bfbc52869e9 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -127,7 +127,7 @@ void addBoxedProcedurePass(mlir::PassManager &pm) {
 }
 
 void addExternalNameConversionPass(mlir::PassManager &pm,
-                                          bool appendUnderscore) {
+                                   bool appendUnderscore) {
   addPassConditionally(pm, disableExternalNameConversion, [&]() {
     return fir::createExternalNameConversion({appendUnderscore});
   });

>From f04fcf6134c250182be3d2bb20579a9181b9aaa6 Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu at gmail.com>
Date: Wed, 25 Sep 2024 11:20:17 -0600
Subject: [PATCH 4/4] Expose the addNestedPassToAll* API's as well. Move those
 into the fir namespace since leaving them in the anonymous namespace may
 result in ODR violations.

---
 .../include/flang/Optimizer/Passes/Pipelines.h  |  8 +++++---
 flang/lib/Optimizer/Passes/Pipelines.cpp        | 17 ++++++-----------
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
index 4214b594723329..3b54ac38838587 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -28,7 +28,7 @@
 #include "llvm/Passes/OptimizationLevel.h"
 #include "llvm/Support/CommandLine.h"
 
-namespace {
+namespace fir {
 
 using PassConstructor = std::unique_ptr<mlir::Pass>();
 
@@ -59,9 +59,11 @@ void addNestedPassConditionally(mlir::PassManager &pm,
     pm.addNestedPass<OP>(ctor());
 }
 
-} // namespace
+void addNestedPassToAllTopLevelOperations(mlir::PassManager &pm,
+                                          PassConstructor ctor);
 
-namespace fir {
+void addNestedPassToAllTopLevelOperationsConditionally(
+    mlir::PassManager &pm, llvm::cl::opt<bool> &disabled, PassConstructor ctor);
 
 /// Add MLIR Canonicalizer pass with region simplification disabled.
 /// FIR does not support the promotion of some SSA value to block arguments (or
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index c82bfbc52869e9..3fa5c54403bd8c 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -11,26 +11,21 @@
 
 #include "flang/Optimizer/Passes/Pipelines.h"
 
-namespace {
+namespace fir {
 
-static void addNestedPassToAllTopLevelOperations(mlir::PassManager &pm,
-                                                 PassConstructor ctor) {
+void addNestedPassToAllTopLevelOperations(mlir::PassManager &pm,
+                                          PassConstructor ctor) {
   addNestedPassToOps<mlir::func::FuncOp, mlir::omp::DeclareReductionOp,
                      mlir::omp::PrivateClauseOp, fir::GlobalOp>(pm, ctor);
 }
 
-static void
-addNestedPassToAllTopLevelOperationsConditionally(mlir::PassManager &pm,
-                                                  llvm::cl::opt<bool> &disabled,
-                                                  PassConstructor ctor) {
+void addNestedPassToAllTopLevelOperationsConditionally(
+    mlir::PassManager &pm, llvm::cl::opt<bool> &disabled,
+    PassConstructor ctor) {
   if (!disabled)
     addNestedPassToAllTopLevelOperations(pm, ctor);
 }
 
-} // namespace
-
-namespace fir {
-
 void addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm) {
   mlir::GreedyRewriteConfig config;
   config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;



More information about the flang-commits mailing list