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

via flang-commits flang-commits at lists.llvm.org
Wed Sep 25 13:04:42 PDT 2024


Author: Tarun Prabhu
Date: 2024-09-25T14:04:38-06:00
New Revision: c3201ddaeac02a2c86a38b75be14be61a8ffcc9e

URL: https://github.com/llvm/llvm-project/commit/c3201ddaeac02a2c86a38b75be14be61a8ffcc9e
DIFF: https://github.com/llvm/llvm-project/commit/c3201ddaeac02a2c86a38b75be14be61a8ffcc9e.diff

LOG: [flang][NFC] Refactor to remove .inc file containing shared code (#109874)

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.

Added: 
    flang/include/flang/Optimizer/Passes/CommandLineOpts.h
    flang/include/flang/Optimizer/Passes/Pipelines.h
    flang/lib/Optimizer/Passes/CMakeLists.txt
    flang/lib/Optimizer/Passes/CommandLineOpts.cpp
    flang/lib/Optimizer/Passes/Pipelines.cpp

Modified: 
    flang/docs/FlangDriver.md
    flang/lib/Common/CMakeLists.txt
    flang/lib/Frontend/CMakeLists.txt
    flang/lib/Frontend/FrontendActions.cpp
    flang/lib/Optimizer/CMakeLists.txt
    flang/tools/bbc/CMakeLists.txt
    flang/tools/bbc/bbc.cpp
    flang/tools/tco/CMakeLists.txt
    flang/tools/tco/tco.cpp

Removed: 
    flang/include/flang/Tools/CLOptions.inc


################################################################################
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 
diff erent points of the default pass pipeline. An example use of these

diff  --git a/flang/include/flang/Optimizer/Passes/CommandLineOpts.h b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
new file mode 100644
index 00000000000000..1cfaf285e75e64
--- /dev/null
+++ b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
@@ -0,0 +1,60 @@
+//===-- 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.
+// 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_OPTIMIZER_PASSES_COMMANDLINEOPTS_H
+#define FORTRAN_OPTIMIZER_PASSES_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_OPTIMIZER_PASSES_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..3b54ac38838587
--- /dev/null
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -0,0 +1,162 @@
+//===-- 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/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"
+#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 fir {
+
+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());
+}
+
+void addNestedPassToAllTopLevelOperations(mlir::PassManager &pm,
+                                          PassConstructor ctor);
+
+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
+/// 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,
+                      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..6579e9cdf82491 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,7 +34,6 @@ if(FLANG_VENDOR)
     PROPERTIES COMPILE_DEFINITIONS "FLANG_VENDOR=\"${FLANG_VENDOR} \"")
 endif()
 
-
 add_flang_library(FortranCommon
   Fortran.cpp
   Fortran-features.cpp

diff  --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index ecdcc73d61ec1f..ebfdb14b534bb4 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -38,6 +38,7 @@ add_flang_library(flangFrontend
   FIRTransforms
   HLFIRDialect
   HLFIRTransforms
+  flangPasses
   FlangOpenMPTransforms
   MLIRTransforms
   MLIRBuiltinToLLVMIRTranslation

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..3df988940e005f
--- /dev/null
+++ b/flang/lib/Optimizer/Passes/CMakeLists.txt
@@ -0,0 +1,22 @@
+add_flang_library(flangPasses
+  CommandLineOpts.cpp
+  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/CommandLineOpts.cpp b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
new file mode 100644
index 00000000000000..f95a280883cbaf
--- /dev/null
+++ b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
@@ -0,0 +1,73 @@
+//===-- 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/Optimizer/Passes/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/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
new file mode 100644
index 00000000000000..3fa5c54403bd8c
--- /dev/null
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -0,0 +1,314 @@
+//===-- 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 fir {
+
+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);
+}
+
+void addCanonicalizerPassWithoutRegionSimplification(mlir::OpPassManager &pm) {
+  mlir::GreedyRewriteConfig config;
+  config.enableRegionSimplification = mlir::GreedySimplifyRegionLevel::Disabled;
+  pm.addPass(mlir::createCanonicalizerPass(config));
+}
+
+void addCfgConversionPass(mlir::PassManager &pm,
+                          const MLIRToLLVMPassPipelineConfig &config) {
+  if (config.NSWOnLoopVarInc)
+    addNestedPassToAllTopLevelOperationsConditionally(
+        pm, disableCfgConversion, fir::createCFGConversionPassWithNSW);
+  else
+    addNestedPassToAllTopLevelOperationsConditionally(pm, disableCfgConversion,
+                                                      fir::createCFGConversion);
+}
+
+void addAVC(mlir::PassManager &pm, const llvm::OptimizationLevel &optLevel) {
+  ArrayValueCopyOptions options;
+  options.optimizeConflicts = optLevel.isOptimizingForSpeed();
+  addNestedPassConditionally<mlir::func::FuncOp>(
+      pm, disableFirAvc, [&]() { return createArrayValueCopyPass(options); });
+}
+
+void addMemoryAllocationOpt(mlir::PassManager &pm) {
+  addNestedPassConditionally<mlir::func::FuncOp>(pm, disableFirMao, [&]() {
+    return fir::createMemoryAllocationOpt(
+        {dynamicArrayStackToHeapAllocation, arrayStackAllocationThreshold});
+  });
+}
+
+void addCodeGenRewritePass(mlir::PassManager &pm, bool preserveDeclare) {
+  fir::CodeGenRewriteOptions options;
+  options.preserveDeclare = preserveDeclare;
+  addPassConditionally(pm, disableCodeGenRewrite,
+                       [&]() { return fir::createCodeGenRewrite(options); });
+}
+
+void addTargetRewritePass(mlir::PassManager &pm) {
+  addPassConditionally(pm, disableTargetRewrite,
+                       []() { return fir::createTargetRewritePass(); });
+}
+
+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);
+  });
+}
+
+void addBoxedProcedurePass(mlir::PassManager &pm) {
+  addPassConditionally(pm, disableBoxedProcedureRewrite,
+                       [&]() { return fir::createBoxedProcedurePass(); });
+}
+
+void addExternalNameConversionPass(mlir::PassManager &pm,
+                                   bool appendUnderscore) {
+  addPassConditionally(pm, disableExternalNameConversion, [&]() {
+    return fir::createExternalNameConversion({appendUnderscore});
+  });
+}
+
+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..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,23 +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
-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 dcff4503f16571..ac3de35319106f 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/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 698a398547c773..aac80437ee11d9 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -17,7 +17,9 @@ target_link_libraries(tco PRIVATE
   FIRBuilder
   HLFIRDialect
   HLFIRTransforms
+  flangPasses
   FlangOpenMPTransforms
+  FortranCommon
   ${dialect_libs}
   ${extension_libs}
   MLIRIR

diff  --git a/flang/tools/tco/tco.cpp b/flang/tools/tco/tco.cpp
index a8c64333109aeb..5c373c4e85258c 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/Optimizer/Passes/CommandLineOpts.h"
+#include "flang/Optimizer/Passes/Pipelines.h"
 
 static void printModule(mlir::ModuleOp mod, raw_ostream &output) {
   output << mod << '\n';


        


More information about the flang-commits mailing list