[StableHLO] Add stablehlo pipeline to auto input conversion (#13868)
Prefer it over the legacy MHLO pipeline.
Issue: https://github.com/openxla/iree/issues/12678
diff --git a/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp b/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
index c7233ad..68a08b5 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
+++ b/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
@@ -16,7 +16,9 @@
// Dialect specific
#ifdef IREE_HAVE_MHLO_INPUT
#include "iree/compiler/InputConversion/MHLO/Passes.h"
+#include "iree/compiler/InputConversion/StableHLO/Passes.h"
#include "mhlo/IR/hlo_ops.h"
+#include "stablehlo/dialect/StablehloOps.h"
#endif // IREE_HAVE_MHLO_INPUT
#ifdef IREE_HAVE_TOSA_INPUT
#include "iree/compiler/InputConversion/TOSA/Passes.h"
@@ -28,17 +30,17 @@
namespace mlir::iree_compiler {
namespace {
-struct AutoInputConversionPipelinePass
- : public AutoInputConversionPipelineBase<AutoInputConversionPipelinePass> {
+struct AutoInputConversionPipelinePass final
+ : AutoInputConversionPipelineBase<AutoInputConversionPipelinePass> {
void runOnOperation() override;
void getDependentDialects(DialectRegistry& registry) const override;
};
// All the features seen that should be handled during input conversion.
struct InputFeatures {
- // MHLO features.
- bool hasMHLO = false;
+ // HLO features.
bool hasStableHLO = false;
+ bool hasMHLO = false;
// - XLA import features.
bool hasTuples = false;
@@ -50,7 +52,6 @@
};
static void populateHloFeatures(Operation* op, InputFeatures& features) {
- features.hasMHLO = true;
if (features.hasTuples) {
return;
}
@@ -86,12 +87,18 @@
}
}
-static void populateFeatures(Operation* op, const Dialect* mhloDialect,
+static void populateFeatures(Operation* op, const Dialect* stablehloDialect,
+ const Dialect* mhloDialect,
const Dialect* tmTensorDialect,
const Dialect* tosaDialect,
InputFeatures& features) {
Dialect* d = op->getDialect();
+ if (d == stablehloDialect) {
+ features.hasStableHLO = true;
+ return populateHloFeatures(op, features);
+ }
if (d == mhloDialect) {
+ features.hasMHLO = true;
return populateHloFeatures(op, features);
}
if (d == tosaDialect) {
@@ -109,20 +116,23 @@
MLIRContext* ctxt = &getContext();
InputFeatures features;
+ const Dialect* stablehloDialect = ctxt->getLoadedDialect("stablehlo");
const Dialect* mhloDialect = ctxt->getLoadedDialect("mhlo");
const Dialect* tosaDialect = ctxt->getLoadedDialect("tosa");
const Dialect* tmTensorDialect = ctxt->getLoadedDialect("tm_tensor");
- if (!mhloDialect && !tosaDialect && !tmTensorDialect) {
+ if (!stablehloDialect && !mhloDialect && !tosaDialect && !tmTensorDialect) {
return;
}
auto res = module.walk([&](Operation* op) {
- populateFeatures(op, mhloDialect, tmTensorDialect, tosaDialect, features);
- if (features.hasMHLO && features.hasTOSA) {
+ populateFeatures(op, stablehloDialect, mhloDialect, tmTensorDialect,
+ tosaDialect, features);
+ bool hasAnyHLO = features.hasStableHLO || features.hasMHLO;
+ if (hasAnyHLO && features.hasTOSA) {
module.emitError("not yet implemented mixture of *HLO and TOSA");
return WalkResult::interrupt();
}
- if (features.hasMHLO && features.hasTmTensor) {
+ if (hasAnyHLO && features.hasTmTensor) {
module.emitError("not yet implemented mixture of *HLO and TM Tensor");
return WalkResult::interrupt();
}
@@ -135,13 +145,21 @@
if (res.wasInterrupted()) {
return signalPassFailure();
}
- if (!features.hasMHLO && !features.hasTOSA && !features.hasTmTensor) {
+ if (!features.hasStableHLO && !features.hasMHLO && !features.hasTOSA &&
+ !features.hasTmTensor) {
return;
}
OpPassManager pm(ModuleOp::getOperationName(),
OpPassManager::Nesting::Explicit);
#ifdef IREE_HAVE_MHLO_INPUT
+ if (features.hasStableHLO && !features.hasMHLO) {
+ if (features.hasTuples) {
+ stablehlo::buildStableHLOXLAInputConversionPassPipeline(pm);
+ } else {
+ stablehlo::buildStableHLOInputConversionPassPipeline(pm);
+ }
+ }
if (features.hasMHLO) {
if (features.hasTuples) {
MHLO::buildXLAInputConversionPassPipeline(pm);
@@ -183,6 +201,10 @@
};
#ifdef IREE_HAVE_MHLO_INPUT
+ appendPipelineDialects(stablehlo::buildStableHLOInputConversionPassPipeline);
+ appendPipelineDialects(
+ stablehlo::buildStableHLOXLAInputConversionPassPipeline);
+
appendPipelineDialects(MHLO::buildMHLOInputConversionPassPipeline);
appendPipelineDialects(MHLO::buildXLAInputConversionPassPipeline);
#endif // IREE_HAVE_MHLO_INPUT
diff --git a/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel b/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
index ae10820..8f61d1d 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
+++ b/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
@@ -107,6 +107,7 @@
"@llvm-project//mlir:TosaDialect",
"@llvm-project//mlir:Transforms",
"@mlir-hlo//:mlir_hlo",
+ "@mlir-hlo//stablehlo:stablehlo_ops",
"@torch-mlir-dialects//:TorchMLIRTMTensorDialect",
],
)
diff --git a/compiler/src/iree/compiler/InputConversion/Common/test/auto_input_conversion_pipeline.mlir b/compiler/src/iree/compiler/InputConversion/Common/test/auto_input_conversion_pipeline.mlir
index 1e8e90d..11ac344 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/test/auto_input_conversion_pipeline.mlir
+++ b/compiler/src/iree/compiler/InputConversion/Common/test/auto_input_conversion_pipeline.mlir
@@ -1,10 +1,19 @@
-// RUN: iree-opt --iree-auto-input-conversion %s | FileCheck %s
+// RUN: iree-opt --iree-auto-input-conversion --split-input-file %s | FileCheck %s
// Check that the input conversion pipeline handles a simple input and does not crash.
-// CHECK-LABEL: func.func @simple_add
+// CHECK-LABEL: func.func @simple_add_stablehlo
// CHECK: arith.addi
-func.func @simple_add(%arg0: tensor<2x2xi32>, %arg1: tensor<2x2xi32>) -> tensor<2x2xi32> {
+func.func @simple_add_stablehlo(%arg0: tensor<2x2xi32>, %arg1: tensor<2x2xi32>) -> tensor<2x2xi32> {
+ %0 = stablehlo.add %arg0, %arg1 : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
+ return %0 : tensor<2x2xi32>
+}
+
+// -----
+
+// CHECK-LABEL: func.func @simple_add_mhlo
+// CHECK: arith.addi
+func.func @simple_add_mhlo(%arg0: tensor<2x2xi32>, %arg1: tensor<2x2xi32>) -> tensor<2x2xi32> {
%0 = "mhlo.add"(%arg0, %arg1) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
return %0 : tensor<2x2xi32>
}