Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move demotion passes to GlobalOptimization. #14815

Merged
merged 5 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build_tools/benchmarks/comparisons/setup_desktop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ for i in $(ls ${ROOT_DIR}/models/tflite/); do
--iree-input-type=tosa \
--iree-hal-target-backends=cuda \
--iree-hal-cuda-llvm-target-arch=sm_80 \
--iree-flow-demote-f32-to-f16 \
--iree-opt-demote-f32-to-f16 \
--iree-llvmcpu-debug-symbols=false \
--iree-vm-bytecode-module-strip-source-map=true \
--iree-vm-emit-polyglot-zip=false \
Expand Down
2 changes: 1 addition & 1 deletion build_tools/benchmarks/comparisons/setup_mobile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ for i in $(ls ${ROOT_DIR}/models/tflite/); do
--iree-input-type=tosa \
--iree-hal-target-backends=vulkan-spirv \
--iree-vulkan-target-triple=valhall-unknown-android31 \
--iree-flow-demote-f32-to-f16 \
--iree-opt-demote-f32-to-f16 \
--iree-llvmcpu-debug-symbols=false \
--iree-vm-bytecode-module-strip-source-map=true \
--iree-vm-emit-polyglot-zip=false \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def _get_module_generation_configs(
id=compile_config.id + "-demote-f32-to-16",
tags=compile_config.tags + ["demote-f32-to-f16"],
compile_targets=compile_config.compile_targets,
extra_flags=compile_config.extra_flags + ["--iree-flow-demote-f32-to-f16"],
extra_flags=compile_config.extra_flags + ["--iree-opt-demote-f32-to-f16"],
)
return (
[
Expand Down
9 changes: 4 additions & 5 deletions compiler/src/iree/compiler/API/Internal/CompilerDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ struct GlobalInit {
BindingOptions *clBindingOptions = nullptr;
InputDialectOptions *clInputOptions = nullptr;
PreprocessingOptions *clPreprocessingOptions = nullptr;
HighLevelOptimizationOptions *clHighLevelOptimizationOptions = nullptr;
GlobalOptimizationOptions *clGlobalOptimizationOptions = nullptr;
SchedulingOptions *clSchedulingOptions = nullptr;
IREE::HAL::TargetOptions *clHalTargetOptions = nullptr;
IREE::VM::TargetOptions *clVmTargetOptions = nullptr;
Expand Down Expand Up @@ -167,8 +167,7 @@ void GlobalInit::registerCommandLineOptions() {
clBindingOptions = &BindingOptions::FromFlags::get();
clInputOptions = &InputDialectOptions::FromFlags::get();
clPreprocessingOptions = &PreprocessingOptions::FromFlags::get();
clHighLevelOptimizationOptions =
&HighLevelOptimizationOptions::FromFlags::get();
clGlobalOptimizationOptions = &GlobalOptimizationOptions::FromFlags::get();
clSchedulingOptions = &SchedulingOptions::FromFlags::get();
clHalTargetOptions = &IREE::HAL::TargetOptions::FromFlags::get();
clVmTargetOptions = &IREE::VM::TargetOptions::FromFlags::get();
Expand Down Expand Up @@ -252,7 +251,7 @@ struct Session {
BindingOptions bindingOptions;
InputDialectOptions inputOptions;
PreprocessingOptions preprocessingOptions;
HighLevelOptimizationOptions highLevelOptimizationOptions;
GlobalOptimizationOptions highLevelOptimizationOptions;
SchedulingOptions schedulingOptions;
IREE::HAL::TargetOptions halTargetOptions;
IREE::VM::TargetOptions vmTargetOptions;
Expand All @@ -275,7 +274,7 @@ Session::Session(GlobalInit &globalInit)
bindingOptions = *globalInit.clBindingOptions;
inputOptions = *globalInit.clInputOptions;
preprocessingOptions = *globalInit.clPreprocessingOptions;
highLevelOptimizationOptions = *globalInit.clHighLevelOptimizationOptions;
highLevelOptimizationOptions = *globalInit.clGlobalOptimizationOptions;
schedulingOptions = *globalInit.clSchedulingOptions;
halTargetOptions = *globalInit.clHalTargetOptions;
vmTargetOptions = *globalInit.clVmTargetOptions;
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/iree/compiler/ConstEval/JitGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct CompileOptions {
BindingOptions bindingOptions;
InputDialectOptions inputOptions;
PreprocessingOptions preprocessingOptions;
HighLevelOptimizationOptions highLevelOptimizationOptions;
GlobalOptimizationOptions globalOptimizationOptions;
SchedulingOptions schedulingOptions;
IREE::HAL::TargetOptions executableOptions;
IREE::VM::TargetOptions targetOptions;
Expand Down Expand Up @@ -336,12 +336,12 @@ struct JitGlobalsPass : public JitGlobalsBase<JitGlobalsPass> {
// Disable constant evaluation for our Jit compilation pipeline.
// It would make no sense to recursively do constant evaluation, and since
// we omit the necessary hooks, it is unsupported anyway.
options->highLevelOptimizationOptions.constExprHoisting = false;
options->highLevelOptimizationOptions.constEval = false;
options->globalOptimizationOptions.constExprHoisting = false;
options->globalOptimizationOptions.constEval = false;

buildIREEVMTransformPassPipeline(
targetRegistry, options->bindingOptions, options->inputOptions,
options->preprocessingOptions, options->highLevelOptimizationOptions,
options->preprocessingOptions, options->globalOptimizationOptions,
options->schedulingOptions, options->executableOptions,
options->targetOptions, options->hooks, compilePipeline);
}
Expand Down
48 changes: 0 additions & 48 deletions compiler/src/iree/compiler/Dialect/Flow/Transforms/Passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,32 +49,6 @@ static llvm::cl::opt<std::string> clTraceDispatch(
"occurrences of the dispatch symbol."),
llvm::cl::init(""));

static llvm::cl::opt<bool> clDemoteI64ToI32(
"iree-flow-demote-i64-to-i32",
llvm::cl::desc("Converts all i64 ops and values into i32 counterparts "
"unconditionally before main flow conversions."),
llvm::cl::init(false));
static llvm::cl::opt<bool> clDemoteF32ToF16(
"iree-flow-demote-f32-to-f16",
llvm::cl::desc("Converts all f32 ops and values into f16 counterparts "
"unconditionally before main flow conversions."),
llvm::cl::init(false));
static llvm::cl::opt<bool> clPromoteBF16ToF32(
"iree-flow-promote-bf16-to-f32",
llvm::cl::desc("Converts all bf16 ops and values into f32 counterparts "
"unconditionally before main flow conversions."),
llvm::cl::init(false));
static llvm::cl::opt<bool> clPromoteF16ToF32(
"iree-flow-promote-f16-to-f32",
llvm::cl::desc("Converts all f16 ops and values into f32 counterparts "
"unconditionally before main flow conversions."),
llvm::cl::init(false));
static llvm::cl::opt<bool> clDemoteF64ToF32(
"iree-flow-demote-f64-to-f32",
llvm::cl::desc("Converts all f64 ops and values into f32 counterparts "
"unconditionally before main flow conversions."),
llvm::cl::init(true));

static llvm::cl::opt<bool> clDetensoring(
"iree-flow-enable-detensoring",
llvm::cl::desc(
Expand Down Expand Up @@ -149,28 +123,6 @@ void buildFlowTransformPassPipeline(OpPassManager &passManager,
// Start of Flow pipeline, verify input legality.
passManager.addPass(IREE::Flow::createVerifyInputLegalityPass());

// 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
// the frontends. It'll always be better to do this higher up in the stack
// as these kind of blanket conversions have corner cases and potential
// accuracy/precision losses beyond what the user may expect.
if (clDemoteF64ToF32) {
passManager.addPass(IREE::Util::createDemoteF64ToF32Pass());
}
if (clDemoteF32ToF16) {
passManager.addPass(IREE::Util::createDemoteF32ToF16Pass());
}
if (clPromoteF16ToF32) {
passManager.addPass(IREE::Util::createPromoteF16ToF32Pass());
}
if (clDemoteI64ToI32) {
passManager.addPass(IREE::Util::createDemoteI64ToI32Pass());
}
if (clPromoteBF16ToF32) {
passManager.addPass(IREE::Util::createPromoteBF16ToF32Pass());
}

// Transform pad operations into linalg.fill + tensor.insert_slice.
// This is a WAR for not having native pad handling.
if (!clEnablePadHandling && !clEnableFusePaddingIntoLinalgProducerOps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ iree_compiler_cc_library(
deps = [
"//compiler/src/iree/compiler/Dialect/Flow/Transforms",
"//compiler/src/iree/compiler/Dialect/Util/Transforms",
"//compiler/src/iree/compiler/Pipelines:Options",
"//compiler/src/iree/compiler/Utils",
"@llvm-project//llvm:Support",
"@llvm-project//mlir:FuncDialect",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ iree_cc_library(
MLIRTransforms
iree::compiler::Dialect::Flow::Transforms
iree::compiler::Dialect::Util::Transforms
iree::compiler::Pipelines::Options
iree::compiler::Utils
PUBLIC
)
Expand Down
33 changes: 31 additions & 2 deletions compiler/src/iree/compiler/GlobalOptimization/Passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@ using FunctionLikeNest = MultiOpNest<func::FuncOp, IREE::Util::InitializerOp>;

void buildGlobalOptimizationPassPipeline(
OpPassManager &mainPassManager, const TransformOptions &transformOptions) {
// 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
// the frontends. It'll always be better to do this higher up in the stack
// as these kind of blanket conversions have corner cases and potential
// accuracy/precision losses beyond what the user may expect.
if (transformOptions.options.demoteF64ToF32) {
mainPassManager.addPass(IREE::Util::createDemoteF64ToF32Pass());
}
if (transformOptions.options.demoteF32ToF16) {
mainPassManager.addPass(IREE::Util::createDemoteF32ToF16Pass());
}
if (transformOptions.options.promoteF16ToF32) {
mainPassManager.addPass(IREE::Util::createPromoteF16ToF32Pass());
}
if (transformOptions.options.promoteBF16ToF32) {
mainPassManager.addPass(IREE::Util::createPromoteBF16ToF32Pass());
}
if (transformOptions.options.demoteI64ToI32) {
mainPassManager.addPass(IREE::Util::createDemoteI64ToI32Pass());
}

// Preprocessing passes to get the program into a canonical state.
FunctionLikeNest(mainPassManager)
.addPass(IREE::Flow::createRemoveZeroExtentTensorsPass)
Expand Down Expand Up @@ -47,15 +69,15 @@ void buildGlobalOptimizationPassPipeline(
pipeline.addPass(IREE::Util::createFoldGlobalsPass());
pipeline.addPass(IREE::Util::createIPOPass());

if (transformOptions.constExprHoisting) {
if (transformOptions.options.constExprHoisting) {
pipeline.addPass(IREE::Util::createHoistIntoGlobalsPass());
}

if (transformOptions.buildConstEvalPassPipeline) {
transformOptions.buildConstEvalPassPipeline(pipeline);
}

if (transformOptions.numericPrecisionReduction) {
if (transformOptions.options.numericPrecisionReduction) {
pipeline.addPass(IREE::Flow::createInferNumericNarrowingPass());
pipeline.addPass(IREE::Flow::createOptimizeNumericsPass());
pipeline.addPass(IREE::Flow::createCleanupNumericNarrowingPass());
Expand All @@ -68,6 +90,13 @@ void buildGlobalOptimizationPassPipeline(
// Add the whole fixed point iterator.
mainPassManager.addPass(
IREE::Util::createFixedPointIteratorPass(std::move(pipeline)));

// Strip std.assert & co after we perform optimizations; prior to this we
// may use the assertions to derive information during analysis.
if (transformOptions.options.stripAssertions) {
FunctionLikeNest(mainPassManager)
.addPass(IREE::Util::createStripDebugOpsPass);
}
}

void registerGlobalOptimizationPipeline() {
Expand Down
11 changes: 5 additions & 6 deletions compiler/src/iree/compiler/GlobalOptimization/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@

#include <functional>

#include "iree/compiler/Pipelines/Options.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"

namespace mlir {
namespace iree_compiler {
namespace GlobalOptimization {

// We have a layer of indirection around the GlobalOptimizationOptions because
// we also need a reference to the const-eval builder, which is injected
// in by callers.
struct TransformOptions : public PassPipelineOptions<TransformOptions> {
// 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;
GlobalOptimizationOptions options;

// Hook to populate a constant evaluation pass pipeline. If nullptr, then
// no passes are added for constant evaluation. This must be injected in
Expand Down
32 changes: 29 additions & 3 deletions compiler/src/iree/compiler/Pipelines/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
IREE_DEFINE_COMPILER_OPTION_FLAGS(mlir::iree_compiler::BindingOptions);
IREE_DEFINE_COMPILER_OPTION_FLAGS(mlir::iree_compiler::InputDialectOptions);
IREE_DEFINE_COMPILER_OPTION_FLAGS(
mlir::iree_compiler::HighLevelOptimizationOptions);
mlir::iree_compiler::GlobalOptimizationOptions);
IREE_DEFINE_COMPILER_OPTION_FLAGS(mlir::iree_compiler::SchedulingOptions);
IREE_DEFINE_COMPILER_OPTION_FLAGS(mlir::iree_compiler::PreprocessingOptions);

Expand Down Expand Up @@ -98,9 +98,35 @@ InputDialectOptions::Type InputDialectOptions::parseInputTypeMnemonic() {
}
}

void HighLevelOptimizationOptions::bindOptions(OptionsBinder &binder) {
void GlobalOptimizationOptions::bindOptions(OptionsBinder &binder) {
static llvm::cl::OptionCategory category(
"IREE options for controlling high level optimizations.");
"IREE options for controlling global optimizations.");
// Type promotion/demotion options.
binder.opt<bool>(
"iree-opt-demote-f64-to-f32", demoteF64ToF32,
llvm::cl::desc("Converts all f64 ops and values into f32 counterparts "
"unconditionally before main global optimizations."),
llvm::cl::cat(category));
binder.opt<bool>(
"iree-opt-demote-f32-to-f16", demoteF32ToF16,
llvm::cl::desc("Converts all f32 ops and values into f16 counterparts "
"unconditionally before main global optimizations."),
llvm::cl::cat(category));
binder.opt<bool>(
"iree-opt-promote-f16-to-f32", promoteF16ToF32,
llvm::cl::desc("Converts all f16 ops and values into f32 counterparts "
"unconditionally before main global optimizations."),
llvm::cl::cat(category));
binder.opt<bool>(
"iree-opt-promote-bf16-to-f32", promoteBF16ToF32,
llvm::cl::desc("Converts all bf16 ops and values into f32 counterparts "
"unconditionally before main global optimizations."),
llvm::cl::cat(category));
binder.opt<bool>(
"iree-opt-demote-i64-to-i32", demoteI64ToI32,
llvm::cl::desc("Converts all i64 ops and values into i32 counterparts "
"unconditionally before main global optimizations."),
llvm::cl::cat(category));

binder.opt<bool>(
"iree-opt-const-eval", constEval,
Expand Down
11 changes: 9 additions & 2 deletions compiler/src/iree/compiler/Pipelines/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,14 @@ struct InputDialectOptions {
};

// Options controlling high level optimizations.
struct HighLevelOptimizationOptions {
struct GlobalOptimizationOptions {
// Gate various type based demotion passes that run before anything else.
bool demoteF64ToF32 = true;
bool demoteF32ToF16 = false;
bool promoteF16ToF32 = false;
bool promoteBF16ToF32 = false;
bool demoteI64ToI32 = false;

// Enables const-expr hoisting into globals.
bool constExprHoisting = true;

Expand All @@ -90,7 +97,7 @@ struct HighLevelOptimizationOptions {
bool stripAssertions = false;

void bindOptions(OptionsBinder &binder);
using FromFlags = OptionsFromFlags<HighLevelOptimizationOptions>;
using FromFlags = OptionsFromFlags<GlobalOptimizationOptions>;
};

// Options controlling scheduling across host/device.
Expand Down
27 changes: 9 additions & 18 deletions compiler/src/iree/compiler/Pipelines/Pipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void buildIREEVMTransformPassPipeline(
const IREE::HAL::TargetBackendRegistry &targetRegistry,
BindingOptions bindingOptions, InputDialectOptions inputOptions,
PreprocessingOptions preprocessingOptions,
HighLevelOptimizationOptions highLevelOptimizationOptions,
GlobalOptimizationOptions globalOptimizationOptions,
SchedulingOptions schedulingOptions,
IREE::HAL::TargetOptions executableOptions,
IREE::VM::TargetOptions targetOptions, IREEVMPipelineHooks &hooks,
Expand Down Expand Up @@ -147,31 +147,22 @@ void buildIREEVMTransformPassPipeline(
if (compileTo == IREEVMPipelinePhase::ABI)
return; // early-exit

GlobalOptimization::TransformOptions globalOptOptions;
globalOptOptions.constExprHoisting =
highLevelOptimizationOptions.constExprHoisting;
globalOptOptions.numericPrecisionReduction =
highLevelOptimizationOptions.numericPrecisionReduction;
GlobalOptimization::TransformOptions globalTransformOptions;
globalTransformOptions.options = globalOptimizationOptions;

// Enable const-eval via hook. For debug builds, we assert if enabled
// without a hook. For release, we just silently skip enabling const-eval.
if (highLevelOptimizationOptions.constEval) {
if (globalOptimizationOptions.constEval) {
assert(hooks.buildConstEvalPassPipelineCallback &&
"if const-eval is enabled the buildConstEvalPassPipelineCallback "
"hook must be enabled");
}
if (highLevelOptimizationOptions.constEval &&
if (globalOptimizationOptions.constEval &&
hooks.buildConstEvalPassPipelineCallback) {
globalOptOptions.buildConstEvalPassPipeline =
globalTransformOptions.buildConstEvalPassPipeline =
hooks.buildConstEvalPassPipelineCallback;
}

if (highLevelOptimizationOptions.stripAssertions) {
// Strip std.assert & co after we perform optimizations; prior to this we
// may use the assertions to derive information during analysis.
passManager.addPass(IREE::Util::createStripDebugOpsPass());
}

IREE::Stream::TransformOptions streamOptions;
// TODO(benvanik): find a way to share the enums w/o circular deps.
streamOptions.dumpStatisticsFormat =
Expand All @@ -195,8 +186,8 @@ void buildIREEVMTransformPassPipeline(

if (compileFrom < IREEVMPipelinePhase::GlobalOptimization) { // late-entry
IREE_TRACE_ADD_BEGIN_FRAME_PASS(passManager, "GlobalOptimization");
GlobalOptimization::buildGlobalOptimizationPassPipeline(passManager,
globalOptOptions);
GlobalOptimization::buildGlobalOptimizationPassPipeline(
passManager, globalTransformOptions);
IREE_TRACE_ADD_END_FRAME_PASS(passManager, "GlobalOptimization");
}

Expand Down Expand Up @@ -295,7 +286,7 @@ void buildDefaultIREEVMTransformPassPipeline(OpPassManager &passManager) {

// Since a JIT hook cannot be provided in such a default pipeline, we
// force disable const eval, which relies on the JIT.
auto highLevelOptimizations = HighLevelOptimizationOptions::FromFlags::get();
auto highLevelOptimizations = GlobalOptimizationOptions::FromFlags::get();
highLevelOptimizations.constEval = false;

buildIREEVMTransformPassPipeline(
Expand Down
Loading
Loading