diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.cpp index dd4ac8b42c70c..2d9ac0e55b5ff 100644 --- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.cpp +++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.cpp @@ -142,55 +142,9 @@ namespace iree_compiler { namespace IREE { namespace Flow { -namespace { - using FunctionLikeNest = MultiOpNest; -// Subset of the overall pass pipeline for optimizing globals and numerics. -// We may ultimately break this out separately so creating a syntactic -// distinction to keep that as an option. -void buildGlobalOptimizationPassPipeline( - OpPassManager &mainPassManager, const TransformOptions &transformOptions) { - OpPassManager pipeline(ModuleOp::getOperationName()); - - FunctionLikeNest(pipeline) - // Simplify util.global accesses early on; this can help with dispatch - // region formation as redundant store-loads are removed. - .addPass(IREE::Util::createSimplifyGlobalAccessesPass); - - // Module level cleanup and canonicalization of util.global (and other util - // ops). - pipeline.addPass(IREE::Util::createApplyPatternsPass()); - pipeline.addPass(IREE::Util::createFoldGlobalsPass()); - pipeline.addPass(IREE::Util::createIPOPass()); - - if (transformOptions.constExprHoisting) { - pipeline.addPass(IREE::Util::createHoistIntoGlobalsPass()); - } - - if (transformOptions.buildConstEvalPassPipeline) { - transformOptions.buildConstEvalPassPipeline(pipeline); - } - - if (transformOptions.numericPrecisionReduction) { - pipeline.addPass(createInferNumericNarrowingPass()); - pipeline.addPass(createOptimizeNumericsPass()); - pipeline.addPass(createCleanupNumericNarrowingPass()); - } - - FunctionLikeNest(pipeline) - .addPass(mlir::createCanonicalizerPass) - .addPass(mlir::createCSEPass); - - // Add the whole fixed point iterator. - mainPassManager.addPass( - IREE::Util::createFixedPointIteratorPass(std::move(pipeline))); -} - -} // namespace - -void buildFlowTransformPassPipeline(OpPassManager &passManager, - const TransformOptions &transformOptions) { +void buildFlowPreprocessingTransformPassPipeline(OpPassManager &passManager) { // ML frontends have very uneven support for user-controlled types _and_ users // tend to use types not well suited for the work they are doing. These // demotions/promotions allow users to change the types after lowering out of @@ -221,15 +175,16 @@ void buildFlowTransformPassPipeline(OpPassManager &passManager, .addPass(IREE::Flow::createConvert1X1FilterConv2DToMatmulPass); passManager.addPass(IREE::Flow::createEraseUnusedLinalgOperands()); - // Start of Flow pipeline, verify input legality. - passManager.addPass(IREE::Flow::createVerifyInputLegalityPass()); - // Expand tensor shapes into SSA values and optimize the whole program. // The more we are able to equate shape dimensions at this level the better // our fusions will be. FunctionLikeNest(passManager).addPass(createTopLevelSCFToCFGPass); passManager.addPass(IREE::Flow::createExpandTensorShapesPass()); - buildGlobalOptimizationPassPipeline(passManager, transformOptions); +} + +void buildFlowTransformPassPipeline(OpPassManager &passManager) { + // Start of Flow pipeline, verify input legality. + passManager.addPass(IREE::Flow::createVerifyInputLegalityPass()); // Transform pad operations into linalg.fill + tensor.insert_slice. // This is a WAR for not having native pad handling. @@ -403,11 +358,11 @@ void buildFlowTransformPassPipeline(OpPassManager &passManager, } void registerFlowTransformPassPipeline() { - PassPipelineRegistration transformPassPipeline( + PassPipelineRegistration<> transformPassPipeline( "iree-flow-transformation-pipeline", "Runs the full IREE flow dialect transformation pipeline", - [](OpPassManager &passManager, const TransformOptions &transformOptions) { - buildFlowTransformPassPipeline(passManager, transformOptions); + [](OpPassManager &passManager) { + buildFlowTransformPassPipeline(passManager); }); } diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.h b/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.h index fa4e58a6a04d6..b460e7a5c2aa0 100644 --- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.h +++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.h @@ -25,20 +25,7 @@ namespace Flow { // Pipelines //===----------------------------------------------------------------------===// -struct TransformOptions : public PassPipelineOptions { - // Enables the iree-util-hoist-into-globals pass. This should eventually - // become the default. - bool constExprHoisting = false; - - // Enables passes to perform numeric precision reduction. - bool numericPrecisionReduction = false; - - // Hook to populate a constant evaluation pass pipeline. If nullptr, then - // no passes are added for constant evaluation. This must be injected in - // because constant-evaluators can depend on the whole compiler, of which - // this is a part, and we maintain strict optionality for this component. - std::function buildConstEvalPassPipeline; -}; +void buildFlowPreprocessingTransformPassPipeline(OpPassManager &passManager); // Adds a set of passes to the given pass manager that run the required flow // transforms in the canonical order. @@ -51,8 +38,7 @@ struct TransformOptions : public PassPipelineOptions { // - Directly passing supported flow plus core ops // buildFlowTransformPassPipeline // -void buildFlowTransformPassPipeline(OpPassManager &passManager, - const TransformOptions &transformOptions); +void buildFlowTransformPassPipeline(OpPassManager &passManager); void registerFlowTransformPassPipeline(); diff --git a/compiler/src/iree/compiler/GlobalOptimization/BUILD.bazel b/compiler/src/iree/compiler/GlobalOptimization/BUILD.bazel new file mode 100644 index 0000000000000..e443ef1d34865 --- /dev/null +++ b/compiler/src/iree/compiler/GlobalOptimization/BUILD.bazel @@ -0,0 +1,33 @@ +# Copyright 2023 The IREE Authors +# +# Licensed 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 + +load("//build_tools/bazel:build_defs.oss.bzl", "iree_compiler_cc_library", "iree_gentbl_cc_library") + +package( + default_visibility = ["//visibility:public"], + features = ["layering_check"], + licenses = ["notice"], # Apache 2.0 +) + +iree_compiler_cc_library( + name = "GlobalOptimization", + srcs = [ + "Passes.cpp", + ], + hdrs = [ + "Passes.h", + ], + deps = [ + "//compiler/src/iree/compiler/Dialect/Flow/Transforms", + "//compiler/src/iree/compiler/Dialect/Util/Transforms", + "//compiler/src/iree/compiler/Utils", + "@llvm-project//llvm:Support", + "@llvm-project//mlir:ArithDialect", + "@llvm-project//mlir:FuncDialect", + "@llvm-project//mlir:IR", + "@llvm-project//mlir:Pass", + ], +) diff --git a/compiler/src/iree/compiler/GlobalOptimization/CMakeLists.txt b/compiler/src/iree/compiler/GlobalOptimization/CMakeLists.txt new file mode 100644 index 0000000000000..4ea0049b7cfb6 --- /dev/null +++ b/compiler/src/iree/compiler/GlobalOptimization/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################################################ +# Autogenerated by build_tools/bazel_to_cmake/bazel_to_cmake.py from # +# compiler/src/iree/compiler/GlobalOptimization/BUILD.bazel # +# # +# Use iree_cmake_extra_content from iree/build_defs.oss.bzl to add arbitrary # +# CMake-only content. # +# # +# To disable autogeneration for this file entirely, delete this header. # +################################################################################ + +iree_add_all_subdirs() + +iree_cc_library( + NAME + GlobalOptimization + HDRS + "Passes.h" + SRCS + "Passes.cpp" + DEPS + LLVMSupport + MLIRArithDialect + MLIRFuncDialect + MLIRIR + MLIRPass + iree::compiler::Dialect::Flow::Transforms + iree::compiler::Dialect::Util::Transforms + iree::compiler::Utils + PUBLIC +) + +### BAZEL_TO_CMAKE_PRESERVES_ALL_CONTENT_BELOW_THIS_LINE ### diff --git a/compiler/src/iree/compiler/GlobalOptimization/Passes.cpp b/compiler/src/iree/compiler/GlobalOptimization/Passes.cpp new file mode 100644 index 0000000000000..184deab8aa52a --- /dev/null +++ b/compiler/src/iree/compiler/GlobalOptimization/Passes.cpp @@ -0,0 +1,60 @@ +// Copyright 2023 The IREE Authors +// +// Licensed 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 + +#include "iree/compiler/GlobalOptimization/Passes.h" +#include "iree/compiler/Dialect/Flow/Transforms/Passes.h" +#include "iree/compiler/Dialect/HAL/Transforms/Passes.h" +#include "iree/compiler/Dialect/Util/Transforms/Passes.h" +#include "iree/compiler/Utils/PassUtils.h" +#include "mlir/Transforms/Passes.h" + +namespace mlir { +namespace iree_compiler { +namespace GlobalOptimization { + +using FunctionLikeNest = MultiOpNest; + +void buildGlobalOptimizationPassPipeline( + OpPassManager &mainPassManager, const TransformOptions &transformOptions) { + OpPassManager pipeline(ModuleOp::getOperationName()); + + FunctionLikeNest(pipeline) + // Simplify util.global accesses early on; this can help with dispatch + // region formation as redundant store-loads are removed. + .addPass(IREE::Util::createSimplifyGlobalAccessesPass); + + // Module level cleanup and canonicalization of util.global (and other util + // ops). + pipeline.addPass(IREE::Util::createApplyPatternsPass()); + pipeline.addPass(IREE::Util::createFoldGlobalsPass()); + pipeline.addPass(IREE::Util::createIPOPass()); + + if (transformOptions.constExprHoisting) { + pipeline.addPass(IREE::Util::createHoistIntoGlobalsPass()); + } + + if (transformOptions.buildConstEvalPassPipeline) { + transformOptions.buildConstEvalPassPipeline(pipeline); + } + + if (transformOptions.numericPrecisionReduction) { + pipeline.addPass(IREE::Flow::createInferNumericNarrowingPass()); + pipeline.addPass(IREE::Flow::createOptimizeNumericsPass()); + pipeline.addPass(IREE::Flow::createCleanupNumericNarrowingPass()); + } + + FunctionLikeNest(pipeline) + .addPass(mlir::createCanonicalizerPass) + .addPass(mlir::createCSEPass); + + // Add the whole fixed point iterator. + mainPassManager.addPass( + IREE::Util::createFixedPointIteratorPass(std::move(pipeline))); +} + +} // namespace GlobalOptimization +} // namespace iree_compiler +} // namespace mlir diff --git a/compiler/src/iree/compiler/GlobalOptimization/Passes.h b/compiler/src/iree/compiler/GlobalOptimization/Passes.h new file mode 100644 index 0000000000000..5245d834f413e --- /dev/null +++ b/compiler/src/iree/compiler/GlobalOptimization/Passes.h @@ -0,0 +1,44 @@ +// Copyright 2023 The IREE Authors +// +// Licensed 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 + +#ifndef IREE_COMPILER_GLOBALOPTIMIZATION_PASSES_H_ +#define IREE_COMPILER_GLOBALOPTIMIZATION_PASSES_H_ + +#include + +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" + +namespace mlir { +namespace iree_compiler { +namespace GlobalOptimization { + +struct TransformOptions : public PassPipelineOptions { + // Enables the iree-util-hoist-into-globals pass. This should eventually + // become the default. + bool constExprHoisting = false; + + // Enables passes to perform numeric precision reduction. + bool numericPrecisionReduction = false; + + // Hook to populate a constant evaluation pass pipeline. If nullptr, then + // no passes are added for constant evaluation. This must be injected in + // because constant-evaluators can depend on the whole compiler, of which + // this is a part, and we maintain strict optionality for this component. + std::function buildConstEvalPassPipeline; +}; + +// Subset of the overall pass pipeline for optimizing globals and numerics. +// We may ultimately break this out separately so creating a syntactic +// distinction to keep that as an option. +void buildGlobalOptimizationPassPipeline( + OpPassManager &mainPassManager, const TransformOptions &transformOptions); + +} // namespace GlobalOptimization +} // namespace iree_compiler +} // namespace mlir + +#endif // IREE_COMPILER_GLOBALOPTIMIZATION_PASSES_H_ diff --git a/compiler/src/iree/compiler/Pipelines/BUILD.bazel b/compiler/src/iree/compiler/Pipelines/BUILD.bazel index fb04b06d1ac8d..5b4b8d9c383ba 100644 --- a/compiler/src/iree/compiler/Pipelines/BUILD.bazel +++ b/compiler/src/iree/compiler/Pipelines/BUILD.bazel @@ -46,6 +46,7 @@ iree_compiler_cc_library( "//compiler/src/iree/compiler/Dialect/VM/Conversion/StandardToVM", "//compiler/src/iree/compiler/Dialect/VM/Target/Bytecode", "//compiler/src/iree/compiler/Dialect/VM/Transforms", + "//compiler/src/iree/compiler/GlobalOptimization", "//compiler/src/iree/compiler/InputConversion/Common", "//compiler/src/iree/compiler/InputConversion/Common:AutoInputConversionPipeline", "//compiler/src/iree/compiler/InputConversion/StableHLO", diff --git a/compiler/src/iree/compiler/Pipelines/CMakeLists.txt b/compiler/src/iree/compiler/Pipelines/CMakeLists.txt index 76440ca649ca5..4d334dd9562e1 100644 --- a/compiler/src/iree/compiler/Pipelines/CMakeLists.txt +++ b/compiler/src/iree/compiler/Pipelines/CMakeLists.txt @@ -59,6 +59,7 @@ iree_cc_library( iree::compiler::InputConversion::Common iree::compiler::InputConversion::Common::AutoInputConversionPipeline iree::compiler::Preprocessing::Passes + iree::compiler::GlobalOptimization iree::compiler::Utils PUBLIC ) diff --git a/compiler/src/iree/compiler/Pipelines/Pipelines.cpp b/compiler/src/iree/compiler/Pipelines/Pipelines.cpp index 950832c549f2f..289a3542a0236 100644 --- a/compiler/src/iree/compiler/Pipelines/Pipelines.cpp +++ b/compiler/src/iree/compiler/Pipelines/Pipelines.cpp @@ -13,6 +13,7 @@ #include "iree/compiler/Dialect/Stream/Transforms/Passes.h" #include "iree/compiler/Dialect/Util/Transforms/Passes.h" #include "iree/compiler/Dialect/VM/Transforms/Passes.h" +#include "iree/compiler/GlobalOptimization/Passes.h" #include "iree/compiler/InputConversion/Common/Passes.h" #include "iree/compiler/Modules/HAL/Inline/Transforms/Passes.h" #include "iree/compiler/Modules/HAL/Loader/Transforms/Passes.h" @@ -146,10 +147,10 @@ void buildIREEVMTransformPassPipeline( if (compileTo == IREEVMPipelinePhase::ABI) return; // early-exit - IREE::Flow::TransformOptions flowOptions; - flowOptions.constExprHoisting = + GlobalOptimization::TransformOptions globalOptOptions; + globalOptOptions.constExprHoisting = highLevelOptimizationOptions.constExprHoisting; - flowOptions.numericPrecisionReduction = + globalOptOptions.numericPrecisionReduction = highLevelOptimizationOptions.numericPrecisionReduction; // Enable const-eval via hook. For debug builds, we assert if enabled @@ -161,7 +162,7 @@ void buildIREEVMTransformPassPipeline( } if (highLevelOptimizationOptions.constEval && hooks.buildConstEvalPassPipelineCallback) { - flowOptions.buildConstEvalPassPipeline = + globalOptOptions.buildConstEvalPassPipeline = hooks.buildConstEvalPassPipelineCallback; } @@ -192,9 +193,22 @@ void buildIREEVMTransformPassPipeline( if (compileTo == IREEVMPipelinePhase::Preprocessing) return; // early-exit + if (compileFrom < IREEVMPipelinePhase::FlowPreprocessing) { // late-entry + IREE_TRACE_ADD_BEGIN_FRAME_PASS(passManager, "FlowPreprocessing"); + IREE::Flow::buildFlowPreprocessingTransformPassPipeline(passManager); + IREE_TRACE_ADD_END_FRAME_PASS(passManager, "FlowPreprocessing"); + } + + if (compileFrom < IREEVMPipelinePhase::GlobalOptimization) { // late-entry + IREE_TRACE_ADD_BEGIN_FRAME_PASS(passManager, "GlobalOptimization"); + GlobalOptimization::buildGlobalOptimizationPassPipeline(passManager, + globalOptOptions); + IREE_TRACE_ADD_END_FRAME_PASS(passManager, "GlobalOptimization"); + } + if (compileFrom < IREEVMPipelinePhase::Flow) { // late-entry IREE_TRACE_ADD_BEGIN_FRAME_PASS(passManager, "Flow"); - IREE::Flow::buildFlowTransformPassPipeline(passManager, flowOptions); + IREE::Flow::buildFlowTransformPassPipeline(passManager); IREE_TRACE_ADD_END_FRAME_PASS(passManager, "Flow"); } if (compileTo == IREEVMPipelinePhase::Flow) diff --git a/compiler/src/iree/compiler/Pipelines/Pipelines.h b/compiler/src/iree/compiler/Pipelines/Pipelines.h index ca93652f17574..36a8e619ebc66 100644 --- a/compiler/src/iree/compiler/Pipelines/Pipelines.h +++ b/compiler/src/iree/compiler/Pipelines/Pipelines.h @@ -38,6 +38,8 @@ enum class IREEVMPipelinePhase { Input, ABI, Preprocessing, + FlowPreprocessing, + GlobalOptimization, Flow, Stream, ExecutableSources, @@ -60,6 +62,10 @@ inline static void enumerateIREEVMPipelinePhases( "Adjusts program ABI for the specified execution environment."); callback(IREEVMPipelinePhase::Preprocessing, "preprocessing", "Compiles up to the `preprocessing` specified"); + callback(IREEVMPipelinePhase::FlowPreprocessing, "flow-preprocessing", + "Compiles up to canonical inputs for `flow` dialect."); + callback(IREEVMPipelinePhase::GlobalOptimization, "global-optimization", + "Compiles up to global optimization."); callback(IREEVMPipelinePhase::Flow, "flow", "Compiles up to the `flow` dialect."); callback(IREEVMPipelinePhase::Stream, "stream",