Remove MHLO support (#14008)

Drop the MHLO input conversion pipeline, which has been deprecated for
over a week. The StableHLO pipeline is the direct replacement. See the
announcement thread for more context:
https://groups.google.com/g/iree-discuss/c/s6dBpDtWhtk.

This still uses the copy of stablehlo from the mlir-hlo repo -- we will
switch to the stablehlo repo in a follow-up PR.

Issue: https://github.com/openxla/iree/issues/12678
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 94e41f3..229e7bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -372,14 +372,14 @@
 # Compiler Input Dialects
 #-------------------------------------------------------------------------------
 
-cmake_dependent_option(IREE_INPUT_MHLO "Builds support for compiling MHLO programs" ON ${IREE_BUILD_COMPILER} OFF)
+cmake_dependent_option(IREE_INPUT_STABLEHLO "Builds support for compiling StableHLO programs" ON ${IREE_BUILD_COMPILER} OFF)
 cmake_dependent_option(IREE_INPUT_TORCH "Builds support for compiling Torch MLIR programs" ON ${IREE_BUILD_COMPILER} OFF)
 cmake_dependent_option(IREE_INPUT_TOSA "Builds support for compiling TOSA programs" ON ${IREE_BUILD_COMPILER} OFF)
 
 if(IREE_BUILD_COMPILER)
   message(STATUS "IREE compiler input dialects:")
-  if(IREE_INPUT_MHLO)
-    message(STATUS "  - MHLO")
+  if(IREE_INPUT_STABLEHLO)
+    message(STATUS "  - StableHLO")
   endif()
   if(IREE_INPUT_TORCH)
     message(STATUS "  - Torch MLIR")
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py
index 36d668f..7c70e30 100644
--- a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py
+++ b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py
@@ -77,47 +77,9 @@
         "@llvm-project//mlir:MlirOptLib": ["MLIROptLib"],
         "@llvm-project//mlir:VectorOps": ["MLIRVector"],
 
-        # MHLO.
-        # TODO: Rework this upstream so that Bazel and CMake rules match up
-        # better.
-        # All of these have to depend on tensorflow::external_mhlo_includes to
-        # ensure that include directories are inherited.
-        "@mlir-hlo//:chlo_legalize_to_hlo": [
-            "tensorflow::external_mhlo_includes",
-            "ChloPasses",
-        ],
-        "@mlir-hlo//:mlir_hlo": [
-            "tensorflow::external_mhlo_includes",
-            "MhloDialect",
-            "MLIRMhloUtils",
-        ],
-        "@mlir-hlo//:map_chlo_to_hlo_op": [
-            "ChloOps",
-            "MhloDialect",
-        ],
-        "@mlir-hlo//:map_mhlo_to_scalar_op": [
-            "tensorflow::external_mhlo_includes",
-            "MhloDialect",
-        ],
-        "@mlir-hlo//:mhlo_passes": [
-            "tensorflow::external_mhlo_includes",
-            "MhloPasses",
-            "MhloShapeOpsToStandard",
-            "MhloToLinalg",
-            "MhloToStablehlo",
-            "MhloToStandard",
-            "StablehloToMhlo",
-            # Note: We deliberately omit some passes that we do not use in IREE,
-            # e.g.: MhloToArithmeticConversion, MhloToLhloConversion, or
-            # MhloToMemrefConversion.
-        ],
-        "@mlir-hlo//:unfuse_batch_norm": [
-            "tensorflow::external_mhlo_includes",
-            "MhloPasses",
-        ],
+        # StableHLO.
         "@mlir-hlo//stablehlo:chlo_ops": ["ChloOps",],
         "@mlir-hlo//stablehlo:stablehlo_ops": ["StablehloOps",],
-        "@mlir-hlo//:stablehlo_legalize_to_hlo_pass": ["StablehloToMhlo",],
         "@mlir-hlo//stablehlo:broadcast_utils": ["StablehloBroadcastUtils",],
 
         # NCCL
diff --git a/build_tools/cmake/test_riscv.sh b/build_tools/cmake/test_riscv.sh
index 0f995de..163ff42 100755
--- a/build_tools/cmake/test_riscv.sh
+++ b/build_tools/cmake/test_riscv.sh
@@ -80,11 +80,10 @@
 ctest ${tools_ctest_args[@]}
 
 if [[ "${RISCV_PLATFORM}-${RISCV_ARCH}" == "linux-riscv_32" ]]; then
-  # mhlo.power is also disabled because musl math library is not compiled for
+  # stablehlo.power is also disabled because musl math library is not compiled for
   # 32-bit.
   test_exclude_args+=(
     "stablehlo.*llvm-cpu.*pow"
-    "xla.*llvm-cpu.*pow"
   )
 fi
 
@@ -96,7 +95,6 @@
   "iree/tests/e2e/tensor_ops/check_llvm-cpu_local-task_pack_dynamic_inner_tiles.mlir"
   # TODO(#13421): Enable the tests
   "iree/tests/e2e/stablehlo_ops/check_llvm-cpu_local-task_dot.mlir"
-  "iree/tests/e2e/xla_ops/check_llvm-cpu_local-task_dot.mlir"
   "iree/tests/e2e/matmul/e2e_matmul_direct_i8_small_llvm-cpu_local-task"
   "iree/tests/e2e/matmul/e2e_matmul_direct_f32_small_llvm-cpu_local-task"
   "iree/tests/e2e/matmul/e2e_matmul_direct_f32_small_no_padding_llvm-cpu_local-task"
diff --git a/compiler/bindings/python/iree/compiler/tools/core.py b/compiler/bindings/python/iree/compiler/tools/core.py
index 90814d5..ae3f5c4 100644
--- a/compiler/bindings/python/iree/compiler/tools/core.py
+++ b/compiler/bindings/python/iree/compiler/tools/core.py
@@ -46,8 +46,6 @@
   STABLEHLO_XLA = "stablehlo_xla"
   TOSA = "tosa"
   TM_TENSOR = "tm_tensor"
-  MHLO_LEGACY = "mhlo_legacy"
-  XLA_LEGACY = "xla_legacy"
 
   @staticmethod
   def parse(spec: Union[str, InputType]) -> InputType:
diff --git a/compiler/bindings/python/iree/compiler/tools/tf.py b/compiler/bindings/python/iree/compiler/tools/tf.py
index f3b957d..00c1573 100644
--- a/compiler/bindings/python/iree/compiler/tools/tf.py
+++ b/compiler/bindings/python/iree/compiler/tools/tf.py
@@ -97,7 +97,7 @@
   exported_names: Sequence[str] = ()
   import_only: bool = False
   import_type: ImportType = ImportType.OBJECT_GRAPH
-  input_type: Union[InputType, str] = InputType.XLA_LEGACY
+  input_type: Union[InputType, str] = InputType.STABLEHLO_XLA
   saved_model_tags: Set[str] = field(default_factory=set)
   save_temp_iree_input: Optional[str] = None
 
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/VerifyInputLegality.cpp b/compiler/src/iree/compiler/Dialect/Flow/Transforms/VerifyInputLegality.cpp
index 2fcf59b..07429ad 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/VerifyInputLegality.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/VerifyInputLegality.cpp
@@ -26,8 +26,9 @@
     target.addLegalOp<tosa::ApplyScaleOp>();
     // We're already depending on the Tosa Dialect
     target.addIllegalDialect<tosa::TosaDialect>();
-    // Avoid MHLO dependency
-    target.addIllegalDialect("mhlo");
+    // Avoid StableHLO dependency
+    target.addIllegalDialect("chlo");
+    target.addIllegalDialect("stablehlo");
     target.addIllegalOp<UnrealizedConversionCastOp>();
 
     if (failed(iree_compiler::verifyAllOperationsAreLegal(getOperation(),
diff --git a/compiler/src/iree/compiler/Dialect/Flow/Transforms/test/verify_input_ir.mlir b/compiler/src/iree/compiler/Dialect/Flow/Transforms/test/verify_input_ir.mlir
index 9044969..82822c6 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/Transforms/test/verify_input_ir.mlir
+++ b/compiler/src/iree/compiler/Dialect/Flow/Transforms/test/verify_input_ir.mlir
@@ -1,10 +1,12 @@
 // RUN: iree-opt --pass-pipeline="builtin.module(func.func(iree-verify-input-legality))" --verify-diagnostics %s -split-input-file
 
 // expected-error@below {{illegal operations still remain}}
-func.func @check_no_mhlo(%arg0: tensor<?x?xf32>, %arg1 : tensor<?x?xf32>) -> tensor<?x?xf32> {
+func.func @check_no_stablehlo(%arg0: tensor<?x?xf32>, %arg1 : tensor<?x?xf32>) -> tensor<?x?xf32> {
   // expected-error@+1 {{illegal op still exists}}
-  %0 = "mhlo.add"(%arg0, %arg1) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
-  return %0 : tensor<?x?xf32>
+  %0 = stablehlo.add %arg0, %arg1 : tensor<?x?xf32>
+  // expected-error@+1 {{illegal op still exists}}
+  %1 = chlo.broadcast_add %0, %arg1 : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+  return %1 : tensor<?x?xf32>
 }
 
 // -----
diff --git a/compiler/src/iree/compiler/InputConversion/CMakeLists.txt b/compiler/src/iree/compiler/InputConversion/CMakeLists.txt
index 474215f..6e578b3 100644
--- a/compiler/src/iree/compiler/InputConversion/CMakeLists.txt
+++ b/compiler/src/iree/compiler/InputConversion/CMakeLists.txt
@@ -6,8 +6,7 @@
 
 add_subdirectory(Common)
 
-if(IREE_INPUT_MHLO)
-  add_subdirectory(MHLO)
+if(IREE_INPUT_STABLEHLO)
   add_subdirectory(StableHLO)
 endif()
 if(IREE_INPUT_TORCH)
diff --git a/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp b/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
index 42a36c9..be7a9b7 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
+++ b/compiler/src/iree/compiler/InputConversion/Common/AutoInputConversionPipeline.cpp
@@ -14,12 +14,10 @@
 #include "mlir/Pass/PassManager.h"
 
 // Dialect specific
-#ifdef IREE_HAVE_MHLO_INPUT
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
+#ifdef IREE_HAVE_STABLEHLO_INPUT
 #include "iree/compiler/InputConversion/StableHLO/Passes.h"
-#include "mhlo/IR/hlo_ops.h"
 #include "stablehlo/dialect/StablehloOps.h"
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TOSA_INPUT
 #include "iree/compiler/InputConversion/TOSA/Passes.h"
 #endif  // IREE_HAVE_TOSA_INPUT
@@ -45,7 +43,6 @@
 struct InputFeatures {
   // HLO features.
   bool hasStableHLO = false;
-  bool hasMHLO = false;
   // - XLA import features.
   bool hasTuples = false;
 
@@ -93,7 +90,6 @@
 }
 
 static void populateFeatures(Operation* op, const Dialect* stablehloDialect,
-                             const Dialect* mhloDialect,
                              const Dialect* tmTensorDialect,
                              const Dialect* tosaDialect,
                              InputFeatures& features) {
@@ -102,10 +98,6 @@
     features.hasStableHLO = true;
     return populateHloFeatures(op, features);
   }
-  if (d == mhloDialect) {
-    features.hasMHLO = true;
-    return populateHloFeatures(op, features);
-  }
   if (d == tosaDialect) {
     features.hasTOSA = true;
     return;
@@ -122,22 +114,20 @@
 
   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 (!stablehloDialect && !mhloDialect && !tosaDialect && !tmTensorDialect) {
+  if (!stablehloDialect && !tosaDialect && !tmTensorDialect) {
     return;
   }
 
   auto res = module.walk([&](Operation* op) {
-    populateFeatures(op, stablehloDialect, mhloDialect, tmTensorDialect,
-                     tosaDialect, features);
-    bool hasAnyHLO = features.hasStableHLO || features.hasMHLO;
-    if (hasAnyHLO && features.hasTOSA) {
+    populateFeatures(op, stablehloDialect, tmTensorDialect, tosaDialect,
+                     features);
+    if (features.hasStableHLO && features.hasTOSA) {
       module.emitError("not yet implemented mixture of *HLO and TOSA");
       return WalkResult::interrupt();
     }
-    if (hasAnyHLO && features.hasTmTensor) {
+    if (features.hasStableHLO && features.hasTmTensor) {
       module.emitError("not yet implemented mixture of *HLO and TM Tensor");
       return WalkResult::interrupt();
     }
@@ -150,15 +140,14 @@
   if (res.wasInterrupted()) {
     return signalPassFailure();
   }
-  if (!features.hasStableHLO && !features.hasMHLO && !features.hasTOSA &&
-      !features.hasTmTensor) {
+  if (!features.hasStableHLO && !features.hasTOSA && !features.hasTmTensor) {
     return;
   }
 
   OpPassManager pm(ModuleOp::getOperationName(),
                    OpPassManager::Nesting::Explicit);
-#ifdef IREE_HAVE_MHLO_INPUT
-  if (features.hasStableHLO && !features.hasMHLO) {
+#ifdef IREE_HAVE_STABLEHLO_INPUT
+  if (features.hasStableHLO) {
     stablehlo::StableHloOptions options;
     options.demoteI64ToI32 = demoteI64ToI32;
     options.demoteF64ToF32 = demoteF64ToF32;
@@ -169,14 +158,7 @@
       stablehlo::buildStableHLOInputConversionPassPipeline(pm, options);
     }
   }
-  if (features.hasMHLO) {
-    if (features.hasTuples) {
-      MHLO::buildXLAInputConversionPassPipeline(pm);
-    } else {
-      MHLO::buildMHLOInputConversionPassPipeline(pm);
-    }
-  }
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TOSA_INPUT
   if (features.hasTOSA) {
     buildTOSAInputConversionPassPipeline(pm);
@@ -209,7 +191,7 @@
         pm.getDependentDialects(registry);
       };
 
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
   auto appendStablehloPipelineDialects =
       [&registry](function_ref<void(OpPassManager&,
                                     const stablehlo::StableHloOptions& options)>
@@ -224,10 +206,7 @@
       stablehlo::buildStableHLOInputConversionPassPipeline);
   appendStablehloPipelineDialects(
       stablehlo::buildStableHLOXLAInputConversionPassPipeline);
-
-  appendPipelineDialects(MHLO::buildMHLOInputConversionPassPipeline);
-  appendPipelineDialects(MHLO::buildXLAInputConversionPassPipeline);
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 
 #ifdef IREE_HAVE_TOSA_INPUT
   appendPipelineDialects(buildTOSAInputConversionPassPipeline);
diff --git a/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel b/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
index 8f61d1d..3f944a5 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
+++ b/compiler/src/iree/compiler/InputConversion/Common/BUILD.bazel
@@ -95,7 +95,6 @@
     deps = [
         ":PassHeaders",
         ":PassesIncGen",
-        "//compiler/src/iree/compiler/InputConversion/MHLO",
         "//compiler/src/iree/compiler/InputConversion/StableHLO",
         "//compiler/src/iree/compiler/InputConversion/TMTensor",
         "//compiler/src/iree/compiler/InputConversion/TOSA",
@@ -106,7 +105,6 @@
         "@llvm-project//mlir:Pass",
         "@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/CMakeLists.txt b/compiler/src/iree/compiler/InputConversion/Common/CMakeLists.txt
index e446adf..6864b3c 100644
--- a/compiler/src/iree/compiler/InputConversion/Common/CMakeLists.txt
+++ b/compiler/src/iree/compiler/InputConversion/Common/CMakeLists.txt
@@ -6,8 +6,7 @@
 
 # Enable input dialects based on options.
 set(IREE_INPUT_DEPS "")
-if(IREE_INPUT_MHLO)
-  list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::MHLO)
+if(IREE_INPUT_STABLEHLO)
   list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::StableHLO)
 endif()
 if(IREE_INPUT_TORCH)
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 11ac344..b2ff749 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
@@ -8,12 +8,3 @@
   %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>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/BUILD.bazel b/compiler/src/iree/compiler/InputConversion/MHLO/BUILD.bazel
deleted file mode 100644
index e0fc506..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/BUILD.bazel
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2021 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_gentbl_cc_library(
-    name = "PassesIncGen",
-    tbl_outs = [
-        (
-            ["--gen-pass-decls"],
-            "Passes.h.inc",
-        ),
-    ],
-    tblgen = "@llvm-project//mlir:mlir-tblgen",
-    td_file = "Passes.td",
-    deps = [
-        "@llvm-project//mlir:PassBaseTdFiles",
-    ],
-)
-
-iree_compiler_cc_library(
-    name = "PassHeaders",
-    hdrs = [
-        "PassDetail.h",
-        "Passes.h",
-        "Passes.h.inc",
-        "Rewriters.h",
-    ],
-    deps = [
-        ":PassesIncGen",
-        "@llvm-project//mlir:Pass",
-        "@llvm-project//mlir:Transforms",
-    ],
-)
-
-iree_compiler_cc_library(
-    name = "MHLO",
-    srcs = [
-        "BroadcastingToLinalgPatterns.cpp",
-        "ConvertCollectiveOps.cpp",
-        "ConvertComplexToReal.cpp",
-        "ConvertMHLOToFlow.cpp",
-        "ConvertMHLOToFlow.h",
-        "ConvertMHLOToLinalgExt.cpp",
-        "ConvertMHLOToStableHLO.cpp",
-        "FlattenTuplesInCFG.cpp",
-        "MHLOToLinalgOnTensors.cpp",
-        "MHLOToMHLOPreprocessing.cpp",
-        "Passes.cpp",
-        "VerifyCompilerMHLOInputLegality.cpp",
-    ],
-    hdrs = [
-        "Passes.h",
-    ],
-    defines = [
-        "IREE_HAVE_MHLO_INPUT",
-    ],
-    deps = [
-        ":PassHeaders",
-        ":PassesIncGen",
-        "//compiler/src/iree/compiler/Dialect/Flow/IR",
-        "//compiler/src/iree/compiler/Dialect/Util/IR",
-        "//compiler/src/iree/compiler/Dialect/Util/Transforms",
-        "//compiler/src/iree/compiler/InputConversion/Common",
-        "//compiler/src/iree/compiler/Utils",
-        "//llvm-external-projects/iree-dialects:IREELinalgExtDialect",
-        "//llvm-external-projects/iree-dialects:IREELinalgExtPasses",
-        "@llvm-project//llvm:Support",
-        "@llvm-project//mlir:AffineDialect",
-        "@llvm-project//mlir:AffineUtils",
-        "@llvm-project//mlir:ArithDialect",
-        "@llvm-project//mlir:ComplexDialect",
-        "@llvm-project//mlir:ControlFlowDialect",
-        "@llvm-project//mlir:DialectUtils",
-        "@llvm-project//mlir:FuncDialect",
-        "@llvm-project//mlir:IR",
-        "@llvm-project//mlir:LinalgDialect",
-        "@llvm-project//mlir:LinalgTransforms",
-        "@llvm-project//mlir:MLProgramDialect",
-        "@llvm-project//mlir:MathDialect",
-        "@llvm-project//mlir:MemRefDialect",
-        "@llvm-project//mlir:Pass",
-        "@llvm-project//mlir:ReconcileUnrealizedCasts",
-        "@llvm-project//mlir:SCFToControlFlow",
-        "@llvm-project//mlir:SCFTransforms",
-        "@llvm-project//mlir:ShapeDialect",
-        "@llvm-project//mlir:ShapeToStandard",
-        "@llvm-project//mlir:ShapeTransforms",
-        "@llvm-project//mlir:Support",
-        "@llvm-project//mlir:TensorDialect",
-        "@llvm-project//mlir:TensorUtils",
-        "@llvm-project//mlir:Transforms",
-        "@mlir-hlo//:chlo_legalize_to_hlo",
-        "@mlir-hlo//:map_chlo_to_hlo_op",
-        "@mlir-hlo//:map_mhlo_to_scalar_op",
-        "@mlir-hlo//:mhlo_passes",
-        "@mlir-hlo//:mlir_hlo",
-        "@mlir-hlo//stablehlo:broadcast_utils",
-        "@mlir-hlo//stablehlo:chlo_ops",
-        "@mlir-hlo//stablehlo:stablehlo_ops",
-    ],
-)
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
deleted file mode 100644
index e8b54e4..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/BroadcastingToLinalgPatterns.cpp
+++ /dev/null
@@ -1,822 +0,0 @@
-// Copyright 2021 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
-
-// Patterns for lowering from dynamic-shape sensitive CHLO/MHLO ops. This
-// primarily involves broadcasting ops but also includes other ops that have
-// an impact on dynamic shape conversions.
-
-#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
-#include "iree/compiler/InputConversion/MHLO/Rewriters.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mhlo/transforms/map_chlo_to_hlo_op.h"
-#include "mhlo/transforms/rewriters.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/Linalg/IR/Linalg.h"
-#include "mlir/Dialect/MemRef/IR/MemRef.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "stablehlo/dialect/BroadcastUtils.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-// -----------------------------------------------------------------------------
-// Broadcasting utilities
-// -----------------------------------------------------------------------------
-
-/// Whether an element type is legal for codegen via linalg on IREE.
-bool isElementTypeLegalForCodegen(Type t) { return !llvm::isa<ComplexType>(t); }
-
-/// Returns an ArrayAttr that contains `nLoops` attributes. All the attributes
-/// are "parallel" except the last `nReduction` elements, where are "reduction"
-/// attributes.
-SmallVector<utils::IteratorType, 3> getParallelAndReductionIterators(
-    int nLoops, int nReduction) {
-  SmallVector<utils::IteratorType, 3> res(nLoops - nReduction,
-                                          utils::IteratorType::parallel);
-  res.append(nReduction, utils::IteratorType::reduction);
-  return res;
-}
-
-SmallVector<utils::IteratorType, 3> getNParallelLoopsAttrs(int nParallelLoops) {
-  return getParallelAndReductionIterators(nParallelLoops, 0);
-}
-
-// Holds a static extent or Value for dynamic extents.
-class Extent {
- public:
-  Extent() {}
-  Extent(int64_t extent) : extent(extent) {}
-  Extent(Value value) : value(value) {}
-
-  bool isStatic() const { return !value; }
-  bool isUnitExtent() const { return isStatic() && getStatic() == 1; }
-  int64_t getStatic() const {
-    assert(isStatic());
-    return extent;
-  }
-  Value getValue() const {
-    assert(!isStatic());
-    return value;
-  }
-
-  Value convertToValue(OpBuilder &builder, Location loc) {
-    if (!isStatic()) return getValue();
-    return builder.create<arith::ConstantIndexOp>(loc, getStatic());
-  }
-
- private:
-  int64_t extent;
-  Value value;
-};
-
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
-                                     const Extent &extent) {
-  if (extent.isStatic()) {
-    os << "DIM[" << extent.getStatic() << "]";
-  } else {
-    os << "DIM[" << extent.getValue() << "]";
-  }
-  return os;
-}
-
-Value broadcast(OpBuilder &builder, Location loc, Value operand,
-                SmallVectorImpl<Extent> &resultExtents,
-                SmallVectorImpl<bool> &isExpansion) {
-  auto operandType = llvm::cast<RankedTensorType>(operand.getType());
-  SmallVector<int64_t> resultShape;
-  SmallVector<Value> dynDims;
-  for (Extent &dim : resultExtents) {
-    if (dim.isStatic()) {
-      resultShape.push_back(dim.getStatic());
-    } else {
-      resultShape.push_back(ShapedType::kDynamic);
-      dynDims.push_back(dim.getValue());
-    }
-  }
-
-  // Traverse the right aligned operand dimensions and form expressions.
-  // We keep 1-dims in place instead of reshaping them away, relying on the
-  // DropUnitDims pass to run later.
-  SmallVector<AffineExpr> dimExprs;
-  dimExprs.reserve(operandType.getRank());
-  for (int i = resultExtents.size() - operandType.getRank();
-       i < resultExtents.size(); ++i) {
-    if (isExpansion[i]) {
-      dimExprs.push_back(builder.getAffineConstantExpr(0));
-    } else {
-      dimExprs.push_back(builder.getAffineDimExpr(i));
-    }
-  }
-
-  int nloops = resultExtents.size();
-  Value init = builder.create<tensor::EmptyOp>(
-      loc, resultShape, operandType.getElementType(), dynDims);
-  auto generic = builder.create<linalg::GenericOp>(
-      loc, TypeRange{init.getType()}, ValueRange{operand},
-      /*outputBuffers=*/ValueRange{init},
-      llvm::ArrayRef({
-          AffineMap::get(/*dimCount=*/nloops, /*symbolCount=*/0, dimExprs,
-                         builder.getContext()),
-          builder.getMultiDimIdentityMap(nloops),
-      }),
-      getNParallelLoopsAttrs(nloops),
-      [&](OpBuilder &nestedBuilder, Location nestedLoc, ValueRange args) {
-        nestedBuilder.create<linalg::YieldOp>(loc, *args.begin());
-      });
-  return generic.getResult(0);
-}
-
-Value broadcastScalar(OpBuilder &builder, Location loc, Value scalarValue,
-                      SmallVectorImpl<Extent> &resultExtents) {
-  SmallVector<bool> isExpansion(resultExtents.size());
-  for (int i = 0, e = resultExtents.size(); i < e; ++i) {
-    isExpansion[i] = true;
-  }
-  return broadcast(builder, loc, scalarValue, resultExtents, isExpansion);
-}
-
-std::optional<Extent> computeBinaryResultExtent(OpBuilder &builder,
-                                                Location loc, Extent &lhsDim,
-                                                Extent &rhsDim,
-                                                bool &isLhsExpansion,
-                                                bool &isRhsExpansion) {
-  if (lhsDim.isStatic() && rhsDim.isStatic()) {
-    // Both are static. Just check.
-    if (lhsDim.getStatic() != rhsDim.getStatic() &&
-        !(lhsDim.getStatic() == 1 || rhsDim.getStatic() == 1)) {
-      // Statically illegal.
-      emitError(loc) << "cannot broadcast extents of differing size unless "
-                        "if one of them is 1 (got "
-                     << lhsDim.getStatic() << ", " << rhsDim.getStatic() << ")";
-      return std::nullopt;
-    }
-
-    // Static expansions.
-    if (lhsDim.isUnitExtent() && rhsDim.isUnitExtent()) {
-      // For the fully static case, we can trivially check the 1-equality,
-      // and know we are not expanding.
-      isLhsExpansion = false;
-      isRhsExpansion = false;
-    } else {
-      // Otherwise, mark the dim as expanding if it is 1.
-      isLhsExpansion = lhsDim.isUnitExtent();
-      isRhsExpansion = rhsDim.isUnitExtent();
-    }
-    return Extent(std::max(lhsDim.getStatic(), rhsDim.getStatic()));
-  }
-
-  // At least one of them is dynamic.
-  // Branch on whether one of them is a static-1, which is the only case
-  // we allow for dynamic expansion.
-  if (lhsDim.isUnitExtent() || rhsDim.isUnitExtent()) {
-    if (lhsDim.isUnitExtent()) {
-      isLhsExpansion = true;
-      isRhsExpansion = false;
-      return rhsDim;
-    } else {
-      isLhsExpansion = false;
-      isRhsExpansion = true;
-      return lhsDim;
-    }
-  }
-
-  // At least one is dynamic and neither are a static 1.
-  // In this case, we do not allow either to be an expanding dim and
-  // error if this is the case at runtime.
-  isLhsExpansion = false;
-  isRhsExpansion = false;
-  Value lhsExtentValue = lhsDim.convertToValue(builder, loc);
-  Value rhsExtentValue = rhsDim.convertToValue(builder, loc);
-
-  Value isEqual = builder.create<arith::CmpIOp>(loc, arith::CmpIPredicate::eq,
-                                                lhsExtentValue, rhsExtentValue);
-  builder.create<cf::AssertOp>(
-      loc, isEqual,
-      builder.getStringAttr("mismatched dynamic broadcast extents"));
-
-  // Here, if one of them is static, that has to be the result extent
-  // (because we checked the error condition above).
-  if (lhsDim.isStatic()) {
-    return Extent(lhsDim.getStatic());
-  } else if (rhsDim.isStatic()) {
-    return Extent(rhsDim.getStatic());
-  }
-
-  // Both are dynamic. Compute the max.
-  return Extent(lhsExtentValue);
-}
-
-std::optional<Extent> computeTernaryResultExtent(OpBuilder &builder,
-                                                 Location loc, Extent &aValue,
-                                                 Extent &bValue, Extent &cValue,
-                                                 bool &isAExpansion,
-                                                 bool &isBExpansion,
-                                                 bool &isCExpansion) {
-  // Collect non unit extents (which includes, implicitly, dynamic dims).
-  SmallVector<Extent> nonUnitExtents;
-  if (!aValue.isUnitExtent()) nonUnitExtents.push_back(aValue);
-  if (!bValue.isUnitExtent()) nonUnitExtents.push_back(bValue);
-  if (!cValue.isUnitExtent()) nonUnitExtents.push_back(cValue);
-
-  // Early exit if all unit extents.
-  if (nonUnitExtents.empty()) {
-    isAExpansion = false;
-    isBExpansion = false;
-    isCExpansion = false;
-    return aValue;
-  }
-
-  // Are any a unit?
-  bool hasUnitExtent = false;
-  if (aValue.isUnitExtent()) hasUnitExtent = true;
-  if (bValue.isUnitExtent()) hasUnitExtent = true;
-  if (cValue.isUnitExtent()) hasUnitExtent = true;
-
-  // Mark expansion for any unit.
-  if (hasUnitExtent) {
-    if (aValue.isUnitExtent()) isAExpansion = true;
-    if (bValue.isUnitExtent()) isBExpansion = true;
-    if (cValue.isUnitExtent()) isCExpansion = true;
-  }
-
-  // By default, compare against the first non unit extent; however, prefer
-  // a static extent if present.
-  int nonUnitCompareExtentIndex = 0;
-  for (int i = 0, e = nonUnitExtents.size(); i < e; i++) {
-    if (nonUnitExtents[i].isStatic()) nonUnitCompareExtentIndex = i;
-  }
-
-  // Generate checks for each non unit extent.
-  for (int i = 0, e = nonUnitExtents.size(); i < e; i++) {
-    if (i == nonUnitCompareExtentIndex) continue;
-    Extent &cmpLhs = nonUnitExtents[nonUnitCompareExtentIndex];
-    Extent &cmpRhs = nonUnitExtents[i];
-    // Static check.
-    if (cmpLhs.isStatic() && cmpRhs.isStatic()) {
-      if (cmpLhs.getStatic() != cmpRhs.getStatic()) {
-        // Statically illegal.
-        emitError(loc) << "cannot broadcast extents of differing size unless "
-                          "if one of them is 1 (got "
-                       << cmpLhs.getStatic() << ", " << cmpRhs.getStatic()
-                       << ")";
-        return std::nullopt;
-      }
-      continue;
-    }
-    // Dynamic check.
-    Value cmpLhsValue = cmpLhs.convertToValue(builder, loc);
-    Value cmpRhsValue = cmpRhs.convertToValue(builder, loc);
-    Value isEqual = builder.create<arith::CmpIOp>(loc, arith::CmpIPredicate::eq,
-                                                  cmpLhsValue, cmpRhsValue);
-    builder.create<cf::AssertOp>(
-        loc, isEqual,
-        builder.getStringAttr("mismatched dynamic broadcast extents"));
-  }
-
-  // The result must be one of the non unit extents. Just take the one
-  // used for comparison.
-  return nonUnitExtents[nonUnitCompareExtentIndex];
-}
-
-void padExtents(SmallVectorImpl<Extent> &extents, int size) {
-  for (int i = 0; i < size; ++i) {
-    extents.push_back({1});
-  }
-}
-
-void appendExtents(OpBuilder &builder, Location loc,
-                   SmallVectorImpl<Extent> &extents, Value v,
-                   RankedTensorType t) {
-  for (int i = 0; i < t.getRank(); ++i) {
-    if (t.isDynamicDim(i)) {
-      // Emit a dim op.
-      Value dim = builder.create<tensor::DimOp>(loc, v, i);
-      extents.push_back(dim);
-    } else {
-      // Static dim.
-      extents.push_back({t.getDimSize(i)});
-    }
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Structural op conversions
-// -----------------------------------------------------------------------------
-
-struct ConvertConstantLikeOp
-    : public OpConversionPattern<chlo::ConstantLikeOp> {
-  using OpConversionPattern<chlo::ConstantLikeOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      chlo::ConstantLikeOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto resultTy = llvm::cast<RankedTensorType>(op.getType());
-    if (!resultTy.hasRank())
-      return rewriter.notifyMatchFailure(op, "only supports ranked");
-    // Lower to MHLO constant if statically shaped.
-    if (resultTy.hasStaticShape()) {
-      rewriter.replaceOpWithNewOp<mhlo::ConstantOp>(
-          op, DenseElementsAttr::get(resultTy, op.getValue()));
-      return success();
-    }
-
-    Location loc = op.getLoc();
-
-    int resultRank = resultTy.getRank();
-    SmallVector<Extent> resultExtents;
-    resultExtents.reserve(resultRank);
-    appendExtents(rewriter, loc, resultExtents, adaptor.getOperand(), resultTy);
-
-    auto resultTy0D = RankedTensorType::get({}, resultTy.getElementType());
-    Value scalarConst = rewriter.create<mhlo::ConstantOp>(
-        loc, DenseElementsAttr::get(resultTy0D, op.getValue()));
-    Value broadcasted =
-        broadcastScalar(rewriter, loc, scalarConst, resultExtents);
-    rewriter.replaceOp(op, {broadcasted});
-    return success();
-  }
-};
-
-// -----------------------------------------------------------------------------
-// Binary broadcasting op conversions
-// -----------------------------------------------------------------------------
-
-// Adapter base class for adapting binary elementwise broadcasting ops
-// via generic patterns. Implemented as a virtual class in order to reduce
-// high fanout template instantiations.
-struct BinaryBroadcastingAdaptor {
-  using BroadcastValues = std::pair<Value, Value>;
-  virtual ~BinaryBroadcastingAdaptor() = default;
-  virtual StringRef getFromOperationName() = 0;
-  virtual LogicalResult verifyBroadcastCompatibility(
-      Operation *op, ArrayRef<Value> operands) = 0;
-  virtual BroadcastValues getFromBroadcastValues(Operation *op,
-                                                 ArrayRef<Value> operands) = 0;
-  virtual Operation *createTargetOperation(Location loc, Operation *op,
-                                           Type resultType,
-                                           ArrayRef<Value> operands,
-                                           BroadcastValues broadcastValues,
-                                           OpBuilder &builder) = 0;
-};
-
-// Adaptor for simple binary elementwise operations which have exactly two
-// operands and are matched from src -> target by name.
-template <typename FromOpTy, typename ToOpTy>
-struct SimpleBinaryBroadcastingAdaptor : public BinaryBroadcastingAdaptor {
-  static BinaryBroadcastingAdaptor &getInstance() {
-    static SimpleBinaryBroadcastingAdaptor<FromOpTy, ToOpTy> instance;
-    return instance;
-  }
-  StringRef getFromOperationName() override {
-    return FromOpTy::getOperationName();
-  }
-  LogicalResult verifyBroadcastCompatibility(
-      Operation *op, ArrayRef<Value> operands) override {
-    auto broadcastDimensions =
-        llvm::cast<FromOpTy>(op).getBroadcastDimensions();
-    if (broadcastDimensions &&
-        !hlo::isLegalNumpyRankedBroadcast(operands[0], operands[1],
-                                          *broadcastDimensions)) {
-      return failure();
-    }
-    return success();
-  }
-  BroadcastValues getFromBroadcastValues(Operation *op,
-                                         ArrayRef<Value> operands) override {
-    assert(operands.size() == 2);
-    return std::make_pair(operands[0], operands[1]);
-  }
-  Operation *createTargetOperation(Location loc, Operation *op, Type resultType,
-                                   ArrayRef<Value> operands,
-                                   BroadcastValues broadcastValues,
-                                   OpBuilder &builder) override {
-    return builder.create<ToOpTy>(loc, resultType, broadcastValues.first,
-                                  broadcastValues.second);
-  }
-};
-
-struct CompareBinaryBroadcastingAdaptor : public BinaryBroadcastingAdaptor {
-  static BinaryBroadcastingAdaptor &getInstance() {
-    static CompareBinaryBroadcastingAdaptor instance;
-    return instance;
-  }
-  StringRef getFromOperationName() override {
-    return chlo::BroadcastCompareOp::getOperationName();
-  }
-  LogicalResult verifyBroadcastCompatibility(
-      Operation *op, ArrayRef<Value> operands) override {
-    auto broadcastDimensions =
-        llvm::cast<chlo::BroadcastCompareOp>(op).getBroadcastDimensions();
-    if (broadcastDimensions &&
-        !hlo::isLegalNumpyRankedBroadcast(operands[0], operands[1],
-                                          *broadcastDimensions)) {
-      return failure();
-    }
-    return success();
-  }
-  BroadcastValues getFromBroadcastValues(Operation *op,
-                                         ArrayRef<Value> operands) override {
-    chlo::BroadcastCompareOpAdaptor adaptor(operands, op->getAttrDictionary());
-    return std::make_pair(adaptor.getLhs(), adaptor.getRhs());
-  }
-  Operation *createTargetOperation(Location loc, Operation *op, Type resultType,
-                                   ArrayRef<Value> operands,
-                                   BroadcastValues broadcastValues,
-                                   OpBuilder &builder) override {
-    chlo::BroadcastCompareOpAdaptor adaptor(operands, op->getAttrDictionary());
-    std::optional<chlo::ComparisonType> chloCmpType = adaptor.getCompareType();
-    mhlo::ComparisonTypeAttr mhloCmpType;
-    if (chloCmpType)
-      mhloCmpType = mhlo::ComparisonTypeAttr::get(
-          builder.getContext(), *chlo::mhloComparisonType(*chloCmpType));
-    return builder.create<mhlo::CompareOp>(
-        loc, resultType, broadcastValues.first, broadcastValues.second,
-        *chlo::mhloComparisonDirection(adaptor.getComparisonDirection()),
-        mhloCmpType);
-  }
-};
-
-struct ConvertRankedBroadcastBinaryOp : public ConversionPattern {
-  ConvertRankedBroadcastBinaryOp(MLIRContext *context,
-                                 TypeConverter &typeConverter,
-                                 PatternBenefit benefit,
-                                 BinaryBroadcastingAdaptor &bcastAdaptor)
-      : ConversionPattern(typeConverter, bcastAdaptor.getFromOperationName(),
-                          benefit, context),
-        bcastAdaptor(bcastAdaptor) {}
-
-  LogicalResult matchAndRewrite(
-      Operation *op, ArrayRef<Value> operands,
-      ConversionPatternRewriter &rewriter) const override {
-    auto loc = op->getLoc();
-    // Only rewrite for statically determinable non-broadcasting cases.
-    auto bcastOperands = bcastAdaptor.getFromBroadcastValues(op, operands);
-    Value lhs = bcastOperands.first;
-    Value rhs = bcastOperands.second;
-    auto lhsType = llvm::dyn_cast<RankedTensorType>(lhs.getType());
-    auto rhsType = llvm::dyn_cast<RankedTensorType>(rhs.getType());
-    if (!lhsType || !rhsType)
-      return rewriter.notifyMatchFailure(op, "not ranked tensors");
-
-    if (failed(bcastAdaptor.verifyBroadcastCompatibility(op, operands))) {
-      return rewriter.notifyMatchFailure(op, "not legal broadcasting");
-    }
-    if (!isElementTypeLegalForCodegen(lhsType.getElementType()) ||
-        !isElementTypeLegalForCodegen(rhsType.getElementType())) {
-      return rewriter.notifyMatchFailure(op,
-                                         "not legal element type for codegen");
-    }
-
-    // Extract the original extents.
-    SmallVector<Extent> lhsOrigExtents;
-    lhsOrigExtents.reserve(lhsType.getRank());
-    appendExtents(rewriter, loc, lhsOrigExtents, lhs, lhsType);
-    SmallVector<Extent> rhsOrigExtents;
-    rhsOrigExtents.reserve(rhsType.getRank());
-    appendExtents(rewriter, loc, rhsOrigExtents, rhs, rhsType);
-
-    // Left pad with 1-extents to the result rank.
-    int resultRank = std::max(lhsType.getRank(), rhsType.getRank());
-    SmallVector<Extent> lhsBcastExtents;
-    lhsBcastExtents.reserve(resultRank);
-    SmallVector<Extent> rhsBcastExtents;
-    rhsBcastExtents.reserve(resultRank);
-    padExtents(lhsBcastExtents, resultRank - lhsType.getRank());
-    lhsBcastExtents.append(lhsOrigExtents);
-    padExtents(rhsBcastExtents, resultRank - rhsType.getRank());
-    rhsBcastExtents.append(rhsOrigExtents);
-
-    // Compute the result extents.
-    SmallVector<Extent> resultExtents(resultRank);
-    SmallVector<bool> isLhsExpansion(resultRank);
-    SmallVector<bool> isRhsExpansion(resultRank);
-    bool lhsNeedsBroadcast = resultRank != lhsType.getRank();
-    bool rhsNeedsBroadcast = resultRank != rhsType.getRank();
-    for (int i = 0; i < resultRank; i++) {
-      auto resultExtent = computeBinaryResultExtent(
-          rewriter, loc, lhsBcastExtents[i], rhsBcastExtents[i],
-          isLhsExpansion[i], isRhsExpansion[i]);
-      if (!resultExtent) {
-        return rewriter.notifyMatchFailure(op,
-                                           "could not compute result extent");
-      }
-      resultExtents[i] = *resultExtent;
-      if (isLhsExpansion[i]) lhsNeedsBroadcast = true;
-      if (isRhsExpansion[i]) rhsNeedsBroadcast = true;
-    }
-
-    // Broadcast the operands.
-    Value lhsBcast =
-        lhsNeedsBroadcast
-            ? broadcast(rewriter, loc, lhs, resultExtents, isLhsExpansion)
-            : lhs;
-    Value rhsBcast =
-        rhsNeedsBroadcast
-            ? broadcast(rewriter, loc, rhs, resultExtents, isRhsExpansion)
-            : rhs;
-
-    // TODO: Don't do this result type change.
-    rewriter.replaceOp(op,
-                       bcastAdaptor
-                           .createTargetOperation(
-                               loc, op, op->getResult(0).getType(), operands,
-                               std::make_pair(lhsBcast, rhsBcast), rewriter)
-                           ->getResults());
-    return success();
-  }
-
-  BinaryBroadcastingAdaptor &bcastAdaptor;
-};
-
-// Converts binary ops that statically are determined to not broadcast directly
-// to the corresponding mhlo non-broadcasting op.
-struct ConvertTrivialNonBroadcastBinaryOp : public ConversionPattern {
-  ConvertTrivialNonBroadcastBinaryOp(MLIRContext *context,
-                                     TypeConverter &typeConverter,
-                                     PatternBenefit benefit,
-                                     BinaryBroadcastingAdaptor &bcastAdaptor)
-      : ConversionPattern(typeConverter, bcastAdaptor.getFromOperationName(),
-                          benefit, context),
-        bcastAdaptor(bcastAdaptor) {}
-
-  LogicalResult matchAndRewrite(
-      Operation *op, ArrayRef<Value> operands,
-      ConversionPatternRewriter &rewriter) const override {
-    // Only rewrite for statically determinable non-broadcasting cases.
-    auto bcastOperands = bcastAdaptor.getFromBroadcastValues(op, operands);
-    auto lhsType =
-        llvm::dyn_cast<RankedTensorType>(bcastOperands.first.getType());
-    auto rhsType =
-        llvm::dyn_cast<RankedTensorType>(bcastOperands.second.getType());
-    if (!lhsType || !rhsType)
-      return rewriter.notifyMatchFailure(op, "not ranked tensors");
-    if (!isElementTypeLegalForCodegen(lhsType.getElementType()) ||
-        !isElementTypeLegalForCodegen(rhsType.getElementType())) {
-      return rewriter.notifyMatchFailure(op,
-                                         "not legal element type for codegen");
-    }
-
-    // Requires rank broadcast.
-    if (lhsType.getRank() != rhsType.getRank())
-      return rewriter.notifyMatchFailure(op, "not same rank");
-    // Any dynamic dimension may require broadcasting and requires more
-    // analysis.
-    if (!lhsType.hasStaticShape() || !rhsType.hasStaticShape())
-      return rewriter.notifyMatchFailure(op, "not static shapes");
-
-    for (auto [lhsExtent, rhsExtent] :
-         llvm::zip_equal(lhsType.getShape(), rhsType.getShape())) {
-      if (lhsExtent != rhsExtent) {
-        return rewriter.notifyMatchFailure(op, "not equal extents");
-      }
-    }
-
-    if (failed(bcastAdaptor.verifyBroadcastCompatibility(op, operands))) {
-      return rewriter.notifyMatchFailure(op, "not legal broadcasting");
-    }
-
-    rewriter.replaceOp(op, bcastAdaptor
-                               .createTargetOperation(
-                                   op->getLoc(), op, op->getResult(0).getType(),
-                                   operands, bcastOperands, rewriter)
-                               ->getResults());
-    return success();
-  }
-
-  BinaryBroadcastingAdaptor &bcastAdaptor;
-};
-
-// -----------------------------------------------------------------------------
-// Ternary broadcasting op conversions
-// -----------------------------------------------------------------------------
-
-// Sepecial case conversion for the BroadcastSelectOp into primitives.
-// This follows the new convention of SelectV2, which allows a true ternary
-// select (whereas the original definition only supported one broadcasting
-// value).
-struct ConvertSelectOp : public OpConversionPattern<chlo::BroadcastSelectOp> {
-  using OpConversionPattern<chlo::BroadcastSelectOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      chlo::BroadcastSelectOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    // Only support ranked operands.
-    Value pred = adaptor.getPred();
-    Value thenValue = adaptor.getOnTrue();
-    Value elseValue = adaptor.getOnFalse();
-    auto predType = llvm::dyn_cast<RankedTensorType>(pred.getType());
-    auto thenType = llvm::dyn_cast<RankedTensorType>(thenValue.getType());
-    auto elseType = llvm::dyn_cast<RankedTensorType>(elseValue.getType());
-    auto resultType =
-        llvm::dyn_cast<RankedTensorType>(op.getResult().getType());
-    if (!predType || !thenType || !elseType || !resultType) {
-      return rewriter.notifyMatchFailure(op, "cannot convert unranked tensors");
-    }
-    if (!isElementTypeLegalForCodegen(resultType.getElementType())) {
-      return rewriter.notifyMatchFailure(op,
-                                         "not legal element type for codegen");
-    }
-
-    // Short-circuit if all types are statically equal.
-    if (predType == thenType && predType == elseType) {
-      // No broadcasting. This includes the 0d -> 0d case.
-      rewriter.replaceOpWithNewOp<mhlo::SelectOp>(op, resultType, pred,
-                                                  thenValue, elseValue);
-      return success();
-    }
-
-    // Full ternary broadcast. See ConvertBroadcastBinaryOp for the
-    // simplified version.
-    // Extract the original extents.
-    SmallVector<Extent> predOrigExtents;
-    predOrigExtents.reserve(predType.getRank());
-    appendExtents(rewriter, loc, predOrigExtents, pred, predType);
-    SmallVector<Extent> thenOrigExtents;
-    thenOrigExtents.reserve(thenType.getRank());
-    appendExtents(rewriter, loc, thenOrigExtents, thenValue, thenType);
-    SmallVector<Extent> elseOrigExtents;
-    elseOrigExtents.reserve(elseType.getRank());
-    appendExtents(rewriter, loc, elseOrigExtents, elseValue, elseType);
-
-    // Left pad with 1-extents to the result rank.
-    int resultRank = std::max(std::max(predType.getRank(), thenType.getRank()),
-                              elseType.getRank());
-    SmallVector<Extent> predBcastExtents;
-    predBcastExtents.reserve(resultRank);
-    padExtents(predBcastExtents, resultRank - predType.getRank());
-    predBcastExtents.append(predOrigExtents);
-
-    SmallVector<Extent> thenBcastExtents;
-    thenBcastExtents.reserve(resultRank);
-    padExtents(thenBcastExtents, resultRank - thenType.getRank());
-    thenBcastExtents.append(thenOrigExtents);
-
-    SmallVector<Extent> elseBcastExtents;
-    elseBcastExtents.reserve(resultRank);
-    padExtents(elseBcastExtents, resultRank - elseType.getRank());
-    elseBcastExtents.append(elseOrigExtents);
-
-    // Compute the result extents.
-    SmallVector<Extent> resultExtents(resultRank);
-    SmallVector<bool> isPredExpansion(resultRank);
-    SmallVector<bool> isThenExpansion(resultRank);
-    SmallVector<bool> isElseExpansion(resultRank);
-    bool predNeedsBroadcast = resultRank != predType.getRank();
-    bool thenNeedsBroadcast = resultRank != thenType.getRank();
-    bool elseNeedsBroadcast = resultRank != elseType.getRank();
-    for (int i = 0; i < resultRank; i++) {
-      auto resultExtent = computeTernaryResultExtent(
-          rewriter, loc, predBcastExtents[i], thenBcastExtents[i],
-          elseBcastExtents[i], isPredExpansion[i], isThenExpansion[i],
-          isElseExpansion[i]);
-      if (!resultExtent) {
-        return rewriter.notifyMatchFailure(op,
-                                           "could not compute result extent");
-      }
-      resultExtents[i] = *resultExtent;
-      if (isPredExpansion[i]) predNeedsBroadcast = true;
-      if (isThenExpansion[i]) thenNeedsBroadcast = true;
-      if (isElseExpansion[i]) elseNeedsBroadcast = true;
-    }
-
-    // Broadcast all.
-    Value predBcast =
-        predNeedsBroadcast
-            ? broadcast(rewriter, loc, pred, resultExtents, isPredExpansion)
-            : pred;
-    Value thenBcast = thenNeedsBroadcast
-                          ? broadcast(rewriter, loc, thenValue, resultExtents,
-                                      isThenExpansion)
-                          : thenValue;
-    Value elseBcast = elseNeedsBroadcast
-                          ? broadcast(rewriter, loc, elseValue, resultExtents,
-                                      isElseExpansion)
-                          : elseValue;
-
-    rewriter.replaceOpWithNewOp<mhlo::SelectOp>(op, resultType, predBcast,
-                                                thenBcast, elseBcast);
-    return success();
-  }
-};
-
-// Fallback conversion of mhlo.dynamic_reshape to flow.tensor.reshape.
-// This is not the most optimal way to lower most reshapes, and higher
-// benefit patterns should match more specific ops and lower them to
-// Linalg expanding and contracting reshapes.
-//
-// Note that as a low-level op, it is assumed that invariants have been
-// satisfied externally in some fashion and further checks are not inserted
-// at this time. This may need to be re-evaluated as more user-driven
-// reshapes are permitted.
-struct ConvertDynamicReshapeOp
-    : public OpConversionPattern<mhlo::DynamicReshapeOp> {
-  using OpConversionPattern<mhlo::DynamicReshapeOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::DynamicReshapeOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-    Value input = adaptor.getOperand();
-    Value outputShape = adaptor.getOutputShape();
-    auto outputShapeType =
-        llvm::dyn_cast<RankedTensorType>(outputShape.getType());
-    auto resultType = llvm::dyn_cast_if_present<RankedTensorType>(
-        typeConverter->convertType(op.getType()));
-    if (!outputShapeType || !resultType) {
-      return rewriter.notifyMatchFailure(op, "not ranked");
-    }
-    SmallVector<Value> targetDims;
-    assert(resultType.getRank() == outputShapeType.getNumElements() &&
-           "mismatched rank");
-    for (int i = 0, e = resultType.getRank(); i < e; ++i) {
-      if (resultType.isDynamicDim(i)) {
-        Value index = rewriter.create<arith::ConstantIndexOp>(loc, i);
-        targetDims.push_back(
-            rewriter.create<tensor::ExtractOp>(loc, outputShape, index));
-      }
-    }
-
-    SmallVector<Value> castedTargetDims;
-    for (Value dim : targetDims) {
-      if (llvm::isa<IntegerType>(dim.getType())) {
-        dim = rewriter.create<arith::IndexCastOp>(loc, rewriter.getIndexType(),
-                                                  dim);
-      }
-      castedTargetDims.push_back(dim);
-    }
-
-    rewriter.replaceOpWithNewOp<IREE::Flow::TensorReshapeOp>(
-        op, resultType, input, castedTargetDims);
-    return success();
-  }
-};
-
-}  // namespace
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
-
-void mlir::iree_compiler::MHLO::populateMHLOBroadcastingToLinalgPatterns(
-    MLIRContext *context, TypeConverter &typeConverter,
-    RewritePatternSet &patterns) {
-#define POPULATE_SIMPLE_BCAST(ChloOp, HloOp)                          \
-  patterns.insert<ConvertTrivialNonBroadcastBinaryOp>(                \
-      context, typeConverter, 10,                                     \
-      SimpleBinaryBroadcastingAdaptor<ChloOp, HloOp>::getInstance()); \
-  patterns.insert<ConvertRankedBroadcastBinaryOp>(                    \
-      context, typeConverter, 5,                                      \
-      SimpleBinaryBroadcastingAdaptor<ChloOp, HloOp>::getInstance());
-
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastAddOp, mhlo::AddOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastAndOp, mhlo::AndOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastAtan2Op, mhlo::Atan2Op);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastComplexOp, mhlo::ComplexOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastDivOp, mhlo::DivOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastMaxOp, mhlo::MaxOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastMinOp, mhlo::MinOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastMulOp, mhlo::MulOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastOrOp, mhlo::OrOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastPolygammaOp, chlo::PolygammaOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastPowOp, mhlo::PowOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastRemOp, mhlo::RemOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastShiftLeftOp, mhlo::ShiftLeftOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastShiftRightArithmeticOp,
-                        mhlo::ShiftRightArithmeticOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastShiftRightLogicalOp,
-                        mhlo::ShiftRightLogicalOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastSubOp, mhlo::SubtractOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastXorOp, mhlo::XorOp);
-  POPULATE_SIMPLE_BCAST(chlo::BroadcastZetaOp, chlo::ZetaOp);
-
-  // Special case for Compare (not a simple signature).
-  patterns.insert<ConvertTrivialNonBroadcastBinaryOp>(
-      context, typeConverter, 10,
-      CompareBinaryBroadcastingAdaptor::getInstance());
-  patterns.insert<ConvertRankedBroadcastBinaryOp>(
-      context, typeConverter, 5,
-      CompareBinaryBroadcastingAdaptor::getInstance());
-
-  // Other ops.
-  // TODO: Remove the benefit after it is removed upstream.
-  patterns.insert<ConvertSelectOp>(typeConverter, context, 1000);
-  patterns.insert<ConvertConstantLikeOp>(typeConverter, context);
-  patterns.insert<ConvertDynamicReshapeOp>(typeConverter, context);
-
-  // Make mixed scalar broadcasting of Clamp explicit.
-  // NOTE: Because we are doing a full conversion out of HLO, we do not use
-  // the corresponding setup legality, since that explicitly marks clamp as
-  // conditionally legal.
-  // TODO: Rename this upstream or find a better place to shove it.
-  mhlo::populateMaterializeBroadcastsPatterns(context, &patterns);
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/CMakeLists.txt b/compiler/src/iree/compiler/InputConversion/MHLO/CMakeLists.txt
deleted file mode 100644
index faf680c..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/CMakeLists.txt
+++ /dev/null
@@ -1,112 +0,0 @@
-################################################################################
-# Autogenerated by build_tools/bazel_to_cmake/bazel_to_cmake.py from           #
-# compiler/src/iree/compiler/InputConversion/MHLO/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_tablegen_library(
-  NAME
-    PassesIncGen
-  TD_FILE
-    "Passes.td"
-  OUTS
-    --gen-pass-decls Passes.h.inc
-)
-
-iree_cc_library(
-  NAME
-    PassHeaders
-  HDRS
-    "PassDetail.h"
-    "Passes.h"
-    "Passes.h.inc"
-    "Rewriters.h"
-  DEPS
-    ::PassesIncGen
-    MLIRPass
-    MLIRTransforms
-  PUBLIC
-)
-
-iree_cc_library(
-  NAME
-    MHLO
-  HDRS
-    "Passes.h"
-  SRCS
-    "BroadcastingToLinalgPatterns.cpp"
-    "ConvertCollectiveOps.cpp"
-    "ConvertComplexToReal.cpp"
-    "ConvertMHLOToFlow.cpp"
-    "ConvertMHLOToFlow.h"
-    "ConvertMHLOToLinalgExt.cpp"
-    "ConvertMHLOToStableHLO.cpp"
-    "FlattenTuplesInCFG.cpp"
-    "MHLOToLinalgOnTensors.cpp"
-    "MHLOToMHLOPreprocessing.cpp"
-    "Passes.cpp"
-    "VerifyCompilerMHLOInputLegality.cpp"
-  DEPS
-    ::PassHeaders
-    ::PassesIncGen
-    ChloOps
-    ChloPasses
-    IREELinalgExtDialect
-    IREELinalgExtPasses
-    LLVMSupport
-    MLIRAffineDialect
-    MLIRAffineUtils
-    MLIRArithDialect
-    MLIRComplexDialect
-    MLIRControlFlowDialect
-    MLIRFuncDialect
-    MLIRIR
-    MLIRLinalgDialect
-    MLIRLinalgTransforms
-    MLIRMLProgramDialect
-    MLIRMathDialect
-    MLIRMemRefDialect
-    MLIRMhloUtils
-    MLIRPass
-    MLIRReconcileUnrealizedCasts
-    MLIRSCFToControlFlow
-    MLIRSCFTransforms
-    MLIRShapeDialect
-    MLIRShapeOpsTransforms
-    MLIRShapeToStandard
-    MLIRSupport
-    MLIRTensorDialect
-    MLIRTensorUtils
-    MLIRTransforms
-    MhloDialect
-    MhloPasses
-    MhloShapeOpsToStandard
-    MhloToLinalg
-    MhloToStablehlo
-    MhloToStandard
-    StablehloBroadcastUtils
-    StablehloOps
-    StablehloToMhlo
-    iree::compiler::Dialect::Flow::IR
-    iree::compiler::Dialect::Util::IR
-    iree::compiler::Dialect::Util::Transforms
-    iree::compiler::InputConversion::Common
-    iree::compiler::Utils
-    tensorflow::external_mhlo_includes
-  DEFINES
-    "IREE_HAVE_MHLO_INPUT"
-  PUBLIC
-)
-
-### BAZEL_TO_CMAKE_PRESERVES_ALL_CONTENT_BELOW_THIS_LINE ###
-# TODO: For some reason, these dependencies are not being added automatically.
-add_dependencies(
-  iree_compiler_InputConversion_MHLO_PassHeaders
-  iree_compiler_InputConversion_MHLO_PassesIncGen
-)
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertCollectiveOps.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertCollectiveOps.cpp
deleted file mode 100644
index b68e843..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertCollectiveOps.cpp
+++ /dev/null
@@ -1,1010 +0,0 @@
-// 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 <optional>
-
-#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
-#include "iree/compiler/Dialect/Flow/IR/FlowTypes.h"
-#include "iree/compiler/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "iree/compiler/InputConversion/MHLO/Rewriters.h"
-#include "iree/compiler/Utils/IndexSet.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/Transforms/DialectConversion.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-// Work in progress. The implementation is planned as several stages.
-//
-// For the first stage, a few simplifications are made to support simple models.
-//
-//   1. Single stream with deterministic order of execution
-//   2. Single replica group for all collective ops
-//   3. Only replicas without partition_id used
-//
-// These allow us to use a default channel for all communications, and there is
-// 1:1 mapping from the replica IDs to the communication ranks. The attribute,
-// use_global_device_ids, is always set in this case.
-//
-// The next stage is to support multiple replica groups. This needs a channel
-// creation with a subset of processes, which should have another communication
-// among the group. A possible strategy is to have the root process in the group
-// (the first rank of the group) creates a channel and the other processes query
-// the channel info from the root process. A key-value store using gRPC might be
-// a good solution.
-//
-// Supporting partition_id comes next. This includes the support for various
-// mode combinations for cross-replica and cross partition communication. See
-// the stablehlo specification for more details about the different modes.
-
-namespace {
-
-static std::optional<IREE::Flow::CollectiveElementType>
-convertToFlowCollectiveElementType(Type type) {
-  if (type.isF32()) {
-    return IREE::Flow::CollectiveElementType::Float32;
-  }
-
-  if (type.isInteger(32)) {
-    if (type.isSignedInteger()) {
-      return IREE::Flow::CollectiveElementType::Sint32;
-    } else {
-      return IREE::Flow::CollectiveElementType::Uint32;
-    }
-  }
-
-  if (type.isF16()) {
-    return IREE::Flow::CollectiveElementType::Float16;
-  }
-
-  if (type.isInteger(8)) {
-    if (type.isSignedInteger()) {
-      return IREE::Flow::CollectiveElementType::Sint8;
-    } else {
-      return IREE::Flow::CollectiveElementType::Uint8;
-    }
-  }
-
-  if (type.isInteger(16)) {
-    if (type.isSignedInteger()) {
-      return IREE::Flow::CollectiveElementType::Sint16;
-    } else {
-      return IREE::Flow::CollectiveElementType::Uint16;
-    }
-  }
-
-  if (type.isBF16()) {
-    return IREE::Flow::CollectiveElementType::BFloat16;
-  }
-
-  if (type.isF64()) {
-    return IREE::Flow::CollectiveElementType::Float64;
-  }
-
-  if (type.isInteger(64)) {
-    if (type.isSignedInteger()) {
-      return IREE::Flow::CollectiveElementType::Sint64;
-    } else {
-      return IREE::Flow::CollectiveElementType::Uint64;
-    }
-  }
-
-  return std::nullopt;
-}
-
-static std::optional<IREE::Flow::CollectiveReductionOp>
-convertToFlowCollectiveReductionOp(const Operation &op) {
-  if (isa<mhlo::AddOp>(op)) {
-    return IREE::Flow::CollectiveReductionOp::ReductionSum;
-  } else if (isa<mhlo::MulOp>(op)) {
-    return IREE::Flow::CollectiveReductionOp::ReductionProduct;
-  } else if (isa<mhlo::MinOp>(op)) {
-    return IREE::Flow::CollectiveReductionOp::ReductionMinimum;
-  } else if (isa<mhlo::MaxOp>(op)) {
-    return IREE::Flow::CollectiveReductionOp::ReductionMaximum;
-  } else {
-    // TODO: we may be able to detect an average operation and convert it
-    // into IREE::Flow::CollectiveReductionOp::ReductionAverage.
-    return std::nullopt;
-  }
-}
-
-static IREE::Flow::CollectiveElementTypeAttr getCollectiveElementTypeAttr(
-    MLIRContext *context, RankedTensorType type) {
-  std::optional<IREE::Flow::CollectiveElementType> collectiveElemType =
-      convertToFlowCollectiveElementType(type.getElementType());
-  if (!collectiveElemType) {
-    return IREE::Flow::CollectiveElementTypeAttr();
-  }
-  return IREE::Flow::CollectiveElementTypeAttr::get(context,
-                                                    *collectiveElemType);
-}
-
-template <typename T>
-static LogicalResult checkCollectiveAttrs(T op, PatternRewriter &rewriter) {
-  // Note that the channel handle attribute consists of two 64-bit values,
-  // handle and type.
-  int64_t handle =
-      op.getChannelHandle() ? op.getChannelHandleAttr().getHandle() : 0;
-  if (handle <= 0) {
-    // When the channel handle attribute is not present, it means the
-    // handle (a.k.a. channel_id in stablehlo) is 0. When this case is combined
-    // with `use_global_device_ids=false`, the communication type is
-    // `cross-replica`, but since there is only one replica group, it is
-    // effectively the same as `flatten_ids`, which is supported.
-    if (op.getUseGlobalDeviceIds()) {
-      return rewriter.notifyMatchFailure(
-          op, "must not set use_global_device_ids when channel_id <= 0");
-    }
-  }
-
-  return success();
-}
-
-/// Returns `color` and `key` parameter values indexed by the rank of the
-/// participant in |baseChannel|.
-///
-/// Examples:
-///   (0),(1)     => colors=[0,1], keys=[0,0]
-///   (0,1),(2,3) => colors=[0,0,1,1], keys=[0,1,0,1]
-static std::pair<Value, Value> makeSplitColorAndKey(Location loc,
-                                                    Value baseChannel,
-                                                    DenseIntElementsAttr groups,
-                                                    OpBuilder &builder) {
-  IndexSet indexSet(loc, builder);
-  Value noColor = indexSet.get(-1);
-  if (!groups) return std::make_pair(noColor, noColor);
-
-  auto groupsType = llvm::cast<RankedTensorType>(groups.getType());
-  assert(groupsType.getRank() == 2);
-  int64_t rows = groupsType.getShape()[0];
-  int64_t cols = groupsType.getShape()[1];
-  auto values = groups.getValues<int64_t>();
-
-  // Find the max rank so we can size our tables. Today the tables are always
-  // dense starting from rank 0 but we could offset the rank lookup if for
-  // example all ranks started at some offset.
-  int64_t maxRank = 0;
-  for (int64_t rank : values) {
-    maxRank = std::max(maxRank, rank);
-  }
-
-  // Table of <color, key> pairs indexed by rank. -1 is used to indicate that
-  // a particular rank does not participate in any group.
-  SmallVector<Value> colorTable(maxRank + 1, noColor);
-  SmallVector<Value> keyTable(maxRank + 1, noColor);
-
-  // Sparsely populate table with each rank getting a color/key pair.
-  // Rows equate to colors (groups) and columns equate to keys (local ranks).
-  for (int64_t i = 0; i < rows; ++i) {
-    for (int64_t j = 0; j < cols; ++j) {
-      const int64_t index = i * cols + j;
-      int64_t rank = values[index];
-      // -1 represents a null value in a group, where the group does not
-      // fully occupy the space in the row, e.g., [[0,1,2,3], [4,5,-1,-1]].
-      if (rank != -1) {
-        colorTable[rank] = indexSet.get(i);
-        keyTable[rank] = indexSet.get(j);
-      }
-    }
-  }
-
-  // Lookup the color/key split parameters by indexing into the tables we
-  // generated from the static op information.
-  Value rank = builder.create<IREE::Flow::ChannelRankOp>(loc, baseChannel);
-  Value color =
-      builder.create<IREE::Util::SwitchOp>(loc, rank, noColor, colorTable);
-  Value key =
-      builder.create<IREE::Util::SwitchOp>(loc, rank, noColor, keyTable);
-  return std::make_pair(color, key);
-}
-
-static DenseIntElementsAttr convertToRankGroupsByCrossReplica(
-    DenseIntElementsAttr replicaGroups, int32_t numPartitions,
-    OpBuilder &builder) {
-  if (numPartitions <= 1) {
-    // Treat as a single partition.
-    return replicaGroups;
-  }
-
-  auto groupsType = llvm::cast<RankedTensorType>(replicaGroups.getType());
-  assert(groupsType.getRank() == 2);
-  int rows = groupsType.getShape()[0];
-  int cols = groupsType.getShape()[1];
-  auto values = replicaGroups.getValues<int64_t>();
-  SmallVector<Attribute> newValues;
-
-  // The number of groups is (rows * numPartitions).
-  for (int i = 0; i < rows; ++i) {
-    for (int p = 0; p < numPartitions; ++p) {
-      // Each group starts here. The group size is the same as the column size.
-      for (int j = 0; j < cols; ++j) {
-        const int index = i * cols + j;
-        const int64_t replicaId = values[index];
-        const int64_t value =
-            (replicaId == -1) ? -1 : replicaId * numPartitions + p;
-        newValues.push_back(builder.getI64IntegerAttr(value));
-      }
-    }
-  }
-
-  auto type =
-      RankedTensorType::get({rows * numPartitions, cols}, builder.getI64Type());
-  return DenseIntElementsAttr::get(type, newValues);
-}
-
-static DenseIntElementsAttr convertToRankGroupsByCrossPartition(
-    DenseIntElementsAttr partitionGroups, int32_t numReplicas,
-    OpBuilder &builder) {
-  if (numReplicas <= 1) {
-    // Treat as a single replica.
-    return partitionGroups;
-  }
-
-  auto groupsType = llvm::cast<RankedTensorType>(partitionGroups.getType());
-  assert(groupsType.getRank() == 2);
-  int rows = groupsType.getShape()[0];
-  int cols = groupsType.getShape()[1];
-  auto values = partitionGroups.getValues<int64_t>();
-  SmallVector<Attribute> newValues;
-  // partitionGroups must have unique elements and cover all partition_ids, so
-  // numPartitions == values.size().
-  int64_t numPartitions = values.size();
-
-  // The number of groups is (rows * numReplicas).
-  for (int i = 0; i < rows; ++i) {
-    for (int r = 0; r < numReplicas; ++r) {
-      // Each group starts here. The group size is the same as the column size.
-      for (int j = 0; j < cols; ++j) {
-        const int index = i * cols + j;
-        const int64_t partitionId = values[index];
-        const int64_t value =
-            (partitionId == -1) ? -1 : r * numPartitions + partitionId;
-
-        newValues.push_back(builder.getI64IntegerAttr(value));
-      }
-    }
-  }
-
-  auto type =
-      RankedTensorType::get({rows * numReplicas, cols}, builder.getI64Type());
-  return DenseIntElementsAttr::get(type, newValues);
-}
-
-static DenseIntElementsAttr convertToRankGroupsByCrossReplicaAndPartition(
-    DenseIntElementsAttr replicaGroups, int32_t numPartitions,
-    OpBuilder &builder) {
-  if (numPartitions <= 1) {
-    // Treat as a single partition.
-    return replicaGroups;
-  }
-
-  auto groupsType = llvm::cast<RankedTensorType>(replicaGroups.getType());
-  assert(groupsType.getRank() == 2);
-  int rows = groupsType.getShape()[0];
-  int cols = groupsType.getShape()[1];
-  auto values = replicaGroups.getValues<int64_t>();
-  SmallVector<Attribute> newValues;
-
-  // The number of groups is the same as the number of rows.
-  for (int i = 0; i < rows; ++i) {
-    // Each group starts here. The group size is (numPartitions * cols).
-    for (int p = 0; p < numPartitions; ++p) {
-      for (int j = 0; j < cols; ++j) {
-        const int index = i * cols + j;
-        const int64_t replicaId = values[index];
-        const int64_t value =
-            (replicaId == -1) ? -1 : replicaId * numPartitions + p;
-        newValues.push_back(builder.getI64IntegerAttr(value));
-      }
-    }
-  }
-  auto type =
-      RankedTensorType::get({rows, numPartitions * cols}, builder.getI64Type());
-  return DenseIntElementsAttr::get(type, newValues);
-}
-
-// The collective group mode determines how the StableHLO process grid is split
-// into independent process groups.
-enum class CollectiveOpGroupMode {
-  // Only cross-replica communications happen within each process group.
-  CrossReplica,
-  // Only cross-partition communications happen within each process group.
-  CrossPartition,
-  // Both cross-replica and cross-partition communications may happen within
-  // each process group.
-  CrossReplicaAndPartition,
-  // A list of flattened process ids is used to specify the process groups.
-  FlattenedIds,
-};
-
-// clang-format off
-// +--------------------+-----------+--------------------+--------------------------+
-// | Collective         | channelId | useGlobalDeviceIds | Collective Group Mode    |
-// +--------------------+-----------+--------------------+--------------------------+
-// | all_gather         |   <= 0    | false              | CrossReplica             |
-// |                    |    > 0    | false              | CrossReplicaAndPartition |
-// |                    |    > 0    | true               | FlattenedIds             |
-// +--------------------+-----------+--------------------+--------------------------+
-// | all_reduce         |   <= 0    | false              | CrossReplica             |
-// |                    |    > 0    | false              | CrossReplicaAndPartition |
-// |                    |    > 0    | true               | FlattenedIds             |
-// +--------------------+-----------+--------------------+--------------------------+
-// | all_to_all         |   <= 0    |                    | CrossReplica             |
-// |                    |    > 0    |                    | CrossPartition           |
-// +--------------------+-----------+--------------------+--------------------------+
-// | collective_permute |   <= 0    |                    | CrossReplica             |
-// |                    |    > 0    |                    | CrossPartition           |
-// +--------------------+-----------+--------------------+--------------------------+
-// | reduce_scatter     |   <= 0    | false              | CrossReplica             |
-// |                    |    > 0    | false              | CrossReplicaAndPartition |
-// |                    |    > 0    | true               | FlattenedIds             |
-// +--------------------+-----------+--------------------+--------------------------+
-// clang-format on
-static CollectiveOpGroupMode getCollectiveOpGroupMode(
-    int64_t channelId, std::optional<bool> useGlobalDeviceIds) {
-  if (channelId <= 0) {
-    assert(!useGlobalDeviceIds.has_value() || !*useGlobalDeviceIds);
-    return CollectiveOpGroupMode::CrossReplica;
-  } else {
-    if (!useGlobalDeviceIds.has_value()) {
-      return CollectiveOpGroupMode::CrossPartition;
-    } else if (!*useGlobalDeviceIds) {
-      return CollectiveOpGroupMode::CrossReplicaAndPartition;
-    } else {
-      return CollectiveOpGroupMode::FlattenedIds;
-    }
-  }
-}
-
-/// Creates a channel matching the given |channelHandleAttr| scoped to the
-/// requested group.
-static Value createChannelWithGroupInfo(
-    Location loc, mhlo::ChannelHandleAttr channelHandleAttr,
-    int32_t numReplicas, int32_t numPartitions,
-    DenseIntElementsAttr replicaGroups, std::optional<bool> useGlobalDeviceIds,
-    OpBuilder &builder) {
-  // Set numPartitions, numReplicas to 1 if not set by the user.
-  if (numPartitions == -1) numPartitions = 1;
-  if (numReplicas == -1) numReplicas = 1;
-
-  // Base channel that may be split by the group info.
-  Value baseChannel =
-      builder.create<IREE::Flow::ChannelDefaultOp>(loc, /*group=*/StringAttr{});
-
-  // No need to split if there is a single group.
-  ShapedType replicaGroupType = replicaGroups.getType();
-  assert(replicaGroupType.getRank() == 2);
-  if (numPartitions == 1 && replicaGroupType.getDimSize(0) == 1) {
-    return baseChannel;
-  }
-
-  // Convert replica_groups into flattened IDs depending on group mode.
-  DenseIntElementsAttr rankGroups;
-  int64_t channelId = channelHandleAttr ? channelHandleAttr.getHandle() : 0;
-  CollectiveOpGroupMode mode =
-      getCollectiveOpGroupMode(channelId, useGlobalDeviceIds);
-  if (mode == CollectiveOpGroupMode::CrossReplica) {
-    rankGroups = convertToRankGroupsByCrossReplica(replicaGroups, numPartitions,
-                                                   builder);
-  } else if (mode == CollectiveOpGroupMode::CrossPartition) {
-    rankGroups = convertToRankGroupsByCrossPartition(replicaGroups, numReplicas,
-                                                     builder);
-  } else if (mode == CollectiveOpGroupMode::CrossReplicaAndPartition) {
-    rankGroups = convertToRankGroupsByCrossReplicaAndPartition(
-        replicaGroups, numPartitions, builder);
-  } else if (mode == CollectiveOpGroupMode::FlattenedIds) {
-    // already flattened.
-    rankGroups = replicaGroups;
-  }
-
-  // Construct lookups for color and key split parameters.
-  // Note that `replica_groups` can be interpreted in multiple ways based on the
-  // other attributes.
-  auto [color, key] =
-      makeSplitColorAndKey(loc, baseChannel, rankGroups, builder);
-
-  // Split the channel. Note that this is an expensive operation.
-  return builder.create<IREE::Flow::ChannelSplitOp>(loc, baseChannel, color,
-                                                    key);
-}
-
-static Value emitTranspose(ConversionPatternRewriter &rewriter, Location loc,
-                           Value input, int64_t srcDim, int64_t dstDim) {
-  // Creates a transpose op that swaps dimensions srcDim and dstDim in the
-  // input.
-  auto inputType = cast<RankedTensorType>(input.getType());
-  SmallVector<int64_t> inputShape(inputType.getShape());
-  SmallVector<int64_t> permutation =
-      llvm::to_vector(llvm::seq<int64_t>(0, inputShape.size()));
-  std::swap(permutation[srcDim], permutation[dstDim]);
-  std::swap(inputShape[srcDim], inputShape[dstDim]);
-  DenseIntElementsAttr permutationAttr = rewriter.getI64VectorAttr(permutation);
-  return rewriter.create<mhlo::TransposeOp>(
-      loc, RankedTensorType::get(inputShape, inputType.getElementType()), input,
-      permutationAttr);
-}
-
-static int32_t getNumReplicas(ModuleOp moduleOp) {
-  if (!moduleOp) {
-    return -1;
-  }
-  if (auto numReplicasAttr =
-          moduleOp->getAttrOfType<IntegerAttr>("mhlo.num_replicas")) {
-    return numReplicasAttr.getInt();
-  } else {
-    return -1;
-  }
-}
-
-static int32_t getNumPartitions(ModuleOp moduleOp) {
-  if (!moduleOp) {
-    return -1;
-  }
-  if (auto numPartitionsAttr =
-          moduleOp->getAttrOfType<IntegerAttr>("mhlo.num_partitions")) {
-    return numPartitionsAttr.getInt();
-  } else {
-    return -1;
-  }
-}
-
-}  // namespace
-
-/// Converts mhlo.partition_id to (flow.channel.rank % numPartitions)
-struct PartitionIdOpConversion
-    : public OpConversionPattern<mhlo::PartitionIdOp> {
-  using OpConversionPattern<mhlo::PartitionIdOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::PartitionIdOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto loc = op.getLoc();
-    // PartitionId = rank % numPartitions
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numPartitions = getNumPartitions(moduleOp);
-    Value value;
-    if (numPartitions <= 1) {
-      value = rewriter.create<arith::ConstantIndexOp>(loc, 0);
-    } else {
-      auto channel = rewriter.create<IREE::Flow::ChannelDefaultOp>(
-          loc, /*group=*/StringAttr{});
-      Value rank = rewriter.create<IREE::Flow::ChannelRankOp>(loc, channel);
-      auto cst =
-          rewriter.create<arith::ConstantIndexOp>(loc,
-                                                  /*value=*/numPartitions);
-      value = rewriter.create<arith::RemUIOp>(loc, rank, cst);
-    }
-    auto resultType =
-        llvm::cast<RankedTensorType>(op.getType());  // tensor<ui32>
-    auto elemType = resultType.getElementType();
-    // index -> ui32
-    auto rankElem = rewriter.create<arith::IndexCastUIOp>(loc, elemType, value);
-    // tensor<ui32>
-    auto rankTensor = rewriter.create<tensor::FromElementsOp>(
-        loc, resultType, rankElem.getResult());
-    rewriter.replaceOp(op, rankTensor.getResult());
-    return success();
-  }
-};
-
-/// Converts mhlo.replica_id to floor_div(flow.channel.rank, numPartitions)
-struct ReplicaIdOpConversion : public OpConversionPattern<mhlo::ReplicaIdOp> {
-  using OpConversionPattern<mhlo::ReplicaIdOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::ReplicaIdOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto loc = op.getLoc();
-    auto channel = rewriter.create<IREE::Flow::ChannelDefaultOp>(
-        loc, /*group=*/StringAttr{});
-    Value rank = rewriter.create<IREE::Flow::ChannelRankOp>(loc, channel);
-
-    // ReplicaId = floor_div(rank, numPartitions)
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numPartitions = getNumPartitions(moduleOp);
-    auto cst = rewriter.create<arith::ConstantIndexOp>(loc,
-                                                       /*value=*/numPartitions);
-    if (numPartitions > 1) {
-      rank = rewriter.create<arith::DivUIOp>(loc, rank, cst);
-    }
-
-    auto resultType =
-        llvm::cast<RankedTensorType>(op.getType());  // tensor<ui32>
-    auto elemType = resultType.getElementType();
-    // index -> ui32
-    auto rankElem = rewriter.create<arith::IndexCastUIOp>(loc, elemType, rank);
-    // tensor<ui32>
-    auto rankTensor = rewriter.create<tensor::FromElementsOp>(
-        loc, resultType, rankElem.getResult());
-    rewriter.replaceOp(op, rankTensor.getResult());
-    return success();
-  }
-};
-
-struct AllGatherOpConversion : public OpConversionPattern<mhlo::AllGatherOp> {
-  using OpConversionPattern<mhlo::AllGatherOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::AllGatherOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    if (checkCollectiveAttrs(op, rewriter).failed()) {
-      return failure();
-    }
-
-    auto loc = op.getLoc();
-
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numReplicas = getNumReplicas(moduleOp);
-    int32_t numPartitions = getNumPartitions(moduleOp);
-
-    // Create a channel.
-    Value channel = createChannelWithGroupInfo(
-        loc, op.getChannelHandleAttr(), numReplicas, numPartitions,
-        op.getReplicaGroups(), op.getUseGlobalDeviceIds(), rewriter);
-
-    // Get the collective element type attribute.
-    auto resultType = llvm::cast<RankedTensorType>(op.getResult().getType());
-    IREE::Flow::CollectiveElementTypeAttr elementTypeAttr =
-        getCollectiveElementTypeAttr(op.getContext(), resultType);
-    if (!elementTypeAttr) {
-      return rewriter.notifyMatchFailure(
-          op, "unsupported element type for collective op");
-    }
-    uint64_t allGatherDim = op.getAllGatherDim();
-    Value gatherInput = adaptor.getOperand();
-    SmallVector<int64_t> gatherResultShape(resultType.getShape());
-
-    // When all_gather_dim != 0, we need to transpose between 0 and
-    // all_gather_dim before and after the flow allgather op.
-    const bool requiresTranspose = allGatherDim != 0;
-    if (requiresTranspose) {
-      std::swap(gatherResultShape[0], gatherResultShape[allGatherDim]);
-      gatherInput = emitTranspose(rewriter, loc, gatherInput, 0, allGatherDim);
-    }
-
-    // Create an empty tensor for the result.
-    Value target = rewriter.create<tensor::EmptyOp>(
-        loc, gatherResultShape,
-        getElementTypeOrSelf(adaptor.getOperand().getType()));
-    Value gatherResult = rewriter.create<IREE::Flow::CollectiveAllGatherOp>(
-        op.getLoc(), elementTypeAttr, target, gatherInput, channel);
-
-    if (requiresTranspose) {
-      gatherResult =
-          emitTranspose(rewriter, loc, gatherResult, allGatherDim, 0);
-    }
-
-    rewriter.replaceOp(op, gatherResult);
-    return success();
-  }
-};
-
-struct AllReduceOpConversion : public OpConversionPattern<mhlo::AllReduceOp> {
-  using OpConversionPattern<mhlo::AllReduceOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::AllReduceOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    if (checkCollectiveAttrs(op, rewriter).failed()) {
-      return failure();
-    }
-
-    // Only single elementwise op is supported.
-    Block &block = op.getComputation().front();
-
-    if (block.empty() || llvm::hasSingleElement(block) ||
-        std::next(block.begin(), 2) != block.end()) {
-      return rewriter.notifyMatchFailure(op, "must have two ops in the block");
-    }
-
-    if (block.getNumArguments() != 2) {
-      return rewriter.notifyMatchFailure(op, "must have two block args");
-    }
-
-    Operation &op1 = block.front();
-    Operation &op2 = *(++block.begin());
-
-    if (op1.getNumResults() != 1 ||
-        !op1.hasTrait<::mlir::OpTrait::Elementwise>()) {
-      return rewriter.notifyMatchFailure(op, "must have elementwise trait");
-    }
-
-    // Convert mhlo reduction op into flow reduction op.
-    std::optional<IREE::Flow::CollectiveReductionOp> redOp =
-        convertToFlowCollectiveReductionOp(op1);
-    if (!redOp) {
-      return rewriter.notifyMatchFailure(op, "unsupported operation.");
-    }
-
-    if (!op2.mightHaveTrait<OpTrait::IsTerminator>()) {
-      return rewriter.notifyMatchFailure(op,
-                                         "the second op must be a terminator");
-    }
-
-    auto loc = op.getLoc();
-
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numReplicas = getNumReplicas(moduleOp);
-    int32_t numPartitions = getNumPartitions(moduleOp);
-
-    // Create a channel.
-    Value channel = createChannelWithGroupInfo(
-        loc, op.getChannelHandleAttr(), numReplicas, numPartitions,
-        op.getReplicaGroups(), op.getUseGlobalDeviceIds(), rewriter);
-
-    // Convert mhlo reduction op into flow reduction op.
-    auto reductionOpAttr =
-        IREE::Flow::CollectiveReductionOpAttr::get(op.getContext(), *redOp);
-
-    auto inputType = llvm::cast<RankedTensorType>(op.getOperand().getType());
-
-    // Get the collective element type attribute.
-    IREE::Flow::CollectiveElementTypeAttr elementTypeAttr =
-        getCollectiveElementTypeAttr(op.getContext(), inputType);
-    if (!elementTypeAttr) {
-      return rewriter.notifyMatchFailure(op, "unsupported input type");
-    }
-
-    // Create an empty tensor for the result.
-    ArrayRef<int64_t> inputShape = inputType.getShape();
-    Value target = rewriter.create<tensor::EmptyOp>(
-        loc, inputShape, getElementTypeOrSelf(adaptor.getOperand().getType()));
-    auto allReduceOp = rewriter.create<IREE::Flow::CollectiveAllReduceOp>(
-        op.getLoc(), reductionOpAttr, elementTypeAttr, target,
-        adaptor.getOperand(), channel);
-    rewriter.replaceOp(op, allReduceOp.getResult());
-    return success();
-  }
-};
-
-static Value splitAndConcatForAllToAll(ConversionPatternRewriter &rewriter,
-                                       Location loc, Value input,
-                                       uint64_t splitDim, uint64_t concatDim,
-                                       uint64_t splitCount) {
-  // Helper function to rearrange data after all-to-all.
-  auto inputType = llvm::cast<RankedTensorType>(input.getType());
-  ArrayRef<int64_t> inputShape = inputType.getShape();
-
-  // Reshape
-  const int64_t rank = inputShape.size();
-  llvm::SmallVector<int64_t> newShape;
-  for (int64_t i = 0; i < rank; ++i) {
-    if (i != splitDim) {
-      newShape.push_back(inputShape[i]);
-      continue;
-    }
-    newShape.push_back(splitCount);
-    newShape.push_back(inputShape[i] / splitCount);
-  }
-  Value result = rewriter.create<mhlo::ReshapeOp>(
-      loc, RankedTensorType::get(newShape, inputType.getElementType()), input);
-
-  // Transpose
-  SmallVector<int64_t> permutation;
-  permutation.reserve(rank + 1);
-  for (int64_t i = 0; i < rank; ++i) {
-    int64_t dimAfterReshape = i >= splitDim ? i + 1 : i;
-    if (i == concatDim) {
-      permutation.push_back(splitDim);
-    }
-    permutation.push_back(dimAfterReshape);
-  }
-  SmallVector<int64_t> transposeResultShape;
-  transposeResultShape.reserve(rank + 1);
-  for (int64_t i = 0; i < rank + 1; ++i)
-    transposeResultShape.push_back(newShape[permutation[i]]);
-  result = rewriter.create<mhlo::TransposeOp>(
-      loc,
-      RankedTensorType::get(transposeResultShape, inputType.getElementType()),
-      result, rewriter.getI64VectorAttr(permutation));
-
-  // Reshape
-  llvm::SmallVector<int64_t> finalShape(inputShape);
-  finalShape[concatDim] *= splitCount;
-  finalShape[splitDim] /= splitCount;
-  return rewriter.create<mhlo::ReshapeOp>(
-      loc, RankedTensorType::get(finalShape, inputType.getElementType()),
-      result);
-}
-
-struct AllToAllOpConversion : public OpConversionPattern<mhlo::AllToAllOp> {
-  using OpConversionPattern<mhlo::AllToAllOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::AllToAllOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto loc = op.getLoc();
-
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numReplicas = getNumReplicas(moduleOp);
-    int32_t numPartitions = getNumPartitions(moduleOp);
-
-    // Create a channel.
-    Value channel = createChannelWithGroupInfo(
-        loc, op.getChannelHandleAttr(), numReplicas, numPartitions,
-        op.getReplicaGroups(), /*useGlobalDeviceIds=*/std::nullopt, rewriter);
-
-    // Get the collective element type attribute.
-    auto resultType = llvm::cast<RankedTensorType>(op.getResult(0).getType());
-    IREE::Flow::CollectiveElementTypeAttr elementTypeAttr =
-        getCollectiveElementTypeAttr(op.getContext(), resultType);
-    if (!elementTypeAttr) {
-      return rewriter.notifyMatchFailure(
-          op, "unsupported element type for collective op");
-    }
-    if (op.getNumOperands() != 1) {
-      return rewriter.notifyMatchFailure(op,
-                                         "tuple all-to-all is not supported");
-    }
-    if (!op.getSplitDimension() || !op.getConcatDimension() ||
-        !op.getSplitCount()) {
-      return rewriter.notifyMatchFailure(
-          op,
-          "split_dimension, concat_dimension, and split_count must be present "
-          "for array all-to-all");
-    }
-
-    uint64_t splitDim = *op.getSplitDimension();
-    uint64_t concatDim = *op.getConcatDimension();
-    uint64_t splitCount = *op.getSplitCount();
-    Value allToAllInput = adaptor.getOperand().front();
-
-    // When splitDim != 0, we need to transpose splitDim to 0 before and after
-    // the all-to-all.
-    const bool requiresTranspose = splitDim != 0;
-    // When the concatDim != splitDim, we need to rearrange the data after the
-    // all-to-all.
-    const bool requiresSplitAndConcat = concatDim != splitDim;
-    if (requiresTranspose) {
-      allToAllInput = emitTranspose(rewriter, loc, allToAllInput, 0, splitDim);
-    }
-
-    // Create an empty tensor for the result.
-    Value target = rewriter.create<tensor::EmptyOp>(
-        loc, cast<RankedTensorType>(allToAllInput.getType()).getShape(),
-        getElementTypeOrSelf(allToAllInput.getType()));
-    // Create all-to-all.
-    Value allToAllResult = rewriter.create<IREE::Flow::CollectiveAllToAllOp>(
-        op.getLoc(), elementTypeAttr, target, allToAllInput, channel);
-
-    if (requiresTranspose) {
-      allToAllResult =
-          emitTranspose(rewriter, loc, allToAllResult, splitDim, 0);
-    }
-    if (requiresSplitAndConcat) {
-      allToAllResult = splitAndConcatForAllToAll(
-          rewriter, loc, allToAllResult, splitDim, concatDim, splitCount);
-    }
-
-    rewriter.replaceOp(op, allToAllResult);
-    return success();
-  }
-};
-
-struct ReduceScatterOpConversion
-    : public OpConversionPattern<mhlo::ReduceScatterOp> {
-  using OpConversionPattern<mhlo::ReduceScatterOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::ReduceScatterOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    if (checkCollectiveAttrs(op, rewriter).failed()) {
-      return failure();
-    }
-
-    // Only single elementwise op is supported.
-    Block &block = op.getComputation().front();
-
-    if (block.empty() || llvm::hasSingleElement(block) ||
-        std::next(block.begin(), 2) != block.end()) {
-      return rewriter.notifyMatchFailure(op, "must have two ops in the block");
-    }
-
-    if (block.getNumArguments() != 2) {
-      return rewriter.notifyMatchFailure(op, "must have two block args");
-    }
-
-    Operation &op1 = block.front();
-    Operation &op2 = *(++block.begin());
-
-    if (op1.getNumResults() != 1 ||
-        !op1.hasTrait<::mlir::OpTrait::Elementwise>()) {
-      return rewriter.notifyMatchFailure(op, "must have elementwise trait");
-    }
-
-    // Convert mhlo reduction op into flow reduction op.
-    std::optional<IREE::Flow::CollectiveReductionOp> redOp =
-        convertToFlowCollectiveReductionOp(op1);
-    if (!redOp) {
-      return rewriter.notifyMatchFailure(op, "unsupported operation.");
-    }
-
-    if (!op2.mightHaveTrait<OpTrait::IsTerminator>()) {
-      return rewriter.notifyMatchFailure(op,
-                                         "the second op must be a terminator");
-    }
-
-    // Convert mhlo reduction op into flow reduction op.
-    auto reductionOpAttr =
-        IREE::Flow::CollectiveReductionOpAttr::get(op.getContext(), *redOp);
-
-    auto loc = op.getLoc();
-
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numReplicas = getNumReplicas(moduleOp);
-    int32_t numPartitions = getNumPartitions(moduleOp);
-
-    // Create a channel.
-    Value channel = createChannelWithGroupInfo(
-        loc, op.getChannelHandleAttr(), numReplicas, numPartitions,
-        op.getReplicaGroups(), op.getUseGlobalDeviceIds(), rewriter);
-
-    // Get the collective element type attribute.
-    auto resultType = llvm::cast<RankedTensorType>(op.getResult().getType());
-    IREE::Flow::CollectiveElementTypeAttr elementTypeAttr =
-        getCollectiveElementTypeAttr(op.getContext(), resultType);
-    if (!elementTypeAttr) {
-      return rewriter.notifyMatchFailure(op, "unsupported input type");
-    }
-
-    // When scatter_dimension != 0, we need to transpose between 0 and
-    // scatter_dimension before and after the flow reduce_scatter op.
-    uint64_t scatterDim = op.getScatterDimension();
-    auto inputType = llvm::cast<RankedTensorType>(op.getOperand().getType());
-    SmallVector<int64_t> reduceInputShape(inputType.getShape());
-    Value reduceInput = adaptor.getOperand();
-    DenseIntElementsAttr permutationAttr;
-
-    SmallVector<int64_t> scatterResultShape(resultType.getShape());
-    auto elemType = getElementTypeOrSelf(reduceInput.getType());
-
-    if (scatterDim != 0) {
-      SmallVector<int64_t> permutation =
-          llvm::to_vector(llvm::seq<int64_t>(0, scatterResultShape.size()));
-      std::swap(permutation[0], permutation[scatterDim]);
-      permutationAttr = rewriter.getI64VectorAttr(permutation);
-      std::swap(reduceInputShape[0], reduceInputShape[scatterDim]);
-      std::swap(scatterResultShape[0], scatterResultShape[scatterDim]);
-      // Transpose the input.
-      reduceInput = rewriter.create<mhlo::TransposeOp>(
-          loc, RankedTensorType::get(reduceInputShape, elemType), reduceInput,
-          permutationAttr);
-    }
-
-    // Create an empty tensor for the result.
-    Value target =
-        rewriter.create<tensor::EmptyOp>(loc, scatterResultShape, elemType);
-    Value scatterResult =
-        rewriter.create<IREE::Flow::CollectiveReduceScatterOp>(
-            op.getLoc(), reductionOpAttr, elementTypeAttr, target, reduceInput,
-            channel);
-
-    if (scatterDim != 0) {
-      scatterResult = rewriter.create<mhlo::TransposeOp>(
-          loc, resultType, scatterResult, permutationAttr);
-    }
-
-    rewriter.replaceOp(op, scatterResult);
-    return success();
-  }
-};
-
-struct CollectivePermuteOpConversion
-    : public OpConversionPattern<mhlo::CollectivePermuteOp> {
-  using OpConversionPattern<mhlo::CollectivePermuteOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::CollectivePermuteOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto loc = op.getLoc();
-
-    auto moduleOp = op->getParentOfType<ModuleOp>();
-    int32_t numReplicas = getNumReplicas(moduleOp);
-    int32_t numPartitions = getNumPartitions(moduleOp);
-
-    // Replica group consists of all partitions or all replicas depending on the
-    // mode. If numPartitions is not set, a single group will result in the base
-    // channel being used.
-    int64_t channelId =
-        op.getChannelHandleAttr() ? op.getChannelHandleAttr().getHandle() : 0;
-    auto mode = getCollectiveOpGroupMode(channelId,
-                                         /*useGlobalDeviceIds=*/std::nullopt);
-    int64_t numParticipants = mode == CollectiveOpGroupMode::CrossReplica
-                                  ? numReplicas
-                                  : numPartitions;
-    if (numParticipants == -1) numParticipants = 1;
-    SmallVector<Attribute> replicaGroups;
-    for (int64_t i = 0; i < numParticipants; ++i) {
-      replicaGroups.push_back(rewriter.getI64IntegerAttr(i));
-    }
-    auto type =
-        RankedTensorType::get({1, numParticipants}, rewriter.getI64Type());
-    auto replicaGroupsAttr = DenseIntElementsAttr::get(type, replicaGroups);
-
-    // Create a channel.
-    Value channel = createChannelWithGroupInfo(
-        loc, op.getChannelHandleAttr(), numReplicas, numPartitions,
-        replicaGroupsAttr, /*useGlobalDeviceIds=*/std::nullopt, rewriter);
-
-    auto inputType = llvm::cast<RankedTensorType>(op.getOperand().getType());
-
-    // Get the collective element type attribute.
-    IREE::Flow::CollectiveElementTypeAttr elementTypeAttr =
-        getCollectiveElementTypeAttr(op.getContext(), inputType);
-    if (!elementTypeAttr) {
-      return rewriter.notifyMatchFailure(op, "unsupported input type");
-    }
-
-    // Convert source target pairs into a constant table that can be indexed by
-    // rank to find which ids that rank should send to and recv from, or -1 for
-    // no send/recv.
-    DenseIntElementsAttr sourceTargetPairs = op.getSourceTargetPairs();
-    llvm::DenseMap<int64_t, int64_t> sendMap, recvMap;
-    auto values = sourceTargetPairs.getValues<int64_t>();
-    // Find the max rank so we can size our tables.
-    int64_t maxRank = 0;
-    for (auto rank : values) {
-      if (rank > std::numeric_limits<int16_t>::max()) {
-        return rewriter.notifyMatchFailure(
-            op, "source or target id exceeds maximum value of 16-bit integer");
-      }
-      maxRank = std::max(maxRank, rank);
-    }
-    // Create tables. -1 is used to indicate no send or recv.
-    IndexSet indexSet(loc, rewriter);
-    Value noSendOrRecv = indexSet.get(-1);
-    SmallVector<Value> sendTable(maxRank + 1, noSendOrRecv);
-    SmallVector<Value> recvTable(maxRank + 1, noSendOrRecv);
-    for (auto i = values.begin(); i != values.end(); ++i) {
-      int64_t source = (*i);
-      int64_t target = (*++i);
-      sendTable[source] = indexSet.get(target);
-      recvTable[target] = indexSet.get(source);
-    }
-    // Look up the local send/recv values using rank.
-    Value rank =
-        rewriter.create<IREE::Flow::ChannelRankOp>(loc, channel).getResult();
-    Value send = rewriter.create<IREE::Util::SwitchOp>(loc, rank, noSendOrRecv,
-                                                       sendTable);
-    Value recv = rewriter.create<IREE::Util::SwitchOp>(loc, rank, noSendOrRecv,
-                                                       recvTable);
-
-    // Create an empty tensor for the result.
-    auto input = adaptor.getOperand();
-    ArrayRef<int64_t> inputShape = inputType.getShape();
-    Value target = rewriter.create<tensor::EmptyOp>(
-        loc, inputShape, getElementTypeOrSelf(input.getType()));
-    auto collectiveSendRecvOp =
-        rewriter.create<IREE::Flow::CollectiveSendRecvOp>(
-            op.getLoc(), elementTypeAttr, target, input, channel, send, recv);
-
-    rewriter.replaceOp(op, collectiveSendRecvOp.getResult());
-    return success();
-  }
-};
-
-void populateMHLOCollectiveOpsConversionPatterns(MLIRContext *context,
-                                                 TypeConverter &typeConverter,
-                                                 RewritePatternSet &patterns) {
-  patterns.insert<AllGatherOpConversion>(typeConverter, context);
-  patterns.insert<AllReduceOpConversion>(typeConverter, context);
-  patterns.insert<AllToAllOpConversion>(typeConverter, context);
-  patterns.insert<PartitionIdOpConversion>(typeConverter, context);
-  patterns.insert<ReduceScatterOpConversion>(typeConverter, context);
-  patterns.insert<CollectivePermuteOpConversion>(typeConverter, context);
-  patterns.insert<ReplicaIdOpConversion>(typeConverter, context);
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp
deleted file mode 100644
index 5052338..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertComplexToReal.cpp
+++ /dev/null
@@ -1,535 +0,0 @@
-// Copyright 2021 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/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "iree/compiler/InputConversion/MHLO/Rewriters.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Transforms/DialectConversion.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-inline std::optional<chlo::ComparisonDirection> chloComparisonDirection(
-    mhlo::ComparisonDirection value) {
-  switch (value) {
-    case mhlo::ComparisonDirection::EQ:
-      return chlo::ComparisonDirection::EQ;
-    case mhlo::ComparisonDirection::NE:
-      return chlo::ComparisonDirection::NE;
-    case mhlo::ComparisonDirection::GE:
-      return chlo::ComparisonDirection::GE;
-    case mhlo::ComparisonDirection::GT:
-      return chlo::ComparisonDirection::GT;
-    case mhlo::ComparisonDirection::LE:
-      return chlo::ComparisonDirection::LE;
-    case mhlo::ComparisonDirection::LT:
-      return chlo::ComparisonDirection::LT;
-    default:
-      return {};
-  }
-}
-
-inline std::optional<chlo::ComparisonType> chloComparisonType(
-    mhlo::ComparisonType value) {
-  switch (value) {
-    case mhlo::ComparisonType::NOTYPE:
-      return chlo::ComparisonType::NOTYPE;
-    case mhlo::ComparisonType::FLOAT:
-      return chlo::ComparisonType::FLOAT;
-    case mhlo::ComparisonType::TOTALORDER:
-      return chlo::ComparisonType::TOTALORDER;
-    case mhlo::ComparisonType::SIGNED:
-      return chlo::ComparisonType::SIGNED;
-    case mhlo::ComparisonType::UNSIGNED:
-      return chlo::ComparisonType::UNSIGNED;
-    default:
-      return {};
-  }
-}
-
-bool isComplexTensor(Value v) {
-  if (auto tt = llvm::dyn_cast<TensorType>(v.getType())) {
-    return llvm::isa<ComplexType>(tt.getElementType());
-  }
-  return false;
-}
-
-Type convertComplexTensorTypeToReal(Type complexTensorType) {
-  auto newElementType =
-      llvm::cast<ComplexType>(
-          complexTensorType.cast<TensorType>().getElementType())
-          .getElementType();
-  if (auto tt = llvm::dyn_cast<RankedTensorType>(complexTensorType)) {
-    return RankedTensorType::get(tt.getShape(), newElementType,
-                                 tt.getEncoding());
-  } else if (auto tt = llvm::dyn_cast<UnrankedTensorType>(complexTensorType)) {
-    return UnrankedTensorType::get(newElementType);
-  }
-  assert(false && "unknown TensorType subclass");
-  return Type();
-}
-
-// Add and subtraction are elementwise and can be distributed across the real
-// and imaginary components.
-template <typename OpTy>
-struct ConvertAddSubOp : public OpConversionPattern<OpTy> {
-  using OpConversionPattern<OpTy>::OpConversionPattern;
-
-  static Value createOp(OpBuilder &b, mhlo::AddOp op, Value lhs, Value rhs) {
-    return b.create<mhlo::AddOp>(op.getLoc(), lhs, rhs);
-  }
-  static Value createOp(OpBuilder &b, mhlo::SubtractOp op, Value lhs,
-                        Value rhs) {
-    return b.create<mhlo::SubtractOp>(op.getLoc(), lhs, rhs);
-  }
-  static Value createOp(OpBuilder &b, chlo::BroadcastAddOp op, Value lhs,
-                        Value rhs) {
-    return b.create<chlo::BroadcastAddOp>(op.getLoc(), lhs, rhs, nullptr);
-  }
-  static Value createOp(OpBuilder &b, chlo::BroadcastSubOp op, Value lhs,
-                        Value rhs) {
-    return b.create<chlo::BroadcastSubOp>(op.getLoc(), lhs, rhs, nullptr);
-  }
-
-  LogicalResult matchAndRewrite(
-      OpTy op, typename OpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-    if (!isComplexTensor(adaptor.getLhs()) ||
-        !isComplexTensor(adaptor.getRhs())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-
-    Value real =
-        createOp(rewriter, op,
-                 rewriter.createOrFold<mhlo::RealOp>(loc, adaptor.getLhs()),
-                 rewriter.createOrFold<mhlo::RealOp>(loc, adaptor.getRhs()));
-    Value imag =
-        createOp(rewriter, op,
-                 rewriter.createOrFold<mhlo::ImagOp>(loc, adaptor.getLhs()),
-                 rewriter.createOrFold<mhlo::ImagOp>(loc, adaptor.getRhs()));
-    Value result = rewriter.create<mhlo::ComplexOp>(loc, real, imag);
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-// Complex multiplication results in a cross product multiplication between the
-// real and imaginary components such that:
-//   result.real = lhs.real * rhs.real - lhs.imag * rhs.imag
-//   result.imag = lhs.imag * rhs.real + lhs.real * rhs.imag
-template <typename MulOpTy>
-struct ConvertMulOp : public OpConversionPattern<MulOpTy> {
-  using OpConversionPattern<MulOpTy>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      MulOpTy op, typename MulOpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getLhs()) ||
-        !isComplexTensor(adaptor.getRhs())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-
-    auto lhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, adaptor.getLhs());
-    auto lhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, adaptor.getLhs());
-    auto rhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, adaptor.getRhs());
-    auto rhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, adaptor.getRhs());
-
-    auto realComponent = rewriter.create<mhlo::SubtractOp>(
-        loc,
-        rewriter.create<chlo::BroadcastMulOp>(loc, lhsReal, rhsReal,
-                                              /*broadcast_dimensions=*/nullptr),
-        rewriter.create<chlo::BroadcastMulOp>(
-            loc, lhsImag, rhsImag, /*broadcast_dimensions=*/nullptr));
-    auto imagComponent = rewriter.create<mhlo::AddOp>(
-        loc,
-        rewriter.create<chlo::BroadcastMulOp>(loc, lhsReal, rhsImag,
-                                              /*broadcast_dimensions=*/nullptr),
-        rewriter.create<chlo::BroadcastMulOp>(
-            loc, lhsImag, rhsReal, /*broadcast_dimensions=*/nullptr));
-    Value result = rewriter.createOrFold<mhlo::ComplexOp>(loc, realComponent,
-                                                          imagComponent);
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-// Division is performed by normalizing the denominator by multiplying by the
-// conjugate of the rhs.
-//   numerator = lhs * conj(rhs)
-//   denominator = rhs * conj(rhs)
-template <typename DivOpTy>
-struct ConvertDivOp : public OpConversionPattern<DivOpTy> {
-  using OpConversionPattern<DivOpTy>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      DivOpTy op, typename DivOpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getLhs()) ||
-        !isComplexTensor(adaptor.getRhs())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-
-    auto lhs = adaptor.getLhs();
-    auto rhs = adaptor.getRhs();
-    auto rhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, rhs);
-    auto rhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, rhs);
-
-    Value conj = rewriter.createOrFold<mhlo::ComplexOp>(
-        loc, rhsReal, rewriter.create<mhlo::NegOp>(loc, rhsImag));
-    Value complexNumerator = rewriter.create<chlo::BroadcastMulOp>(
-        loc, lhs, conj, /*broadcast_dimensions=*/nullptr);
-    Value denominator = rewriter.create<mhlo::AddOp>(
-        loc, rewriter.create<mhlo::MulOp>(loc, rhsReal, rhsReal),
-        rewriter.create<mhlo::MulOp>(loc, rhsImag, rhsImag));
-
-    Value realComponent = rewriter.create<chlo::BroadcastDivOp>(
-        loc, rewriter.create<mhlo::RealOp>(loc, complexNumerator), denominator,
-        /*broadcast_dimensions=*/nullptr);
-    Value imagComponent = rewriter.create<chlo::BroadcastDivOp>(
-        loc, rewriter.create<mhlo::ImagOp>(loc, complexNumerator), denominator,
-        /*broadcast_dimensions=*/nullptr);
-
-    Value result = rewriter.createOrFold<mhlo::ComplexOp>(loc, realComponent,
-                                                          imagComponent);
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-// Absolute value is evaluated as:
-//   result = sqrt(val.real * val.real + val.imag * val.imag)
-struct ConvertAbsOp : public OpConversionPattern<mhlo::AbsOp> {
-  using OpConversionPattern<mhlo::AbsOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::AbsOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getOperand())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-
-    auto operandReal =
-        rewriter.createOrFold<mhlo::RealOp>(loc, adaptor.getOperand());
-    auto operandImag =
-        rewriter.createOrFold<mhlo::ImagOp>(loc, adaptor.getOperand());
-    rewriter.replaceOpWithNewOp<mhlo::SqrtOp>(
-        op,
-        rewriter.create<mhlo::AddOp>(
-            loc, rewriter.create<mhlo::MulOp>(loc, operandReal, operandReal),
-            rewriter.create<mhlo::MulOp>(loc, operandImag, operandImag)));
-    return success();
-  }
-};
-
-// Exponential can be lowered to an exponential on the real component and a
-// sum of sinusoids of the imaginary component, which equates to a normal
-// exponential operator multiplied by Euler's formula.
-//
-// Exp(a + ib) = Exp(a) * Exp(ib) = Exp(a) * Cos(b) + Exp(a) * iSin(b))
-struct ConvertExpOp : public OpConversionPattern<mhlo::ExpOp> {
-  using OpConversionPattern<mhlo::ExpOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::ExpOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getOperand())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-
-    auto operandReal = rewriter.create<mhlo::RealOp>(loc, adaptor.getOperand());
-    auto operandImag = rewriter.create<mhlo::ImagOp>(loc, adaptor.getOperand());
-
-    Value expReal = rewriter.create<mhlo::ExpOp>(loc, operandReal);
-    Value result = rewriter.createOrFold<mhlo::ComplexOp>(
-        loc,
-        rewriter.create<mhlo::MulOp>(
-            loc, rewriter.create<mhlo::CosineOp>(loc, operandImag), expReal),
-        rewriter.create<mhlo::MulOp>(
-            loc, rewriter.create<mhlo::SineOp>(loc, operandImag), expReal));
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-template <typename CompareOpTy, typename ComparatorOpTy>
-struct ConvertCHLOCompareOp : public OpConversionPattern<CompareOpTy> {
-  using OpConversionPattern<CompareOpTy>::OpConversionPattern;
-  ConvertCHLOCompareOp(TypeConverter &typeConverter, MLIRContext *context,
-                       chlo::ComparisonDirection direction)
-      : OpConversionPattern<CompareOpTy>(typeConverter, context),
-        direction(direction) {}
-
-  LogicalResult matchAndRewrite(
-      CompareOpTy op, typename CompareOpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getLhs()) ||
-        !isComplexTensor(adaptor.getRhs())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-    if (direction != op.getComparisonDirection()) {
-      return rewriter.notifyMatchFailure(op, "not matching direction");
-    }
-
-    auto lhs = adaptor.getLhs();
-    auto rhs = adaptor.getRhs();
-    auto lhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, lhs);
-    auto lhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, lhs);
-    auto rhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, rhs);
-    auto rhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, rhs);
-
-    rewriter.replaceOpWithNewOp<ComparatorOpTy>(
-        op,
-        rewriter.create<chlo::BroadcastCompareOp>(
-            loc, lhsReal, rhsReal,
-            /*broadcast_dimensions=*/nullptr,
-            adaptor.getComparisonDirectionAttr(), adaptor.getCompareTypeAttr()),
-        rewriter.create<chlo::BroadcastCompareOp>(
-            loc, lhsImag, rhsImag,
-            /*broadcast_dimensions=*/nullptr,
-            adaptor.getComparisonDirectionAttr(),
-            adaptor.getCompareTypeAttr()));
-
-    return success();
-  }
-
-  chlo::ComparisonDirection direction;
-};
-
-template <typename CompareOpTy, typename ComparatorOpTy>
-struct ConvertMHLOCompareOp : public OpConversionPattern<CompareOpTy> {
-  using OpConversionPattern<CompareOpTy>::OpConversionPattern;
-  ConvertMHLOCompareOp(TypeConverter &typeConverter, MLIRContext *context,
-                       mhlo::ComparisonDirection direction)
-      : OpConversionPattern<CompareOpTy>(typeConverter, context),
-        direction(direction) {}
-
-  LogicalResult matchAndRewrite(
-      CompareOpTy op, typename CompareOpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    Location loc = op.getLoc();
-
-    if (!isComplexTensor(adaptor.getLhs()) ||
-        !isComplexTensor(adaptor.getRhs())) {
-      return rewriter.notifyMatchFailure(op, "not complex tensor");
-    }
-    if (direction != op.getComparisonDirection()) {
-      return rewriter.notifyMatchFailure(op, "not matching direction");
-    }
-
-    auto lhs = adaptor.getLhs();
-    auto rhs = adaptor.getRhs();
-    auto lhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, lhs);
-    auto lhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, lhs);
-    auto rhsReal = rewriter.createOrFold<mhlo::RealOp>(loc, rhs);
-    auto rhsImag = rewriter.createOrFold<mhlo::ImagOp>(loc, rhs);
-
-    // If the input op is an mhlo op, we need to convert the attributes to the
-    // corresponding chlo one..
-    chlo::ComparisonDirection chloCmpDirection =
-        *chloComparisonDirection(adaptor.getComparisonDirection());
-
-    std::optional<mhlo::ComparisonType> mhloCmpType = adaptor.getCompareType();
-    chlo::ComparisonTypeAttr chloCmpType;
-    if (mhloCmpType)
-      chloCmpType = chlo::ComparisonTypeAttr::get(
-          rewriter.getContext(), *chloComparisonType(*mhloCmpType));
-
-    rewriter.replaceOpWithNewOp<ComparatorOpTy>(
-        op,
-        rewriter.create<chlo::BroadcastCompareOp>(
-            loc, lhsReal, rhsReal,
-            /*broadcast_dimensions=*/nullptr, chloCmpDirection, chloCmpType),
-        rewriter.create<chlo::BroadcastCompareOp>(
-            loc, lhsImag, rhsImag,
-            /*broadcast_dimensions=*/nullptr, chloCmpDirection, chloCmpType));
-
-    return success();
-  }
-
-  mhlo::ComparisonDirection direction;
-};
-
-struct ElideComplexPattern : public OpConversionPattern<mhlo::ComplexOp> {
-  using OpConversionPattern<mhlo::ComplexOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::ComplexOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    rewriter.eraseOp(op);
-    return success();
-  }
-};
-
-struct ElideRealPattern : public OpConversionPattern<mhlo::RealOp> {
-  using OpConversionPattern<mhlo::RealOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::RealOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto complexProducer =
-        adaptor.getOperands()[0].getDefiningOp<mhlo::ComplexOp>();
-    if (complexProducer) {
-      rewriter.replaceOp(op, complexProducer.getLhs());
-      return success();
-    }
-    return failure();
-  }
-};
-
-struct ElideImagPattern : public OpConversionPattern<mhlo::ImagOp> {
-  using OpConversionPattern<mhlo::ImagOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::ImagOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto complexProducer =
-        adaptor.getOperands()[0].getDefiningOp<mhlo::ComplexOp>();
-    if (complexProducer) {
-      rewriter.replaceOp(op, complexProducer.getRhs());
-      return success();
-    }
-    return failure();
-  }
-};
-
-}  // namespace
-
-void populateMHLOComplexToRealPatterns(MLIRContext *context,
-                                       TypeConverter &typeConverter,
-                                       RewritePatternSet &patterns) {
-  // Add an subtract patterns.
-  patterns.insert<ConvertAddSubOp<mhlo::AddOp>>(typeConverter, context);
-  patterns.insert<ConvertAddSubOp<mhlo::SubtractOp>>(typeConverter, context);
-  patterns.insert<ConvertAddSubOp<chlo::BroadcastAddOp>>(typeConverter,
-                                                         context);
-  patterns.insert<ConvertAddSubOp<chlo::BroadcastSubOp>>(typeConverter,
-                                                         context);
-
-  // Mul patterns.
-  patterns.insert<ConvertMulOp<mhlo::MulOp>>(typeConverter, context);
-  patterns.insert<ConvertMulOp<chlo::BroadcastMulOp>>(typeConverter, context);
-
-  // Div patterns.
-  patterns.insert<ConvertDivOp<mhlo::DivOp>>(typeConverter, context);
-  patterns.insert<ConvertDivOp<chlo::BroadcastDivOp>>(typeConverter, context);
-
-  // Unary ops.
-  patterns.insert<ConvertAbsOp>(typeConverter, context);
-  patterns.insert<ConvertExpOp>(typeConverter, context);
-
-  // Compare ops.
-  patterns.insert<ConvertMHLOCompareOp<mhlo::CompareOp, mhlo::OrOp>>(
-      typeConverter, context, mhlo::ComparisonDirection::NE);
-  patterns.insert<ConvertMHLOCompareOp<mhlo::CompareOp, mhlo::AndOp>>(
-      typeConverter, context, mhlo::ComparisonDirection::EQ);
-  patterns.insert<ConvertCHLOCompareOp<chlo::BroadcastCompareOp, mhlo::OrOp>>(
-      typeConverter, context, chlo::ComparisonDirection::NE);
-  patterns.insert<ConvertCHLOCompareOp<chlo::BroadcastCompareOp, mhlo::AndOp>>(
-      typeConverter, context, chlo::ComparisonDirection::EQ);
-
-  // Complex/Real/Imag conversions should fold away.
-  // Note that this is an opinion taken because these patterns are targeted
-  // at full conversion scenarios and we would rather know eagerly if
-  // conversion is not possible. A more lax conversion would not include the
-  // ElideComplexPattern.
-  // Doing it this way makes error messages nice because a failure will report
-  // which remaining live op is keeping it from being erased.
-  patterns.insert<ElideComplexPattern>(typeConverter, context, 0);
-  patterns.insert<ElideRealPattern>(typeConverter, context);
-  patterns.insert<ElideImagPattern>(typeConverter, context);
-}
-
-namespace {
-
-struct TestMHLOConvertComplexToRealPass
-    : public TestMHLOConvertComplexToRealBase<
-          TestMHLOConvertComplexToRealPass> {
-  void getDependentDialects(DialectRegistry &registry) const override {
-    registry.insert<mhlo::MhloDialect, chlo::ChloDialect>();
-  }
-
-  void runOnOperation() override {
-    RewritePatternSet patterns(&getContext());
-    MLIRContext *context = &getContext();
-    TypeConverter typeConverter;
-    typeConverter.addConversion([](Type t) { return t; });
-
-    populateMHLOComplexToRealPatterns(context, typeConverter, patterns);
-
-    ConversionTarget target(*context);
-    auto hasNoComplexTypes = [](Operation *op) {
-      for (Value operand : op->getOperands()) {
-        if (auto st = llvm::dyn_cast<ShapedType>(operand.getType())) {
-          if (llvm::isa<ComplexType>(st.getElementType())) {
-            return false;
-          }
-        }
-      }
-      for (Value result : op->getResults()) {
-        if (auto st = llvm::dyn_cast<ShapedType>(result.getType())) {
-          if (llvm::isa<ComplexType>(st.getElementType())) {
-            return false;
-          }
-        }
-      }
-      return true;
-    };
-
-    target.addLegalDialect<mhlo::MhloDialect>();
-    target.addLegalDialect<chlo::ChloDialect>();
-    target.addLegalDialect<func::FuncDialect, mlir::arith::ArithDialect>();
-
-    // For the test, require that casts fully convert.
-    target.addIllegalOp<mhlo::ComplexOp>();
-    target.addIllegalOp<mhlo::ImagOp>();
-    target.addIllegalOp<mhlo::RealOp>();
-
-    // Binary elementwise.
-    target.addDynamicallyLegalOp<mhlo::AddOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<chlo::BroadcastAddOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<mhlo::SubtractOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<chlo::BroadcastSubOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<mhlo::MulOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<chlo::BroadcastMulOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<mhlo::DivOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<chlo::BroadcastDivOp>(hasNoComplexTypes);
-
-    // Unary.
-    target.addDynamicallyLegalOp<mhlo::AbsOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<mhlo::ExpOp>(hasNoComplexTypes);
-
-    // Compare.
-    target.addDynamicallyLegalOp<mhlo::CompareOp>(hasNoComplexTypes);
-    target.addDynamicallyLegalOp<chlo::BroadcastCompareOp>(hasNoComplexTypes);
-
-    if (failed(applyPartialConversion(getOperation(), target,
-                                      std::move(patterns)))) {
-      return signalPassFailure();
-    }
-  }
-};
-
-}  // namespace
-
-std::unique_ptr<OperationPass<func::FuncOp>>
-createTestMHLOConvertComplexToRealPass() {
-  return std::make_unique<TestMHLOConvertComplexToRealPass>();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.cpp
deleted file mode 100644
index 483b7ad..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2019 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/InputConversion/MHLO/ConvertMHLOToFlow.h"
-
-#include <iterator>
-
-#include "iree/compiler/Dialect/Flow/IR/FlowDialect.h"
-#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/PatternMatch.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-struct ConstOpLowering : public OpRewritePattern<mhlo::ConstantOp> {
-  using OpRewritePattern::OpRewritePattern;
-  LogicalResult matchAndRewrite(mhlo::ConstantOp op,
-                                PatternRewriter &rewriter) const override {
-    rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValue());
-    return success();
-  }
-};
-
-}  // namespace
-
-void setupDirectMHLOToFlowLegality(MLIRContext *context,
-                                   ConversionTarget &conversionTarget) {
-  conversionTarget.addIllegalOp<mhlo::ConstantOp>();
-}
-
-void populateMHLOToFlowPatterns(MLIRContext *context,
-                                RewritePatternSet &patterns) {
-  patterns.insert<ConstOpLowering>(context);
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.h b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.h
deleted file mode 100644
index d81d5b2..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2019 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_INPUTCONVERSION_MHLO_CONVERTMHLOTOFLOW_H_
-#define IREE_COMPILER_INPUTCONVERSION_MHLO_CONVERTMHLOTOFLOW_H_
-
-#include "mlir/IR/PatternMatch.h"
-#include "mlir/Transforms/DialectConversion.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-// Setup the |conversionTarget| op legality for early-phase direct-to-flow
-// conversion from the MHLO dialect. This will make certain ops illegal that we
-// know we have good patterns for such that we can be sure we catch them before
-// they are outlined into dispatch regions.
-void setupDirectMHLOToFlowLegality(MLIRContext *context,
-                                   ConversionTarget &conversionTarget);
-
-// Appends all patterns for converting MHLO ops to flow ops.
-void populateMHLOToFlowPatterns(MLIRContext *context,
-                                RewritePatternSet &patterns);
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
-
-#endif  // IREE_COMPILER_INPUTCONVERSION_MHLO_CONVERTMHLOTOFLOW_H_
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
deleted file mode 100644
index a150821..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToLinalgExt.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright 2021 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 <cmath>
-#include <complex>
-
-#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtDialect.h"
-#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.h"
-#include "iree/compiler/Dialect/Flow/IR/FlowDialect.h"
-#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
-#include "iree/compiler/Dialect/Util/IR/UtilOps.h"
-#include "iree/compiler/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "iree/compiler/InputConversion/MHLO/Rewriters.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mhlo/transforms/map_mhlo_to_scalar_op.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h"
-#include "mlir/Dialect/Linalg/IR/Linalg.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/Dialect/Tensor/Utils/Utils.h"
-#include "mlir/Dialect/Utils/ReshapeOpsUtils.h"
-#include "mlir/IR/BuiltinAttributes.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/Matchers.h"
-#include "mlir/IR/PatternMatch.h"
-#include "mlir/Transforms/DialectConversion.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-static Type convertIntegerToSignless(IntegerType intType) {
-  return IntegerType::get(intType.getContext(),
-                          intType.getIntOrFloatBitWidth());
-}
-
-static std::optional<Type> convertRank0TensorToScalar(
-    RankedTensorType tensorType) {
-  if (tensorType.getRank() != 0) return std::nullopt;
-  Type elementType = tensorType.getElementType();
-  if (auto intType = llvm::dyn_cast<IntegerType>(elementType)) {
-    elementType = convertIntegerToSignless(intType);
-  }
-  return elementType;
-}
-
-static Type convertShapedToSignless(ShapedType shapedType) {
-  if (auto intType = llvm::dyn_cast<IntegerType>(shapedType.getElementType()))
-    return shapedType.clone(convertIntegerToSignless(intType));
-  return shapedType;
-}
-
-static std::optional<Value> materializeCast(OpBuilder &builder, Type toType,
-                                            ValueRange inputs, Location loc) {
-  assert(inputs.size() == 1 && "too many inputs to type conversion");
-  Value fromValue = inputs[0];
-  auto fromType = llvm::dyn_cast<RankedTensorType>(fromValue.getType());
-  if (!fromType) return std::nullopt;
-
-  if (auto intFromType =
-          llvm::dyn_cast<IntegerType>(fromType.getElementType())) {
-    Type castType = getElementTypeOrSelf(toType);
-    if (auto shapedType = llvm::dyn_cast<ShapedType>(fromType))
-      castType = shapedType.clone(castType);
-
-    if (castType != fromType)
-      fromValue = builder.create<tensor::BitcastOp>(loc, castType, fromValue)
-                      ->getResult(0);
-  }
-
-  if (fromType.getRank() != 0) return fromValue;
-
-  Type extractType = getElementTypeOrSelf(toType);
-  return builder.createOrFold<tensor::ExtractOp>(loc, extractType, fromValue);
-}
-
-/// Note: only designed to work for casts involving rank-0 tensors and scalars
-/// implicitly captured within op regions.
-class MhloToStdTypeConverter : public TypeConverter {
- public:
-  MhloToStdTypeConverter() {
-    addConversion([](Type type) { return type; });
-
-    addConversion(convertShapedToSignless);
-    addConversion(convertRank0TensorToScalar);
-    addConversion(convertIntegerToSignless);
-
-    addArgumentMaterialization(materializeCast);
-    addSourceMaterialization(materializeCast);
-    addTargetMaterialization(materializeCast);
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Utils
-//===----------------------------------------------------------------------===//
-
-static bool isInBodyOfLinalgExtOps(Operation *op) {
-  auto parent_op = op->getParentRegion()->getParentOp();
-  return parent_op->getDialect() ==
-         parent_op->getContext()
-             ->getLoadedDialect<IREE::LinalgExt::IREELinalgExtDialect>();
-}
-
-//===----------------------------------------------------------------------===//
-// Region operations lowering.
-//===----------------------------------------------------------------------===//
-
-template <typename OpTy>
-struct LinalgExtRegionHLOOpConversion : public OpConversionPattern<OpTy> {
-  using OpConversionPattern<OpTy>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      OpTy op, typename OpTy::Adaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    if (!isInBodyOfLinalgExtOps(op)) return failure();
-    TensorType origRetType = llvm::dyn_cast<TensorType>(op.getType());
-    if (!origRetType) return failure();
-    SmallVector<Value> scalarArgs;
-    Type newRetType = getElementTypeOrSelf(
-        this->typeConverter->convertType(origRetType.getElementType()));
-    Value result = mhlo::MhloOpToStdScalarOp::mapOp<OpTy>(
-        op, newRetType, adaptor.getOperands(), &rewriter);
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-struct LinalgExtRegionReturnOpConversion
-    : public OpConversionPattern<mhlo::ReturnOp> {
-  using OpConversionPattern<mhlo::ReturnOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      mhlo::ReturnOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    if (!isInBodyOfLinalgExtOps(op)) return failure();
-    rewriter.replaceOpWithNewOp<IREE::LinalgExt::YieldOp>(
-        op, adaptor.getOperands());
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// SortOp
-//===----------------------------------------------------------------------===//
-
-struct SortOpConversion : public OpConversionPattern<mhlo::SortOp> {
-  using OpConversionPattern<mhlo::SortOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::SortOp mhloSortOp, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    Location loc = mhloSortOp.getLoc();
-
-    llvm::SmallVector<Type> resultTypes;
-    if (this->typeConverter
-            ->convertTypes(mhloSortOp.getResultTypes(), resultTypes)
-            .failed()) {
-      return failure();
-    };
-    auto sortOp = rewriter.create<IREE::LinalgExt::SortOp>(
-        loc, resultTypes,
-        /*inputs=*/ValueRange{}, adaptor.getOperands(),
-        mhloSortOp.getDimensionAttr());
-    rewriter.inlineRegionBefore(mhloSortOp.getComparator(), sortOp.getRegion(),
-                                sortOp.getRegion().begin());
-    Region &region = sortOp.getRegion();
-    Block &block = region.front();
-    TypeConverter::SignatureConversion signature_converter(
-        block.getNumArguments());
-    for (auto en : llvm::enumerate(block.getArguments())) {
-      signature_converter.addInputs(
-          en.index(), this->typeConverter->convertType(
-                          getElementTypeOrSelf(en.value().getType())));
-    }
-    rewriter.applySignatureConversion(&region, signature_converter);
-
-    rewriter.replaceOp(mhloSortOp, sortOp->getResults());
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// ScatterOp
-//===----------------------------------------------------------------------===//
-
-struct ScatterOpConversion : public OpConversionPattern<mhlo::ScatterOp> {
-  using OpConversionPattern<mhlo::ScatterOp>::OpConversionPattern;
-
-  /// Returns true if the `dimensionNumbers` from the mhlo.scatter op follows a
-  /// canonical form:
-  ///
-  /// * The rank of indices is greater than or equal to two.
-  /// * The index_vector_dim is the last dim of indices.
-  /// * Scatter dims to operand dims order: (0, ... , n)
-  /// * Inserted window dims order: (0, ... , d)
-  /// * Update window dims order: (d + 1, ... , m)
-  static bool hasCanonicalDimensionNumbers(mhlo::ScatterOp op) {
-    auto dimNumbers = op.getScatterDimensionNumbers();
-    auto indicesType = llvm::cast<ShapedType>(op.getScatterIndices().getType());
-    auto indicesRank = indicesType.getRank();
-    auto indexVectorDim = dimNumbers.getIndexVectorDim();
-    auto indexDepth = indicesType.getShape().back();
-    auto scatterDimsToOperandDims = dimNumbers.getScatterDimsToOperandDims();
-
-    if (indicesRank != 2) return false;
-    if (indexVectorDim != indicesRank - 1) return false;
-    if (scatterDimsToOperandDims.size() != indexDepth) return false;
-
-    auto insertedWindowDims = dimNumbers.getInsertedWindowDims();
-    for (auto en : llvm::enumerate(insertedWindowDims)) {
-      if (en.index() != en.value()) return false;
-    }
-
-    // Check that there is only one batch dimension in the updates.
-    for (auto en : llvm::enumerate(dimNumbers.getUpdateWindowDims())) {
-      if (en.index() + 1 != en.value()) return false;
-    }
-
-    return true;
-  }
-
-  LogicalResult matchAndRewrite(
-      mhlo::ScatterOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    if (!hasCanonicalDimensionNumbers(op)) return failure();
-    if (llvm::size(op.getInputs()) != 1)
-      return op.emitError("NYI variadic operands scatter");
-    if (llvm::size(op.getUpdates()) != 1)
-      return op.emitError("NYI variadic updates scatter");
-
-    ImplicitLocOpBuilder b(op.getLoc(), rewriter);
-
-    Value original = adaptor.getInputs().front();
-    Value indices = adaptor.getScatterIndices();
-    Value updates = adaptor.getUpdates().front();
-
-    llvm::SmallVector<int64_t> scatterDimMap;
-    for (auto dim :
-         op.getScatterDimensionNumbers().getScatterDimsToOperandDims()) {
-      scatterDimMap.push_back(dim);
-    }
-
-    auto scatterOp = rewriter.create<IREE::LinalgExt::ScatterOp>(
-        op.getLoc(), op->getResultTypes(), ValueRange{updates, indices},
-        ValueRange{original}, scatterDimMap, op.getUniqueIndices());
-
-    rewriter.inlineRegionBefore(op.getUpdateComputation(),
-                                scatterOp.getRegion(),
-                                scatterOp.getRegion().begin());
-    Region &region = scatterOp.getRegion();
-    TypeConverter::SignatureConversion signatureConverter(2);
-    Type argType = getElementTypeOrSelf(original.getType());
-    // mhlo.scatter ops takes:
-    //   output[O] = update_computation(output[O], updates[U])
-    // where output[O] maps to block args #1 in linalg_ext.scatter ops.
-    signatureConverter.addInputs(1, argType);
-    signatureConverter.addInputs(0, argType);
-    rewriter.applySignatureConversion(&region, signatureConverter);
-
-    rewriter.replaceOp(op, scatterOp->getResults());
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// FftOp
-//===----------------------------------------------------------------------===//
-
-struct FftOpConversion : public OpConversionPattern<mhlo::FftOp> {
-  using OpConversionPattern<mhlo::FftOp>::OpConversionPattern;
-
-  static Value getBitReversalBuffer(ImplicitLocOpBuilder &b, int fftLength) {
-    SmallVector<Attribute> values;
-    int logn = std::log(fftLength) / std::log(2);
-    for (int i = 0; i < fftLength; ++i) {
-      int r = 0;
-      for (int j = 0; j < logn; ++j) {
-        r |= ((i >> j) & 1) << (logn - j - 1);
-      }
-      values.push_back(b.getI32IntegerAttr(r));
-    }
-    auto type = RankedTensorType::get({fftLength}, b.getI32Type());
-    return b.create<arith::ConstantOp>(type,
-                                       DenseIntElementsAttr::get(type, values));
-  }
-
-  static SmallVector<Value> getBitReversalOrder(ImplicitLocOpBuilder &b,
-                                                Value real, int fftLength) {
-    auto realType = llvm::cast<ShapedType>(real.getType());
-    auto rank = realType.getRank();
-
-    SmallVector<OpFoldResult> mixedSizes =
-        tensor::createDimValues(b, b.getLoc(), real);
-    Value emptyTensor =
-        b.create<tensor::EmptyOp>(mixedSizes, realType.getElementType());
-
-    SmallVector<AffineMap> maps;
-    maps.push_back(
-        AffineMap::get(rank, 0, b.getAffineDimExpr(rank - 1), b.getContext()));
-    maps.push_back(b.getMultiDimIdentityMap(rank));
-    SmallVector<utils::IteratorType> iterTypes(rank,
-                                               utils::IteratorType::parallel);
-
-    Value indices = getBitReversalBuffer(b, fftLength);
-    auto genericOp = b.create<linalg::GenericOp>(
-        TypeRange{realType}, indices, emptyTensor, maps, iterTypes,
-        [&](OpBuilder &b, Location loc, ValueRange args) {
-          SmallVector<Value> ivs;
-          for (auto i : llvm::seq<unsigned>(0, rank - 1)) {
-            ivs.push_back(b.create<linalg::IndexOp>(loc, i));
-          }
-          ivs.push_back(
-              b.create<arith::IndexCastOp>(loc, b.getIndexType(), args[0]));
-          b.create<linalg::YieldOp>(
-              loc, b.create<tensor::ExtractOp>(loc, real, ivs).getResult());
-        });
-    return {genericOp.getResult(0),
-            b.create<arith::ConstantOp>(
-                realType,
-                DenseFPElementsAttr::get(
-                    realType, llvm::cast<Attribute>(b.getF32FloatAttr(0.0))))};
-  }
-
-  static SmallVector<Value> getCoeffConstants(ImplicitLocOpBuilder &b,
-                                              int stage) {
-    constexpr std::complex<double> kI(0, 1);
-    int m = 1 << stage;
-    int mh = m >> 1;
-    SmallVector<Attribute> real, imag;
-    for (auto i : llvm::seq<unsigned>(0, mh)) {
-      auto v = std::exp(-2 * M_PI * i / m * kI);
-      real.push_back(b.getF32FloatAttr(v.real()));
-      imag.push_back(b.getF32FloatAttr(v.imag()));
-    }
-    auto type = RankedTensorType::get({mh}, b.getF32Type());
-    return {
-        b.create<arith::ConstantOp>(type, DenseFPElementsAttr::get(type, real)),
-        b.create<arith::ConstantOp>(type,
-                                    DenseFPElementsAttr::get(type, imag))};
-  }
-
-  LogicalResult matchAndRewrite(
-      mhlo::FftOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    // Only handle 2^n fft length.
-    auto operandType =
-        llvm::dyn_cast<RankedTensorType>(adaptor.getOperand().getType());
-    if (!operandType || !operandType.hasStaticShape()) {
-      return failure();
-    }
-    int fftLength = op.getFftLength().getSplatValue<IntegerAttr>().getInt();
-    if (fftLength & (fftLength - 1)) {
-      return rewriter.notifyMatchFailure(
-          op, "expected FFT length to be a power of two");
-    }
-
-    ImplicitLocOpBuilder b(op.getLoc(), rewriter);
-    SmallVector<Value> results =
-        getBitReversalOrder(b, adaptor.getOperand(), fftLength);
-    int lognPlus1 = std::log(fftLength) / std::log(2) + 1;
-    for (auto s : llvm::seq<unsigned>(1, lognPlus1)) {
-      SmallVector<Value> inputs;
-      inputs.push_back(b.create<arith::ConstantIndexOp>(s));
-      inputs.append(getCoeffConstants(b, s));
-      auto fft = b.create<IREE::LinalgExt::FftOp>(
-          TypeRange{results[0].getType(), results[1].getType()}, inputs,
-          results);
-      results = fft.getResults();
-    }
-
-    SmallVector<int64_t> shape(operandType.getShape().begin(),
-                               operandType.getShape().end());
-    shape.back() = fftLength / 2 + 1;
-    auto ty = RankedTensorType::get(shape, operandType.getElementType());
-    SmallVector<OpFoldResult> offsets(ty.getRank(), b.getIndexAttr(0));
-    SmallVector<OpFoldResult> strides(ty.getRank(), b.getIndexAttr(1));
-    SmallVector<OpFoldResult> sizes =
-        tensor::createDimValues(b, b.getLoc(), adaptor.getOperand());
-    sizes.back() = b.getIndexAttr(shape.back());
-    auto real = b.create<tensor::ExtractSliceOp>(ty, results[0], offsets, sizes,
-                                                 strides);
-    auto imag = b.create<tensor::ExtractSliceOp>(ty, results[1], offsets, sizes,
-                                                 strides);
-    rewriter.replaceOpWithNewOp<mhlo::ComplexOp>(op, op.getType(), real, imag);
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// ReverseOp
-//===----------------------------------------------------------------------===//
-
-struct ReverseOpConversion : public OpConversionPattern<mhlo::ReverseOp> {
-  using OpConversionPattern<mhlo::ReverseOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::ReverseOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    auto ty =
-        llvm::dyn_cast<RankedTensorType>(adaptor.getOperands()[0].getType());
-    if (!ty) return failure();
-
-    Location loc = op.getLoc();
-    SmallVector<OpFoldResult> mixedSizes =
-        tensor::createDimValues(rewriter, loc, adaptor.getOperands()[0]);
-    Value emptyTensor =
-        rewriter.create<tensor::EmptyOp>(loc, mixedSizes, ty.getElementType());
-    rewriter.replaceOpWithNewOp<IREE::LinalgExt::ReverseOp>(
-        op, typeConverter->convertType(op.getType()), adaptor.getOperands(),
-        emptyTensor, op.getDimensions());
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// TopkOp
-//===----------------------------------------------------------------------===//
-
-struct TopkOpConversion : public OpConversionPattern<chlo::TopKOp> {
-  using OpConversionPattern<chlo::TopKOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      chlo::TopKOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const final {
-    Location loc = op.getLoc();
-    Value operand = adaptor.getOperand();
-
-    auto inputValuesType = llvm::dyn_cast<ShapedType>(operand.getType());
-    auto outputValuesType =
-        llvm::dyn_cast<ShapedType>(op.getValues().getType());
-    auto outputIndicesType =
-        llvm::dyn_cast<ShapedType>(op.getIndices().getType());
-    if (!inputValuesType || !outputValuesType || !outputIndicesType) {
-      return rewriter.notifyMatchFailure(
-          op, "Input and output must be of ShapedType");
-    }
-
-    Type valueElementType = outputValuesType.getElementType();
-    Type indicesElementType = outputIndicesType.getElementType();
-    // Only handle integer types for indicies. Index type is not supported.
-    if (!llvm::isa<IntegerType>(indicesElementType)) {
-      return rewriter.notifyMatchFailure(
-          op, "Output indices must be of integer type.");
-    }
-
-    // Create and initialize output tensors for LinalgExt TopK results
-    // Define the output types based on the results of CHLO TopK
-    SmallVector<OpFoldResult> mixedSizes =
-        tensor::createDimValues(rewriter, loc, adaptor.getOperand());
-    mixedSizes.back() = rewriter.getIndexAttr(adaptor.getK());
-    Value emptyTensorOutputValues = rewriter.create<mlir::tensor::EmptyOp>(
-        loc, mixedSizes, valueElementType);
-    Value emptyTensorOutputIndices = rewriter.create<mlir::tensor::EmptyOp>(
-        loc, mixedSizes, indicesElementType);
-    // Initialize indices to 0 and values to negative infinity
-    TypedAttr negInfAttr;
-    if (auto intType = llvm::dyn_cast<IntegerType>(valueElementType)) {
-      negInfAttr = rewriter.getIntegerAttr(
-          intType, APInt::getSignedMinValue(intType.getWidth()));
-    } else {
-      auto negApFloat = APFloat::getInf(
-          llvm::cast<FloatType>(valueElementType).getFloatSemantics(),
-          /*Negative=*/true);
-      negInfAttr = rewriter.getFloatAttr(valueElementType, negApFloat);
-    }
-    Value negInf = rewriter.create<arith::ConstantOp>(loc, negInfAttr);
-    TypedAttr posInfAttr = rewriter.getIntegerAttr(
-        indicesElementType, APInt::getSignedMaxValue(32));
-    Value posInf = rewriter.create<arith::ConstantOp>(loc, posInfAttr);
-    Value negInfTensor =
-        rewriter.create<linalg::FillOp>(loc, negInf, emptyTensorOutputValues)
-            .result();
-    Value posInfTensor =
-        rewriter.create<linalg::FillOp>(loc, posInf, emptyTensorOutputIndices)
-            .result();
-
-    // Replace the CHLO TopK with LinalgExt TopK
-    uint64_t kDim = inputValuesType.getRank() - 1;
-    auto topkOp = rewriter.replaceOpWithNewOp<IREE::LinalgExt::TopkOp>(
-        op, op->getResultTypes(), ValueRange{operand},
-        ValueRange{negInfTensor, posInfTensor}, kDim);
-
-    // Define the region of TopK with a GT comparison
-    SmallVector<Type> types(2, valueElementType);
-    SmallVector<Location> locations(2, loc);
-    Block *block =
-        rewriter.createBlock(&topkOp.getRegion(), {}, types, locations);
-    {
-      OpBuilder::InsertionGuard guard(rewriter);
-      rewriter.setInsertionPointToStart(block);
-      Value lhs = block->getArgument(0);
-      Value rhs = block->getArgument(1);
-      Value condition;
-      if (llvm::isa<IntegerType>(valueElementType)) {
-        condition = rewriter.create<arith::CmpIOp>(
-            loc, arith::CmpIPredicate::sge, lhs, rhs);
-      } else {
-        condition = rewriter.create<arith::CmpFOp>(
-            loc, arith::CmpFPredicate::OGT, lhs, rhs);
-      }
-      rewriter.create<IREE::LinalgExt::YieldOp>(loc, condition);
-    }
-
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// Pass
-//===----------------------------------------------------------------------===//
-
-struct ConvertMHLOToLinalgExtPass
-    : public ConvertMHLOToLinalgExtBase<ConvertMHLOToLinalgExtPass> {
-  void getDependentDialects(DialectRegistry &registry) const override {
-    registry
-        .insert<IREE::LinalgExt::IREELinalgExtDialect, linalg::LinalgDialect,
-                IREE::Flow::FlowDialect, mlir::cf::ControlFlowDialect,
-                mlir::math::MathDialect, mlir::arith::ArithDialect,
-                complex::ComplexDialect, tensor::TensorDialect>();
-  }
-
-  void runOnOperation() override {
-    RewritePatternSet patterns(&getContext());
-    MLIRContext *context = &getContext();
-
-    MhloToStdTypeConverter typeConverter;
-    patterns.insert<SortOpConversion, ScatterOpConversion, FftOpConversion,
-                    ReverseOpConversion, TopkOpConversion>(typeConverter,
-                                                           context);
-    // FIXME: It shouldn't be necessary to list every matching MHLO op here,
-    // especially since they're already listed in
-    // populateHLOToLinalgConversionPattern and in HloOpToStdScalarOp. These
-    // lists are all the same. Can we leverage SFINAE here?
-    patterns
-        .insert<LinalgExtRegionHLOOpConversion<mhlo::AbsOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::AddOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::AndOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::Atan2Op>,
-                LinalgExtRegionHLOOpConversion<mhlo::BitcastConvertOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::CeilOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ClampOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::CompareOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ComplexOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ConvertOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::CopyOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::CosineOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::DivOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ExpOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::Expm1Op>,
-                LinalgExtRegionHLOOpConversion<mhlo::FloorOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ImagOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::IsFiniteOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::LogOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::LogisticOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::Log1pOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::MaxOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::MinOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::MulOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::NegOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::NotOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::OrOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::PowOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::RealOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::RemOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::RsqrtOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::SelectOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ShiftLeftOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ShiftRightArithmeticOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::ShiftRightLogicalOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::SignOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::SineOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::SqrtOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::SubtractOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::TanhOp>,
-                LinalgExtRegionHLOOpConversion<mhlo::XorOp>,
-                LinalgExtRegionReturnOpConversion>(typeConverter, context);
-
-    ConversionTarget target(getContext());
-    target.addLegalDialect<IREE::LinalgExt::IREELinalgExtDialect,
-                           linalg::LinalgDialect, IREE::Flow::FlowDialect,
-                           mlir::cf::ControlFlowDialect,
-                           mlir::math::MathDialect, mlir::arith::ArithDialect,
-                           tensor::TensorDialect, complex::ComplexDialect>();
-    // TODO: Scatter is not marked as illegal to allow falling back to the
-    // generic LinAlg lowering, the generic lowering is not always performant
-    // and even though only used in fallback here, may hide performance
-    // issues and we'd rather know when the optimized lowering fails.
-    target.addIllegalOp<mhlo::SortOp, mhlo::FftOp, mhlo::ReverseOp>();
-    // FFT conversion creates complex ops which will be converted by the normal
-    // MHLO lowering, but these should still be converted if present inside
-    // other linalg_ext op regions.
-    target.addDynamicallyLegalOp<mhlo::ComplexOp>(
-        [](mhlo::ComplexOp complexOp) {
-          return !isInBodyOfLinalgExtOps(complexOp);
-        });
-
-    if (failed(applyPartialConversion(getOperation(), target,
-                                      std::move(patterns)))) {
-      signalPassFailure();
-    }
-  }
-};
-}  // namespace
-
-std::unique_ptr<OperationPass<func::FuncOp>>
-createConvertMHLOToLinalgExtPass() {
-  return std::make_unique<ConvertMHLOToLinalgExtPass>();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToStableHLO.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToStableHLO.cpp
deleted file mode 100644
index c64b983..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/ConvertMHLOToStableHLO.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "mhlo/transforms/passes.h"
-#include "mlir/IR/BuiltinDialect.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/DialectRegistry.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Pass/PassManager.h"
-#include "stablehlo/dialect/StablehloOps.h"
-
-namespace mlir::iree_compiler::MHLO {
-namespace {
-struct ConvertMHLOToStableHLOPass final
-    : ConvertMHLOToStableHLOPassBase<ConvertMHLOToStableHLOPass> {
-  void runOnOperation() override {
-    OpPassManager pm(ModuleOp::getOperationName(),
-                     OpPassManager::Nesting::Explicit);
-    pm.addPass(mlir::mhlo::createHloLegalizeToStablehloPass());
-
-    if (failed(runPipeline(pm, getOperation()))) {
-      signalPassFailure();
-    }
-  }
-
-  void getDependentDialects(DialectRegistry& registry) const override {
-    registry.insert<mlir::stablehlo::StablehloDialect>();
-  }
-};
-}  // namespace
-
-std::unique_ptr<OperationPass<ModuleOp>> createConvertMHLOToStableHLOPass() {
-  return std::make_unique<ConvertMHLOToStableHLOPass>();
-}
-}  // namespace mlir::iree_compiler::MHLO
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp
deleted file mode 100644
index df2bae3..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/FlattenTuplesInCFG.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2019 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/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/iterator_range.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mlir/Dialect/Affine/Utils.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/IRMapping.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Pass/PassRegistry.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-// Given a set of types, unpack to a list of a types, removing all tuples.
-void untupleTypes(TypeRange types, llvm::SmallVectorImpl<Type> &newTypes) {
-  for (Type type : types) {
-    if (llvm::isa<TupleType>(type)) {
-      untupleTypes(llvm::dyn_cast<TupleType>(type).getTypes(), newTypes);
-    } else {
-      newTypes.push_back(type);
-    }
-  }
-}
-
-Value processTuple(Type type, Location loc, Block *block, OpBuilder &builder) {
-  if (!llvm::isa<TupleType>(type)) {
-    return block->addArgument(type, loc);
-  }
-
-  auto tupleType = llvm::dyn_cast<TupleType>(type);
-  llvm::SmallVector<Value, 4> values;
-  values.reserve(tupleType.size());
-  for (auto subtype : tupleType.getTypes()) {
-    values.push_back(processTuple(subtype, loc, block, builder));
-  }
-
-  return builder.create<mhlo::TupleOp>(loc, tupleType, values);
-}
-
-void copyOperationAttrs(Operation *oldOp, Operation *newOp) {
-  for (const auto &oldAttr : oldOp->getAttrs()) {
-    // Don't copy segment attributes as these correspond to the number operands,
-    // which may be different.
-    if (oldAttr.getName() == "operand_segment_sizes" ||
-        oldAttr.getName() == "result_segment_sizes")
-      continue;
-
-    newOp->setAttr(oldAttr.getName(), oldAttr.getValue());
-  }
-}
-
-bool recursiveUntuple(Value value, Location loc, OpBuilder &builder,
-                      IRMapping *mapping,
-                      llvm::SmallVectorImpl<Value> *newValues) {
-  Type type = value.getType();
-  // We can return the value as is.
-  if (!llvm::isa<TupleType>(type)) {
-    newValues->push_back(value);
-    return false;
-  }
-
-  TupleType tupleType = llvm::dyn_cast<TupleType>(type);
-  for (int i = 0; i < tupleType.size(); i++) {
-    auto subType = tupleType.getType(i);
-
-    auto elementOp = builder.create<mhlo::GetTupleElementOp>(
-        loc, subType, value, builder.getI32IntegerAttr(i));
-    recursiveUntuple(elementOp.getResult(), loc, builder, mapping, newValues);
-  }
-
-  return false;
-}
-
-Value recursiveRetuple(Type oldType, Operation::result_range *values,
-                       OpBuilder &builder, Location loc) {
-  if (!llvm::isa<TupleType>(oldType)) {
-    Value returnValue = *values->begin();
-    *values = {values->begin() + 1, values->end()};
-    return returnValue;
-  }
-
-  TupleType tupleType = llvm::dyn_cast<TupleType>(oldType);
-  llvm::SmallVector<Value, 10> subValues;
-  for (auto subtype : tupleType.getTypes()) {
-    subValues.push_back(recursiveRetuple(subtype, values, builder, loc));
-  }
-
-  return builder.create<mhlo::TupleOp>(loc, tupleType, subValues).getResult();
-}
-
-template <typename T>
-bool untupleAndLookupValues(T values, llvm::SmallVectorImpl<Value> *newValues,
-                            OpBuilder &builder, Location loc,
-                            IRMapping *mapping) {
-  for (auto operand : values) {
-    auto newValue = mapping->lookupOrNull(operand);
-    if (!newValue) {
-      return true;
-    }
-
-    recursiveUntuple(newValue, loc, builder, mapping, newValues);
-  }
-
-  return false;
-}
-
-bool convertReturnOp(mlir::func::ReturnOp *op, OpBuilder &builder,
-                     IRMapping *mapping) {
-  llvm::SmallVector<Value, 10> newOperands;
-  if (untupleAndLookupValues(op->getOperands(), &newOperands, builder,
-                             op->getLoc(), mapping)) {
-    return true;
-  }
-
-  builder.create<mlir::func::ReturnOp>(op->getLoc(), newOperands);
-  return false;
-}
-
-bool convertCallOp(func::CallOp *oldOp, OpBuilder &builder,
-                   IRMapping *mapping) {
-  llvm::SmallVector<Value, 4> newArgs;
-  if (untupleAndLookupValues(oldOp->getOperands(), &newArgs, builder,
-                             oldOp->getLoc(), mapping)) {
-    return true;
-  }
-
-  SmallVector<Type, 4> resultTypes;
-  untupleTypes(oldOp->getOperation()->getResultTypes(), resultTypes);
-  auto newOp = builder.create<func::CallOp>(oldOp->getLoc(), oldOp->getCallee(),
-                                            resultTypes, newArgs);
-  copyOperationAttrs(oldOp->getOperation(), newOp.getOperation());
-
-  auto newResults = newOp.getResults();
-  for (auto oldResult : oldOp->getResults()) {
-    llvm::SmallVector<Value, 10> subValues;
-    auto newResult = recursiveRetuple(oldResult.getType(), &newResults, builder,
-                                      oldOp->getLoc());
-    mapping->map(oldResult, newResult);
-  }
-
-  return false;
-}
-
-bool convertIndirectCallOp(func::CallIndirectOp *oldOp, OpBuilder &builder,
-                           IRMapping *mapping) {
-  llvm::SmallVector<Value, 4> newArgs;
-  if (untupleAndLookupValues(oldOp->getOperands(), &newArgs, builder,
-                             oldOp->getLoc(), mapping)) {
-    return true;
-  }
-
-  auto newOp = builder.create<func::CallIndirectOp>(
-      oldOp->getLoc(), oldOp->getCallee(), newArgs);
-  copyOperationAttrs(oldOp->getOperation(), newOp.getOperation());
-
-  for (int i = 0; i < newOp.getNumResults(); ++i) {
-    auto oldResult = oldOp->getResult(i);
-    auto newResult = newOp.getResult(i);
-    mapping->map(oldResult, newResult);
-  }
-
-  return false;
-}
-
-bool convertBranchOp(cf::BranchOp *oldOp, OpBuilder &builder,
-                     IRMapping *mapping) {
-  llvm::SmallVector<Value, 4> newArgs;
-  if (untupleAndLookupValues(oldOp->getOperands(), &newArgs, builder,
-                             oldOp->getLoc(), mapping)) {
-    return true;
-  }
-
-  auto newOp = builder.create<cf::BranchOp>(
-      oldOp->getLoc(), mapping->lookupOrNull(oldOp->getDest()), newArgs);
-
-  copyOperationAttrs(oldOp->getOperation(), newOp.getOperation());
-
-  return false;
-}
-
-bool convertCondBranchOp(cf::CondBranchOp *oldOp, OpBuilder &builder,
-                         IRMapping *mapping) {
-  llvm::SmallVector<Value, 4> trueArgs;
-  if (untupleAndLookupValues(oldOp->getTrueOperands(), &trueArgs, builder,
-                             oldOp->getLoc(), mapping)) {
-    return true;
-  }
-
-  llvm::SmallVector<Value, 4> falseArgs;
-  if (untupleAndLookupValues(oldOp->getFalseOperands(), &falseArgs, builder,
-                             oldOp->getLoc(), mapping)) {
-    return true;
-  }
-
-  auto newOp = builder.create<cf::CondBranchOp>(
-      oldOp->getLoc(), mapping->lookupOrNull(oldOp->getCondition()),
-      mapping->lookupOrNull(oldOp->getTrueDest()), trueArgs,
-      mapping->lookupOrNull(oldOp->getFalseDest()), falseArgs);
-
-  copyOperationAttrs(oldOp->getOperation(), newOp.getOperation());
-
-  return false;
-}
-
-bool convertOperation(Operation *op, OpBuilder &builder, IRMapping *mapping) {
-  if (auto returnOp = dyn_cast<mlir::func::ReturnOp>(op)) {
-    return convertReturnOp(&returnOp, builder, mapping);
-  } else if (auto callOp = dyn_cast<func::CallOp>(op)) {
-    return convertCallOp(&callOp, builder, mapping);
-  } else if (auto callIndirectOp = dyn_cast<func::CallIndirectOp>(op)) {
-    return convertIndirectCallOp(&callIndirectOp, builder, mapping);
-  } else if (auto branchOp = dyn_cast<cf::BranchOp>(op)) {
-    return convertBranchOp(&branchOp, builder, mapping);
-  } else if (auto condBranchOp = dyn_cast<cf::CondBranchOp>(op)) {
-    return convertCondBranchOp(&condBranchOp, builder, mapping);
-  }
-
-  builder.clone(*op, *mapping);
-  return false;
-}
-
-bool convertFunction(func::FuncOp oldFunction, func::FuncOp newFunction) {
-  OpBuilder builder(newFunction.getBody());
-  IRMapping mapping;
-
-  // Check whether has tuple in signature.
-  bool hasTupleSig = (oldFunction.getArgumentTypes().size() !=
-                      newFunction.getArgumentTypes().size()) ||
-                     (oldFunction.getResultTypes().size() !=
-                      newFunction.getResultTypes().size());
-
-  // Cache unused XLA ABI marker names.
-  auto xlaAbiParam = StringAttr::get(newFunction.getContext(),
-                                     "xla_entry_computation_parameter_layouts"),
-       xlaAbiLayout = StringAttr::get(newFunction.getContext(),
-                                      "xla_entry_computation_result_layout");
-
-  for (auto attr : oldFunction->getAttrs()) {
-    if (attr.getName() == oldFunction.getFunctionTypeAttrName() ||
-        // Currently skipping all arg, result and XLA specific ABI attributes.
-        attr.getName() == xlaAbiParam || attr.getName() == xlaAbiLayout)
-      continue;
-    // If it has tuples in sig, then skip arg and res attrs. None of the
-    // existing ones along path that produces tuples are used further, so just
-    // remove instead of flattening.
-    if (hasTupleSig && (attr.getName() == oldFunction.getArgAttrsAttrName() ||
-                        attr.getName() == oldFunction.getResAttrsAttrName()))
-      continue;
-    newFunction->setAttr(attr.getName(), attr.getValue());
-  }
-
-  newFunction.getBlocks().clear();
-  for (auto &oldBlock : oldFunction.getBlocks()) {
-    auto *newBlock = builder.createBlock(&newFunction.getBody());
-    for (auto oldArg : oldBlock.getArguments()) {
-      llvm::SmallVector<Type, 4> newTypes;
-      untupleTypes(oldArg.getType(), newTypes);
-
-      Value newTuple = processTuple(oldArg.getType(), oldFunction.getLoc(),
-                                    newBlock, builder);
-      if (!newTuple) {
-        return true;
-      }
-
-      mapping.map(oldArg, newTuple);
-    }
-    mapping.map(&oldBlock, newBlock);
-  }
-
-  // Convert all ops in the blocks.
-  for (auto &oldBlock : oldFunction.getBlocks()) {
-    builder.setInsertionPointToEnd(mapping.lookupOrNull(&oldBlock));
-    for (auto &oldOp : oldBlock.getOperations()) {
-      if (convertOperation(&oldOp, builder, &mapping)) {
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-class FlattenTuplesInCFGPass
-    : public FlattenTuplesInCFGBase<FlattenTuplesInCFGPass> {
- public:
-  void runOnOperation() override {
-    auto module = getOperation();
-    Builder builder(module.getContext());
-
-    // Build a list of (oldFunction, newFunction) for all functions we need to
-    // replace. This will ensure that when we go to convert function bodies we
-    // have only new functions defined.
-    std::vector<std::pair<func::FuncOp, func::FuncOp>> convertedFunctions;
-
-    for (auto oldFunction : module.getOps<func::FuncOp>()) {
-      auto oldFunctionType = oldFunction.getFunctionType();
-
-      llvm::SmallVector<Type, 10> newInputTypes;
-      untupleTypes(oldFunctionType.getInputs(), newInputTypes);
-
-      llvm::SmallVector<Type, 10> newResultTypes;
-      untupleTypes(oldFunctionType.getResults(), newResultTypes);
-
-      auto newFunctionType =
-          builder.getFunctionType(newInputTypes, newResultTypes);
-      auto newFunction =
-          func::FuncOp::create(oldFunction.getLoc(), oldFunction.getName(),
-                               newFunctionType, oldFunction->getDialectAttrs());
-      convertedFunctions.push_back({oldFunction, newFunction});
-
-      // Perform the actual body conversion now that we have proper signatures.
-      if (convertFunction(oldFunction, newFunction)) {
-        return signalPassFailure();
-      }
-    }
-
-    // Replace functions in the module.
-    for (auto &pair : convertedFunctions) {
-      pair.first.erase();
-      module.push_back(pair.second);
-    }
-  }
-};
-
-}  // namespace
-
-std::unique_ptr<OperationPass<ModuleOp>> createFlattenTuplesInCFGPass() {
-  return std::make_unique<FlattenTuplesInCFGPass>();
-}
-
-static PassRegistration<FlattenTuplesInCFGPass> pass;
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
deleted file mode 100644
index 75d0de5..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToLinalgOnTensors.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-// Copyright 2020 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
-
-//===- XLAToLinalgOnTensors.cpp - Pass to convert XLA to Linalg on tensors-===//
-//
-// Pass to convert from XLA to linalg on tensers. Uses the patterns from
-// tensorflow/compiler/mlir/xla/transforms/legalize_to_linalg.cc along with
-// some IREE specific patterns.
-//
-//===----------------------------------------------------------------------===//
-#include <memory>
-
-#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtDialect.h"
-#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
-#include "iree/compiler/Dialect/Util/IR/UtilDialect.h"
-#include "iree/compiler/Dialect/Util/IR/UtilOps.h"
-#include "iree/compiler/InputConversion/MHLO/ConvertMHLOToFlow.h"
-#include "iree/compiler/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "iree/compiler/InputConversion/MHLO/Rewriters.h"
-#include "iree/compiler/Utils/ConversionUtils.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mhlo/transforms/rewriters.h"
-#include "mhlo/utils/legalize_to_linalg_utils.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Complex/IR/Complex.h"
-#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/Linalg/IR/Linalg.h"
-#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
-#include "mlir/Dialect/MLProgram/IR/MLProgram.h"
-#include "mlir/Dialect/Math/IR/Math.h"
-#include "mlir/Dialect/MemRef/IR/MemRef.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/Attributes.h"
-#include "mlir/IR/Builders.h"
-#include "mlir/IR/BuiltinAttributes.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/Location.h"
-#include "mlir/IR/MLIRContext.h"
-#include "mlir/IR/Matchers.h"
-#include "mlir/IR/Operation.h"
-#include "mlir/IR/PatternMatch.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Transforms/DialectConversion.h"
-#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
-#include "mlir/Transforms/Passes.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-//===----------------------------------------------------------------------===//
-// mhlo.concatenate conversion patterns.
-//===----------------------------------------------------------------------===//
-
-namespace {
-/// Converts mhlo.concatenate operation to extract_slice ops + insert_slice ops.
-struct ConcatenateOpConversion
-    : public OpConversionPattern<mhlo::ConcatenateOp> {
-  using OpConversionPattern<mhlo::ConcatenateOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::ConcatenateOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto resultType = llvm::dyn_cast<RankedTensorType>(
-        this->typeConverter->convertType(op.getResult().getType()));
-    if (!resultType || !resultType.hasStaticShape()) {
-      return rewriter.notifyMatchFailure(op,
-                                         "expected static shape for output");
-    }
-
-    Location loc = op.getLoc();
-    int dim = op.getDimension();
-    int rank = resultType.getRank();
-    SmallVector<Value, 3> offsets, sizes, strides;
-    for (int i = 0; i < rank; ++i) {
-      offsets.push_back(rewriter.create<arith::ConstantIndexOp>(loc, 0));
-      sizes.push_back(rewriter.createOrFold<tensor::DimOp>(
-          loc, adaptor.getOperands()[0], i));
-      strides.push_back(rewriter.create<arith::ConstantIndexOp>(loc, 1));
-    }
-    Value resultDimSize = rewriter.create<arith::ConstantIndexOp>(loc, 0);
-    for (auto arg : adaptor.getOperands()) {
-      auto size = rewriter.createOrFold<tensor::DimOp>(loc, arg, dim);
-      resultDimSize =
-          rewriter.createOrFold<arith::AddIOp>(loc, resultDimSize, size);
-    }
-    sizes[dim] = resultDimSize;
-    Value result = rewriter.create<tensor::EmptyOp>(
-        loc, resultType.getShape(), resultType.getElementType());
-
-    auto toOpFoldResult = [](Value v) -> OpFoldResult {
-      auto op = v.getDefiningOp<arith::ConstantIndexOp>();
-      if (!op) return v;
-      return op.getValue();
-    };
-
-    Value accBound = rewriter.create<arith::ConstantIndexOp>(loc, 0);
-    for (auto arg : adaptor.getOperands()) {
-      offsets[dim] = accBound;
-      sizes[dim] = rewriter.createOrFold<tensor::DimOp>(loc, arg, dim);
-      result = rewriter.create<tensor::InsertSliceOp>(
-          loc, arg, result, llvm::map_to_vector(offsets, toOpFoldResult),
-          llvm::map_to_vector(sizes, toOpFoldResult),
-          llvm::map_to_vector(strides, toOpFoldResult));
-      accBound = rewriter.create<arith::AddIOp>(loc, accBound, sizes[dim]);
-    }
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-//===----------------------------------------------------------------------===//
-// mhlo.fft conversion patterns.
-//===----------------------------------------------------------------------===//
-
-/// Creats coefficients based on DFT definition, see
-/// https://en.wikipedia.org/wiki/Discrete_Fourier_transform
-Value getDFTMatmulCoeff(OpBuilder b, Location loc, RankedTensorType matrixType,
-                        bool isRealPart) {
-  // scale = 2 * pi / N
-  double scale = 2 * M_PI / matrixType.getDimSize(0);
-
-  SmallVector<Attribute> values;
-  assert(matrixType.getRank() == 2 && "expected 2D matrix");
-  for (auto i : llvm::seq<unsigned>(0, matrixType.getDimSize(0))) {
-    for (auto j : llvm::seq<unsigned>(0, matrixType.getDimSize(1))) {
-      double v = scale * i * j;
-      if (isRealPart) {
-        v = cos(v);
-      } else {
-        v = -sin(v);
-      }
-      values.push_back(b.getF32FloatAttr(v));
-    }
-  }
-  return b.create<arith::ConstantOp>(
-      loc, matrixType, DenseFPElementsAttr::get(matrixType, values));
-}
-
-Value createLinalgMatmulOnTensors(OpBuilder b, Location loc,
-                                  RankedTensorType resultType, Value lhs,
-                                  Value rhs) {
-  Value zero = b.create<arith::ConstantOp>(
-      loc, b.getZeroAttr(resultType.getElementType()));
-  Value emptyTensor = b.create<mlir::tensor::EmptyOp>(
-      loc, resultType.getShape(), resultType.getElementType(),
-      /*dyn_size=*/ValueRange{});
-  Value zeroTensor =
-      b.create<linalg::FillOp>(loc, zero, emptyTensor).getResult(0);
-
-  switch (llvm::cast<RankedTensorType>(lhs.getType()).getRank()) {
-    case 1:
-      return b
-          .create<linalg::VecmatOp>(loc, TypeRange{resultType},
-                                    ValueRange{lhs, rhs},
-                                    ValueRange{zeroTensor})
-          .getResult(0);
-    case 2:
-      return b
-          .create<linalg::MatmulOp>(loc, TypeRange{resultType},
-                                    ValueRange{lhs, rhs},
-                                    ValueRange{zeroTensor})
-          .getResult(0);
-    default:
-      assert(false && "unhandled matmul type");
-      return Value();
-  }
-}
-
-/// Converts mhlo.fft operation to Linalg ops.
-struct FftOpConversion : public OpConversionPattern<mhlo::FftOp> {
-  using OpConversionPattern<mhlo::FftOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::FftOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    if (op.getFftType() != mhlo::FftType::RFFT) {
-      return rewriter.notifyMatchFailure(op,
-                                         "non RFFT types are supported yet");
-    }
-
-    auto inputType =
-        llvm::dyn_cast<RankedTensorType>(adaptor.getOperand().getType());
-    if (!inputType || !inputType.hasStaticShape() || inputType.getRank() > 2) {
-      return rewriter.notifyMatchFailure(op, "only static 1D or 2D dft ops");
-    }
-
-    int rank = inputType.getRank();
-    int n = inputType.getDimSize(rank - 1);
-    int fftLength =
-        op.getFftLength().getSplatValue<IntegerAttr>().getInt() / 2 + 1;
-
-    Location loc = op.getLoc();
-    auto matrixType =
-        RankedTensorType::get({n, fftLength}, inputType.getElementType());
-    auto resultType = RankedTensorType::get(
-        llvm::cast<RankedTensorType>(op.getType()).getShape(),
-        inputType.getElementType());
-
-    auto realMatrix =
-        getDFTMatmulCoeff(rewriter, loc, matrixType, /*isRealPart=*/true);
-    auto real = createLinalgMatmulOnTensors(rewriter, loc, resultType,
-                                            adaptor.getOperand(), realMatrix);
-
-    auto imagMatrix =
-        getDFTMatmulCoeff(rewriter, loc, matrixType, /*isRealPart=*/false);
-    auto imag = createLinalgMatmulOnTensors(rewriter, loc, resultType,
-                                            adaptor.getOperand(), imagMatrix);
-
-    // Pack the results back to mhlo::ComplexOp.
-    rewriter.replaceOpWithNewOp<mhlo::ComplexOp>(op, op.getType(), real, imag);
-    return success();
-  }
-};
-
-struct OptimizationBarrierOpConversion
-    : public OpConversionPattern<mhlo::OptimizationBarrierOp> {
-  using OpConversionPattern<mhlo::OptimizationBarrierOp>::OpConversionPattern;
-
-  LogicalResult matchAndRewrite(
-      mhlo::OptimizationBarrierOp op, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    SmallVector<Value> outputs;
-    for (auto operand : adaptor.getOperands()) {
-      outputs.push_back(
-          rewriter
-              .create<IREE::Util::OptimizationBarrierOp>(op.getLoc(), operand)
-              .getResult(0));
-    }
-    rewriter.replaceOp(op, outputs);
-    return success();
-  }
-};
-
-// Returns true if all attributes in the given dictionary are valid for IREE
-// input dialects.
-static bool isValidFuncAttr(DictionaryAttr attrs) {
-  // TODO: switch to using a dialect-based exclusion list or some other way that
-  // is not a big string table.
-  for (auto attr : attrs) {
-    if (attr.getName() == "tf.aliasing_output") return false;
-  }
-  return true;
-}
-
-// Adds iree.abi.encoding attributes for arguments and results when they have
-// had their type changed during conversion.
-static void setFuncEncodings(func::FuncOp funcOp, FunctionType oldFuncType,
-                             FunctionType newFuncType) {
-  auto encodingName = StringAttr::get(funcOp.getContext(), "iree.abi.encoding");
-  for (auto [i, oldType, newType] :
-       llvm::enumerate(oldFuncType.getInputs(), newFuncType.getInputs())) {
-    if (oldType != newType)
-      funcOp.setArgAttr(i, encodingName, TypeAttr::get(oldType));
-  }
-  for (auto [i, oldType, newType] :
-       llvm::enumerate(oldFuncType.getResults(), newFuncType.getResults())) {
-    if (oldType != newType)
-      funcOp.setResultAttr(i, encodingName, TypeAttr::get(oldType));
-  }
-}
-
-// Rewrites attributes on the function from ones coming from HLO-based frontends
-// to the IREE supported versions.
-static void rewriteFuncAttrs(func::FuncOp funcOp) {
-  auto *context = funcOp.getContext();
-  auto indexType = IndexType::get(context);
-  auto abiOutputName = StringAttr::get(context, "iree.abi.output");
-  auto aliasingOutputName = StringAttr::get(context, "tf.aliasing_output");
-  auto rewriteAttrs = [&](DictionaryAttr &allAttrs) {
-    SmallVector<NamedAttribute> newAttrs;
-    newAttrs.reserve(allAttrs.size());
-    for (auto attr : allAttrs) {
-      if (attr.getName() == aliasingOutputName) {
-        newAttrs.push_back({
-            abiOutputName,
-            IntegerAttr::get(indexType,
-                             llvm::cast<IntegerAttr>(attr.getValue()).getInt()),
-        });
-      } else {
-        newAttrs.push_back(attr);
-      }
-    }
-    allAttrs = DictionaryAttr::get(context, newAttrs);
-  };
-  SmallVector<DictionaryAttr> argAttrs;
-  funcOp.getAllArgAttrs(argAttrs);
-  llvm::for_each(argAttrs, rewriteAttrs);
-  funcOp.setAllArgAttrs(argAttrs);
-  SmallVector<DictionaryAttr> resultAttrs;
-  funcOp.getAllResultAttrs(resultAttrs);
-  llvm::for_each(resultAttrs, rewriteAttrs);
-  funcOp.setAllResultAttrs(resultAttrs);
-}
-
-// We need to convert func ops in order to convert types.
-class BuiltinFuncOpPattern : public OpConversionPattern<func::FuncOp> {
-  using OpConversionPattern<func::FuncOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      func::FuncOp srcOp, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    FunctionType srcFuncType = srcOp.getFunctionType();
-    TypeConverter::SignatureConversion signatureConversion(
-        srcOp.getNumArguments());
-
-    // Convert function arguments.
-    for (unsigned i = 0, e = srcFuncType.getNumInputs(); i < e; ++i) {
-      if (failed(getTypeConverter()->convertSignatureArg(
-              i, srcFuncType.getInput(i), signatureConversion))) {
-        return rewriter.notifyMatchFailure(srcOp, "argument failed to convert");
-      }
-    }
-
-    // Convert function results.
-    SmallVector<Type> convertedResultTypes;
-    if (failed(getTypeConverter()->convertTypes(srcFuncType.getResults(),
-                                                convertedResultTypes))) {
-      return rewriter.notifyMatchFailure(srcOp, "results failed to convert");
-    }
-
-    // Create new function with converted argument and result types.
-    auto oldFuncType = srcOp.getFunctionType();
-    auto newFuncType = mlir::FunctionType::get(
-        srcOp.getContext(), signatureConversion.getConvertedTypes(),
-        convertedResultTypes);
-
-    // Update the function in place.
-    rewriter.startRootUpdate(srcOp);
-    srcOp.setType(newFuncType);
-    rewriteFuncAttrs(srcOp);
-    setFuncEncodings(srcOp, oldFuncType, newFuncType);
-
-    // Tell the rewriter to convert the region signature.
-    TypeConverter &typeConverter = *getTypeConverter();
-    if (failed(rewriter.convertRegionTypes(&srcOp.getBody(), typeConverter,
-                                           &signatureConversion))) {
-      return failure();
-    }
-
-    rewriter.finalizeRootUpdate(srcOp);
-    return success();
-  }
-};
-
-class GlobalOpPattern : public OpConversionPattern<ml_program::GlobalOp> {
- public:
-  using OpConversionPattern<ml_program::GlobalOp>::OpConversionPattern;
-  LogicalResult matchAndRewrite(
-      ml_program::GlobalOp globalOp, OpAdaptor adaptor,
-      ConversionPatternRewriter &rewriter) const override {
-    auto oldType = globalOp.getType();
-    auto newType = getTypeConverter()->convertType(oldType);
-    if (newType == oldType) return failure();
-    if (!newType) {
-      return rewriter.notifyMatchFailure(globalOp,
-                                         "result type conversion failed");
-    }
-    rewriter.updateRootInPlace(globalOp, [&]() {
-      globalOp.setType(newType);
-      if (auto oldValue = globalOp.getValueAttr()) {
-        globalOp.setValueAttr(
-            convertAttribute(globalOp.getLoc(), oldValue, *getTypeConverter()));
-      }
-    });
-    return success();
-  }
-};
-
-class GenericTypeConvert : public ConversionPattern {
- public:
-  GenericTypeConvert(StringRef rootName, TypeConverter &converter,
-                     MLIRContext *context, PatternBenefit benefit = 0)
-      : ConversionPattern(converter, rootName, benefit, context) {}
-  LogicalResult matchAndRewrite(
-      Operation *op, ArrayRef<Value> operands,
-      ConversionPatternRewriter &rewriter) const override {
-    llvm::SmallVector<NamedAttribute, 4> newAttr;
-    llvm::append_range(newAttr, op->getAttrs());
-    llvm::SmallVector<Type, 4> newResults;
-    if (failed(getTypeConverter()->convertTypes(op->getResultTypes(),
-                                                newResults))) {
-      return rewriter.notifyMatchFailure(op, "result type conversion failed");
-    }
-    OperationState state(op->getLoc(), op->getName().getStringRef(), operands,
-                         newResults, newAttr, op->getSuccessors());
-    for (Region &r : op->getRegions()) {
-      Region *newRegion = state.addRegion();
-      rewriter.inlineRegionBefore(r, *newRegion, newRegion->begin());
-      TypeConverter::SignatureConversion result(newRegion->getNumArguments());
-      if (failed(getTypeConverter()->convertSignatureArgs(
-              newRegion->getArgumentTypes(), result))) {
-        return rewriter.notifyMatchFailure(op,
-                                           "argument type conversion failed");
-      }
-      rewriter.applySignatureConversion(newRegion, result);
-    }
-    Operation *newOp = rewriter.create(state);
-    rewriter.replaceOp(op, newOp->getResults());
-    return success();
-  }
-};
-
-std::optional<Value> scalarToTensor(OpBuilder &builder, Type /*type*/,
-                                    ValueRange inputs, Location loc) {
-  assert(inputs.size() == 1);
-  if (llvm::isa<ShapedType>(inputs.front().getType())) {
-    return std::nullopt;
-  }
-  return builder
-      .create<tensor::FromElementsOp>(
-          loc, RankedTensorType::get({}, inputs.front().getType()),
-          inputs.front())
-      .getResult();
-}
-
-std::optional<Value> materializeCastFromIllegal(OpBuilder &builder, Type type,
-                                                ValueRange inputs,
-                                                Location loc) {
-  Type fromType = getElementTypeOrSelf(inputs[0].getType());
-  Type toType = getElementTypeOrSelf(type);
-  if ((!fromType.isSignedInteger() && !fromType.isUnsignedInteger()) ||
-      !toType.isSignlessInteger())
-    return std::nullopt;
-  // Use bitcast to do signless->signful conversions.
-  return builder.create<tensor::BitcastOp>(loc, type, inputs[0])->getResult(0);
-}
-
-std::optional<Value> materializeCastToIllegal(OpBuilder &builder, Type type,
-                                              ValueRange inputs, Location loc) {
-  Type fromType = getElementTypeOrSelf(inputs[0].getType());
-  Type toType = getElementTypeOrSelf(type);
-  if (!fromType.isSignlessInteger() ||
-      (!toType.isSignedInteger() && !toType.isUnsignedInteger()))
-    return std::nullopt;
-  // Use bitcast to do signless->signful conversions.
-  return builder.create<tensor::BitcastOp>(loc, type, inputs[0])->getResult(0);
-}
-
-struct ConvertMHLOToLinalgOnTensorsPass
-    : public ConvertMHLOToLinalgOnTensorsBase<
-          ConvertMHLOToLinalgOnTensorsPass> {
-  void getDependentDialects(DialectRegistry &registry) const override {
-    registry.insert<
-        IREE::Flow::FlowDialect, IREE::Util::UtilDialect, linalg::LinalgDialect,
-        mhlo::MhloDialect, shape::ShapeDialect, tensor::TensorDialect,
-        math::MathDialect, memref::MemRefDialect, complex::ComplexDialect>();
-  }
-
-  void runOnOperation() override {
-    RewritePatternSet patterns(&getContext());
-    MLIRContext *context = &getContext();
-
-    auto typeConverter = mhlo::createHloToLinalgTypeConverter();
-    typeConverter->addArgumentMaterialization(scalarToTensor);
-    typeConverter->addArgumentMaterialization(materializeCastFromIllegal);
-    typeConverter->addTargetMaterialization(materializeCastFromIllegal);
-    typeConverter->addSourceMaterialization(materializeCastToIllegal);
-    // NOTE: not using corresponding setupMHLOToFlowPatterns because the entire
-    // MHLO dialects are marked illegal by this pass.
-    // TODO: Collapse/rework all of these patterns once the consolidation
-    // lands. There is little reason to have these so spread out.
-    populateMHLOToFlowPatterns(context, patterns);
-
-    chlo::populateDecomposeChloPatterns(context, &patterns);
-    populateMHLOBroadcastingToLinalgPatterns(context, *typeConverter, patterns);
-    mhlo::populateScalarHloToArithmeticConversionPatterns(
-        context, *typeConverter, &patterns,
-        [](Operation *op) { return mhlo::isInBodyOfLinalgOps(op); });
-    populateMHLOToLinalgOnTensorsConversionPatterns(context, *typeConverter,
-                                                    patterns);
-    populateMHLOComplexToRealPatterns(context, *typeConverter, patterns);
-
-    populateMHLOCollectiveOpsConversionPatterns(context, *typeConverter,
-                                                patterns);
-    // TODO(*): expose patterns that do this much better from
-    // iree/compiler/Dialect/Util/Transforms/ConvertPrimitiveType.cpp
-
-    // Structural patterns (functions, cfg, terminators).
-    patterns.insert<BuiltinFuncOpPattern>(*typeConverter, context);
-    patterns.insert<GenericTypeConvert>(func::ReturnOp::getOperationName(),
-                                        *typeConverter, context);
-    patterns.insert<GenericTypeConvert>(func::CallOp::getOperationName(),
-                                        *typeConverter, context);
-    patterns.insert<GenericTypeConvert>(cf::CondBranchOp::getOperationName(),
-                                        *typeConverter, context);
-    patterns.insert<GenericTypeConvert>(cf::BranchOp::getOperationName(),
-                                        *typeConverter, context);
-    patterns.insert<GlobalOpPattern>(*typeConverter, context);
-    patterns.insert<GenericTypeConvert>(
-        ml_program::GlobalLoadOp::getOperationName(), *typeConverter, context);
-    patterns.insert<GenericTypeConvert>(
-        ml_program::GlobalLoadConstOp::getOperationName(), *typeConverter,
-        context);
-    patterns.insert<GenericTypeConvert>(
-        ml_program::GlobalStoreOp::getOperationName(), *typeConverter, context);
-    // This is needed when converting mhlo::ReplicaIDOp.
-    patterns.insert<GenericTypeConvert>(
-        tensor::FromElementsOp::getOperationName(), *typeConverter, context);
-    patterns.insert<GenericTypeConvert>(
-        arith::IndexCastUIOp::getOperationName(), *typeConverter, context);
-    ConversionTarget target(getContext());
-
-    auto isIllegalType = [&](Type t) { return !typeConverter->isLegal(t); };
-    auto isLegallyTypedOp = [&](Operation *op) -> bool {
-      for (Type type : op->getResultTypes()) {
-        if (isIllegalType(type)) return false;
-      }
-      for (Type type : op->getOperandTypes()) {
-        if (isIllegalType(type)) return false;
-      }
-      return true;
-    };
-
-    target.addIllegalDialect<chlo::ChloDialect>();
-    target.addIllegalDialect<mhlo::MhloDialect>();
-
-    // Functions must have legal types.
-    target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp funcOp) {
-      if (auto attrs = funcOp.getAllArgAttrs()) {
-        if (!llvm::all_of(attrs.getAsRange<DictionaryAttr>(),
-                          isValidFuncAttr)) {
-          return false;
-        }
-      }
-      if (auto attrs = funcOp.getAllResultAttrs()) {
-        if (!llvm::all_of(attrs.getAsRange<DictionaryAttr>(),
-                          isValidFuncAttr)) {
-          return false;
-        }
-      }
-      for (Type type : funcOp.getFunctionType().getInputs()) {
-        if (isIllegalType(type)) return false;
-      }
-      for (Type type : funcOp.getFunctionType().getResults()) {
-        if (isIllegalType(type)) return false;
-      }
-      for (Block &block : funcOp.getFunctionBody()) {
-        for (Type type : block.getArgumentTypes()) {
-          if (isIllegalType(type)) return false;
-        }
-      }
-      return true;
-    });
-    target.addDynamicallyLegalOp<func::ReturnOp>([&](func::ReturnOp op) {
-      return llvm::all_of(op.getOperandTypes(),
-                          [&](Type type) { return !isIllegalType(type); });
-    });
-    target.addDynamicallyLegalOp<func::CallOp>([&](func::CallOp op) {
-      return llvm::all_of(op.getOperandTypes(),
-                          [&](Type type) { return !isIllegalType(type); });
-    });
-    target.addDynamicallyLegalOp<cf::CondBranchOp>([&](cf::CondBranchOp op) {
-      return llvm::all_of(op.getOperandTypes(),
-                          [&](Type type) { return !isIllegalType(type); });
-    });
-    target.addDynamicallyLegalOp<cf::BranchOp>([&](cf::BranchOp op) {
-      return llvm::all_of(op.getOperandTypes(),
-                          [&](Type type) { return !isIllegalType(type); });
-    });
-    target.addDynamicallyLegalOp<ml_program::GlobalOp>(
-        [&](ml_program::GlobalOp op) {
-          return typeConverter->isLegal(op.getType());
-        });
-
-    // Let the rest fall through.
-    target.addLegalDialect<BuiltinDialect>();
-    target.addLegalDialect<IREE::LinalgExt::IREELinalgExtDialect>();
-    target.addLegalOp<tensor::BitcastOp>();
-    target.markUnknownOpDynamicallyLegal(isLegallyTypedOp);
-
-    if (failed(applyPartialConversion(getOperation(), target,
-                                      std::move(patterns)))) {
-      return signalPassFailure();
-    }
-
-    {
-      // Apply the patterns to remove unused operands and results.
-      RewritePatternSet removeUnusedOperandsResultsPatterns(&getContext());
-      linalg::populateEraseUnusedOperandsAndResultsPatterns(
-          removeUnusedOperandsResultsPatterns);
-      if (failed(applyPatternsAndFoldGreedily(
-              getOperation(),
-              std::move(removeUnusedOperandsResultsPatterns)))) {
-        return signalPassFailure();
-      }
-    }
-  }
-};
-
-}  // namespace
-
-void populateMHLOToLinalgOnTensorsConversionPatterns(
-    MLIRContext *context, TypeConverter &typeConverter,
-    RewritePatternSet &patterns) {
-  mhlo::populateHloToLinalgConversionPattern(context, typeConverter, &patterns);
-  // TODO(#5809): Drop ConcatenateOp lowering in favor of the upstream version
-  //              then remove the PatternBenefit here
-  patterns.insert<ConcatenateOpConversion, FftOpConversion,
-                  OptimizationBarrierOpConversion>(typeConverter, context,
-                                                   PatternBenefit(1000));
-}
-
-std::unique_ptr<OperationPass<ModuleOp>> createMHLOToLinalgOnTensorsPass() {
-  return std::make_unique<ConvertMHLOToLinalgOnTensorsPass>();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToMHLOPreprocessing.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToMHLOPreprocessing.cpp
deleted file mode 100644
index c627f25..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/MHLOToMHLOPreprocessing.cpp
+++ /dev/null
@@ -1,1535 +0,0 @@
-// Copyright 2020 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 <numeric>
-#include <random>
-
-#include "iree/compiler/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Casting.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mhlo/transforms/rewriters.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/Math/IR/Math.h"
-#include "mlir/Dialect/Shape/IR/Shape.h"
-#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/Attributes.h"
-#include "mlir/IR/BuiltinTypes.h"
-#include "mlir/IR/ImplicitLocOpBuilder.h"
-#include "mlir/IR/TypeUtilities.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LogicalResult.h"
-#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-namespace {
-
-static bool isIota(ArrayRef<int64_t> array) {
-  for (auto it : llvm::enumerate(array)) {
-    if (it.index() != it.value()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static DenseIntElementsAttr make1DElementsAttr(OpBuilder &b,
-                                               ArrayRef<int64_t> integers) {
-  auto type = RankedTensorType::get({static_cast<int64_t>(integers.size())},
-                                    b.getIntegerType(64));
-  return DenseIntElementsAttr::get(type, integers);
-}
-
-static DenseIntElementsAttr make1DElementsAttr(OpBuilder &b, int64_t start,
-                                               int64_t num) {
-  return make1DElementsAttr(
-      b, llvm::to_vector<4>(llvm::seq<int64_t>(start, start + num)));
-}
-
-static Value getF32Const(ImplicitLocOpBuilder b, ArrayRef<int64_t> shapes,
-                         ArrayRef<float> values) {
-  RankedTensorType ty = RankedTensorType::get(shapes, b.getF32Type());
-  return b.create<mhlo::ConstantOp>(DenseFPElementsAttr::get(ty, values))
-      .getResult();
-}
-
-// Guarantee that the input dimensions are ordered batch, spatial_dims, feature
-// dim.
-class ReorderConvOpInputDimensions
-    : public OpRewritePattern<mhlo::ConvolutionOp> {
- public:
-  using OpRewritePattern<mhlo::ConvolutionOp>::OpRewritePattern;
-  LogicalResult matchAndRewrite(mhlo::ConvolutionOp op,
-                                PatternRewriter &rewriter) const override {
-    auto lhsType = llvm::cast<ShapedType>(op.getLhs().getType());
-    auto lhsShape = lhsType.getShape();
-    if (!lhsType.hasRank()) {
-      return failure();
-    }
-
-    auto dimensionNumbers = op.getDimensionNumbers();
-    auto spatialDims = dimensionNumbers.getInputSpatialDimensions();
-
-    // Compute the permutation required to create a standard order.
-    llvm::SmallVector<int64_t, 4> permutations;
-    permutations.push_back(dimensionNumbers.getInputBatchDimension());
-    permutations.append(spatialDims.begin(), spatialDims.end());
-    permutations.push_back(dimensionNumbers.getInputFeatureDimension());
-
-    // If the permutation is iota then no reordering is required.
-    if (isIota(permutations)) {
-      return failure();
-    }
-
-    llvm::SmallVector<int64_t, 4> transposeShape;
-    for (auto p : permutations) {
-      transposeShape.push_back(lhsShape[p]);
-    }
-
-    auto transposed = rewriter.create<mhlo::TransposeOp>(
-        op.getLoc(),
-        RankedTensorType::get(transposeShape, lhsType.getElementType()),
-        op.getLhs(), rewriter.getI64TensorAttr(permutations));
-
-    llvm::SmallVector<int64_t, 4> newSpatialDimensions(spatialDims.size());
-    std::iota(newSpatialDimensions.begin(), newSpatialDimensions.end(), 1);
-
-    auto newDimensionNumbers = mhlo::ConvDimensionNumbersAttr::get(
-        op.getContext(),
-        /*input_batch_dimension=*/0,
-        /*input_feature_dimension=*/newSpatialDimensions.size() + 1,
-        /*input_spatial_dimensions=*/newSpatialDimensions,
-        dimensionNumbers.getKernelInputFeatureDimension(),
-        dimensionNumbers.getKernelOutputFeatureDimension(),
-        dimensionNumbers.getKernelSpatialDimensions(),
-        dimensionNumbers.getOutputBatchDimension(),
-        dimensionNumbers.getOutputFeatureDimension(),
-        dimensionNumbers.getOutputSpatialDimensions());
-
-    SmallVector<Value, 2> operands = {transposed, op.getRhs()};
-    auto newConv = rewriter.create<mhlo::ConvolutionOp>(
-        op.getLoc(), op.getType(), operands, op->getAttrs());
-    newConv.setDimensionNumbersAttr(newDimensionNumbers);
-    rewriter.replaceOp(op, newConv.getResult());
-
-    return success();
-  }
-};
-
-struct ReorderConvOpKernelDimensions
-    : public OpRewritePattern<mhlo::ConvolutionOp> {
-  using OpRewritePattern::OpRewritePattern;
-  LogicalResult matchAndRewrite(mhlo::ConvolutionOp op,
-                                PatternRewriter &rewriter) const override {
-    auto kernel = op.getRhs();
-    auto kernelType = llvm::cast<ShapedType>(kernel.getType());
-    if (!kernelType.hasRank()) return failure();
-    auto kernelShape = kernelType.getShape();
-
-    auto dimensionNumbers = op.getDimensionNumbers();
-
-    auto spatialDims = dimensionNumbers.getKernelSpatialDimensions();
-
-    auto inputFeatureDimension =
-        dimensionNumbers.getKernelInputFeatureDimension();
-    auto outputFeatureDimension =
-        dimensionNumbers.getKernelOutputFeatureDimension();
-
-    // Compute the permutation for the transpose.
-    llvm::SmallVector<int64_t, 4> permutation(spatialDims.begin(),
-                                              spatialDims.end());
-    permutation.push_back(inputFeatureDimension);
-    permutation.push_back(outputFeatureDimension);
-
-    // If the permutation is iota, then no transpose is required.
-    if (isIota(permutation)) return failure();
-
-    llvm::SmallVector<int64_t, 4> transposeShape;
-    for (auto perm : permutation) {
-      transposeShape.push_back(kernelShape[perm]);
-    }
-
-    llvm::SmallVector<int64_t, 4> newSpatialDimensions(spatialDims.size());
-    std::iota(newSpatialDimensions.begin(), newSpatialDimensions.end(), 0);
-
-    auto transposeKernel = rewriter.create<mhlo::TransposeOp>(
-        op.getLoc(),
-        RankedTensorType::get(transposeShape, kernelType.getElementType()),
-        kernel, rewriter.getI64TensorAttr(permutation));
-
-    auto newDimensionNumbers = mhlo::ConvDimensionNumbersAttr::get(
-        op.getContext(), dimensionNumbers.getInputBatchDimension(),
-        dimensionNumbers.getInputFeatureDimension(),
-        dimensionNumbers.getInputSpatialDimensions(),
-        /*kernel_input_feature_dimension=*/
-        newSpatialDimensions.size(),
-        /*kernel_output_feature_dimension=*/
-        newSpatialDimensions.size() + 1, newSpatialDimensions,
-        dimensionNumbers.getOutputBatchDimension(),
-        dimensionNumbers.getOutputFeatureDimension(),
-        dimensionNumbers.getOutputSpatialDimensions());
-
-    SmallVector<Value, 2> operands = {op.getLhs(), transposeKernel};
-    mhlo::ConvolutionOp newConv = rewriter.create<mhlo::ConvolutionOp>(
-        op.getLoc(), op.getType(), operands, op->getAttrs());
-    newConv.setDimensionNumbersAttr(newDimensionNumbers);
-
-    rewriter.replaceOp(op, {newConv.getResult()});
-    return success();
-  }
-};
-
-// Guarantee that the output dimensions are ordered batch, spatial_dims, feature
-// dim.
-class ReorderConvOpOutputDimensions
-    : public OpRewritePattern<mhlo::ConvolutionOp> {
- public:
-  using OpRewritePattern<mhlo::ConvolutionOp>::OpRewritePattern;
-  LogicalResult matchAndRewrite(mhlo::ConvolutionOp op,
-                                PatternRewriter &rewriter) const override {
-    auto resultType = llvm::cast<ShapedType>(op.getType());
-    auto resultShape = resultType.getShape();
-    if (!resultType.hasRank()) {
-      return failure();
-    }
-
-    auto dimensionNumbers = op.getDimensionNumbers();
-    auto spatialDims = dimensionNumbers.getOutputSpatialDimensions();
-
-    // Compute the permutation to transpose to an ordered output.
-    llvm::SmallVector<int64_t, 4> permutation;
-    permutation.push_back(dimensionNumbers.getOutputBatchDimension());
-    permutation.append(spatialDims.begin(), spatialDims.end());
-    permutation.push_back(dimensionNumbers.getOutputFeatureDimension());
-
-    // If the permutation is iota then no reordering is required.
-    if (isIota(permutation)) {
-      return failure();
-    }
-
-    // Compute what the new conv shape should be.
-    llvm::SmallVector<int64_t, 4> convShape;
-    for (auto p : permutation) {
-      convShape.push_back(resultShape[p]);
-    }
-
-    // Compute the inverse transpose to unordered and ordered output.
-    llvm::SmallVector<int64_t, 4> invertPermutation(permutation.size());
-    for (auto it : llvm::enumerate(permutation)) {
-      invertPermutation[it.value()] = it.index();
-    }
-
-    llvm::SmallVector<int64_t, 4> newSpatialDimensions(spatialDims.size());
-    std::iota(newSpatialDimensions.begin(), newSpatialDimensions.end(), 1);
-
-    auto newDimensionNumbers = mhlo::ConvDimensionNumbersAttr::get(
-        op.getContext(), dimensionNumbers.getInputBatchDimension(),
-        dimensionNumbers.getInputFeatureDimension(),
-        dimensionNumbers.getInputSpatialDimensions(),
-        dimensionNumbers.getKernelInputFeatureDimension(),
-        dimensionNumbers.getKernelOutputFeatureDimension(),
-        dimensionNumbers.getKernelSpatialDimensions(),
-        /*output_batch_dimension=*/0,
-        /*output_feature_dimension=*/newSpatialDimensions.size() + 1,
-        /*output_spatial_dimensions=*/newSpatialDimensions);
-
-    SmallVector<Value, 2> operands = {op.getLhs(), op.getRhs()};
-    auto newConv = rewriter.create<mhlo::ConvolutionOp>(
-        op.getLoc(),
-        RankedTensorType::get(convShape, resultType.getElementType()), operands,
-        op->getAttrs());
-    newConv.setDimensionNumbersAttr(newDimensionNumbers);
-
-    auto transposed = rewriter.create<mhlo::TransposeOp>(
-        op.getLoc(), resultType, newConv,
-        rewriter.getI64TensorAttr(invertPermutation));
-
-    rewriter.replaceOp(op, transposed.getResult());
-    return success();
-  }
-};
-
-bool isConsecutive(ArrayRef<int64_t> array) {
-  for (int i = 1; i < array.size(); ++i) {
-    if (array[i] - array[i - 1] != 1) return false;
-  }
-  return true;
-}
-
-// Rewrites mhlo.dot_general so lhs contraction dimensions are innermost and rhs
-// contraction dimensions are dims right after batch dimension. The pattern
-// inserts transposes so the dot_general always has the form:
-// {batch_dims, parallel_dims, contraction_dims}.
-//   {batch_dims, contraction_dims, parallel_dims}
-// After that, batch_dims, contraction_dims, parallel_dims are
-// in consecutive order and not spliting the domain. This pattern inserts
-// reshapes to collapse consecutive reduction and parallel dims to always
-// generate a rank-3 dot_general op.
-class TransposeReshapeGenericDotGeneral
-    : public OpRewritePattern<mhlo::DotGeneralOp> {
- public:
-  using OpRewritePattern<mhlo::DotGeneralOp>::OpRewritePattern;
-
-  Value TransposeIfNonConsecutive(OpBuilder &b, Location loc, Value src,
-                                  ArrayRef<int64_t> targetOrder) const {
-    if (isConsecutive(targetOrder)) return src;
-    auto type = llvm::cast<RankedTensorType>(src.getType());
-    SmallVector<int64_t, 4> transposeShape;
-    for (auto i : targetOrder) {
-      transposeShape.push_back(type.getDimSize(i));
-    }
-    return b.create<mhlo::TransposeOp>(
-        loc, RankedTensorType::get(transposeShape, type.getElementType()), src,
-        b.getI64TensorAttr(targetOrder));
-  }
-
-  Value ReshapeIfNonStandard(OpBuilder &b, Location loc, Value src,
-                             size_t dimsBorder0, size_t dimsBorder1) const {
-    auto type = llvm::cast<RankedTensorType>(src.getType());
-    auto shape = type.getShape();
-    if (dimsBorder0 <= 1 && dimsBorder1 - dimsBorder0 <= 1 &&
-        shape.size() - dimsBorder1 <= 1)
-      return src;
-    SmallVector<int64_t, 4> result_shape = {
-        std::accumulate(shape.begin(), shape.begin() + dimsBorder0, 1,
-                        std::multiplies<int64_t>()),
-        std::accumulate(shape.begin() + dimsBorder0,
-                        shape.begin() + dimsBorder1, 1,
-                        std::multiplies<int64_t>()),
-        std::accumulate(shape.begin() + dimsBorder1, shape.end(), 1,
-                        std::multiplies<int64_t>())};
-    return b.create<mhlo::ReshapeOp>(
-        loc, RankedTensorType::get(result_shape, type.getElementType()), src);
-  }
-
-  LogicalResult matchAndRewrite(mhlo::DotGeneralOp op,
-                                PatternRewriter &rewriter) const override {
-    auto lhsShapeType = llvm::dyn_cast<RankedTensorType>(op.getLhs().getType());
-    auto rhsShapeType = llvm::dyn_cast<RankedTensorType>(op.getRhs().getType());
-    auto resultType =
-        llvm::dyn_cast<RankedTensorType>(op.getResult().getType());
-    if (!lhsShapeType || !rhsShapeType || !resultType) return failure();
-
-    // TODO(jpienaar): This pattern is not safe for dynamic shapes and seems to
-    // be (now) redundant with later pass that does handle them. To decouple
-    // fixing and verifying redundant, this just limits to static shapes and
-    // then will remove this in follow up.
-    if (!lhsShapeType.hasStaticShape() || !rhsShapeType.hasStaticShape())
-      return failure();
-
-    SmallVector<int64_t> lhsTargetOrder, rhsTargetOrder;
-    mhlo::DotDimensionNumbersAttr dimNumbers = op.getDotDimensionNumbers();
-    auto lhsBatchingDims = dimNumbers.getLhsBatchingDimensions();
-    auto lhsContractingDims = dimNumbers.getLhsContractingDimensions();
-    auto rhsBatchingDims = dimNumbers.getRhsBatchingDimensions();
-    auto rhsContractingDims = dimNumbers.getRhsContractingDimensions();
-
-    // No contraction dims means this can be represented as a mul.
-    if (lhsContractingDims.size() == 0 || rhsContractingDims.size() == 0)
-      return rewriter.notifyMatchFailure(op, "can be represented as mhlo.mul");
-
-    // No batching dimensions means this can be represented a dot.
-    if (lhsBatchingDims.size() == 0 || rhsBatchingDims.size() == 0)
-      return rewriter.notifyMatchFailure(op, "can be represented as mhlo.dot");
-
-    SmallVector<bool> isLhsParallel(lhsShapeType.getRank(), true);
-    for (auto i : lhsBatchingDims) {
-      lhsTargetOrder.push_back(i);
-      isLhsParallel[i] = false;
-    }
-    for (auto i : lhsContractingDims) {
-      isLhsParallel[i] = false;
-    }
-    for (int64_t i = 0, e = lhsShapeType.getRank(); i < e; ++i) {
-      if (isLhsParallel[i]) {
-        lhsTargetOrder.push_back(i);
-      }
-    }
-    for (auto i : lhsContractingDims) {
-      lhsTargetOrder.push_back(i);
-    }
-
-    SmallVector<bool> isRhsParallel(rhsShapeType.getRank(), true);
-
-    for (auto i : rhsBatchingDims) {
-      rhsTargetOrder.push_back(i);
-      isRhsParallel[i] = false;
-    }
-    for (auto i : rhsContractingDims) {
-      rhsTargetOrder.push_back(i);
-      isRhsParallel[i] = false;
-    }
-    for (int64_t i = 0, e = rhsShapeType.getRank(); i < e; ++i) {
-      if (isRhsParallel[i]) {
-        rhsTargetOrder.push_back(i);
-      }
-    }
-
-    Value lhs = TransposeIfNonConsecutive(rewriter, op.getLoc(), op.getLhs(),
-                                          lhsTargetOrder);
-    Value rhs = TransposeIfNonConsecutive(rewriter, op.getLoc(), op.getRhs(),
-                                          rhsTargetOrder);
-
-    // The dimensions of this will always be transposed into {batch_dims,
-    // parallel_dims, contraction_dims}, and the
-    // following logic is based on this assumption.
-    // TODO(#7443): If we consider transpose performance, the above assumptions
-    // may not be true.
-    int64_t numLhsContractionDims = lhsContractingDims.size();
-    int64_t lhsContractionBase = lhsShapeType.getRank() - numLhsContractionDims;
-    int64_t rhsContractionBase = rhsBatchingDims.size();
-    int64_t numRhsContractionDims =
-        rhsContractionBase + rhsContractingDims.size();
-
-    lhs = ReshapeIfNonStandard(rewriter, op.getLoc(), lhs,
-                               lhsBatchingDims.size(), lhsContractionBase);
-    rhs = ReshapeIfNonStandard(rewriter, op.getLoc(), rhs,
-                               rhsBatchingDims.size(), numRhsContractionDims);
-
-    if (lhs == op.getLhs() && rhs == op.getRhs())
-      return rewriter.notifyMatchFailure(op, "already in canonical form");
-
-    auto dimensionNumbers = mhlo::DotDimensionNumbersAttr::get(
-        rewriter.getContext(), /*lhsBatchingDimensions=*/0,
-        /*rhsBatchingDimensions=*/0,
-        /*lhsContractingDimensions=*/
-        llvm::cast<ShapedType>(lhs.getType()).getRank() - 1,
-        /*rhsContractingDimensions=*/1);
-    auto lhsNewType = llvm::cast<RankedTensorType>(lhs.getType());
-    auto rhsNewType = llvm::cast<RankedTensorType>(rhs.getType());
-
-    // if lhs's shape or rhs's shape has collapsed, we need reshape the result
-    bool needReshapeResult = lhsNewType.getRank() < lhsShapeType.getRank() ||
-                             rhsNewType.getRank() < rhsShapeType.getRank();
-    // batching、lhs parallel、rhs parallel this order is a convension
-    SmallVector<int64_t, 4> newShape = {lhsNewType.getShape()[0],
-                                        lhsNewType.getShape()[1]};
-    if (rhsNewType.getRank() > 2) newShape.push_back(rhsNewType.getDimSize(2));
-
-    auto newResultType =
-        needReshapeResult
-            ? RankedTensorType::get(newShape, resultType.getElementType())
-            : op.getType();
-
-    auto newOp = rewriter.create<mhlo::DotGeneralOp>(
-        op.getLoc(), newResultType, lhs, rhs, dimensionNumbers,
-        op.getPrecisionConfigAttr());
-
-    // Copy over unknown attributes as we currently rely on it to let user tune
-    // lowering parameters.
-    ArrayRef<StringRef> odsAttrs = op.getAttributeNames();
-    for (NamedAttribute kv : op->getAttrs()) {
-      if (!llvm::is_contained(odsAttrs, kv.getName().getValue())) {
-        newOp->setAttr(kv.getName(), kv.getValue());
-      }
-    }
-
-    Value result = newOp.getResult();
-    if (needReshapeResult) {
-      result =
-          rewriter.create<mhlo::ReshapeOp>(op.getLoc(), resultType, result);
-    }
-    rewriter.replaceOp(op, result);
-    return success();
-  }
-};
-
-struct ScatterInt64Indices : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    auto indices = op.getScatterIndices();
-    auto indicesTy = indices.getType();
-    auto indicesETy = indicesTy.getElementType();
-    if (indicesETy.isInteger(32))
-      return rewriter.notifyMatchFailure(op, "already has i32 index type");
-
-    if (!indicesTy.hasStaticShape())
-      return rewriter.notifyMatchFailure(op, "cannot validate legal size");
-
-    uint64_t maxSize = std::numeric_limits<int32_t>::max();
-    if (indicesETy.getIntOrFloatBitWidth() > 32) {
-      for (int i = 0, s = indicesTy.getRank(); i < s; ++i) {
-        if (indicesTy.getDimSize(i) > maxSize) {
-          return rewriter.notifyMatchFailure(op, "index may exceed i32 max");
-        }
-      }
-    }
-
-    indices = rewriter.create<mhlo::ConvertOp>(
-        op.getLoc(), indicesTy.clone(rewriter.getI32Type()), indices);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(), indices,
-        op.getUpdates(), op.getScatterDimensionNumbers(),
-        op.getIndicesAreSorted(), op.getUniqueIndices());
-
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-
-    return success();
-  }
-};
-
-// If the indices tensor has an implicit index vector dim we expand and make it
-// an explicit dim.
-struct ScatterImplicitIndex : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    auto dimNumbers = op.getScatterDimensionNumbers();
-    auto indexVectorDim = dimNumbers.getIndexVectorDim();
-    Value indices = op.getScatterIndices();
-    auto indicesTy = llvm::cast<ShapedType>(indices.getType());
-
-    // Check indices vector has an implicit dim.
-    if (indexVectorDim != indicesTy.getRank()) {
-      return rewriter.notifyMatchFailure(op, "no implicit index dim");
-    }
-
-    // Materialize the implicit indices dim.
-    SmallVector<ReassociationExprs, 4> reassociationMap;
-    reassociationMap.resize(indicesTy.getRank());
-    SmallVector<int64_t> newShape;
-    for (int i = 0, s = indicesTy.getRank(); i < s; i++) {
-      reassociationMap[i].push_back(rewriter.getAffineDimExpr(i));
-      newShape.push_back(indicesTy.getDimSize(i));
-    }
-    if (!reassociationMap.empty()) {
-      reassociationMap.back().push_back(
-          rewriter.getAffineDimExpr(indicesTy.getRank()));
-    }
-    newShape.push_back(1);
-    indicesTy = RankedTensorType::get(newShape, indicesTy.getElementType());
-    indices = rewriter.create<tensor::ExpandShapeOp>(op.getLoc(), indicesTy,
-                                                     indices, reassociationMap);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(), indices,
-        op.getUpdates(), dimNumbers, op.getIndicesAreSorted(),
-        op.getUniqueIndices());
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-    return success();
-  }
-};
-
-struct ScatterImplicitBatch : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  static Value addUnitBatchDim(Location loc, Value value,
-                               PatternRewriter &rewriter) {
-    ShapedType valueTy = llvm::cast<ShapedType>(value.getType());
-    if (!valueTy.hasRank()) return nullptr;
-
-    // Materialize the implicit indices dim.
-    SmallVector<ReassociationExprs, 4> reassociationMap(valueTy.getRank());
-    if (!reassociationMap.empty()) {
-      reassociationMap.front().push_back(rewriter.getAffineDimExpr(0));
-    }
-
-    SmallVector<int64_t> newShape = {1};
-    for (int i = 0, s = valueTy.getRank(); i < s; i++) {
-      reassociationMap[i].push_back(rewriter.getAffineDimExpr(i + 1));
-      newShape.push_back(valueTy.getDimSize(i));
-    }
-
-    valueTy = RankedTensorType::get(newShape, valueTy.getElementType());
-    return rewriter.create<tensor::ExpandShapeOp>(loc, valueTy, value,
-                                                  reassociationMap);
-  }
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    auto dimNumbers = op.getScatterDimensionNumbers();
-    auto indexVectorDim = dimNumbers.getIndexVectorDim();
-    auto indices = llvm::cast<Value>(op.getScatterIndices());
-    auto indicesTy = llvm::dyn_cast<RankedTensorType>(indices.getType());
-
-    // Check whether indices has no batch dimension.
-    if (!indicesTy) return failure();
-    if (indicesTy.getRank() != 1 || indexVectorDim != 0) {
-      return rewriter.notifyMatchFailure(op,
-                                         "no implicit batch dimension to add.");
-    }
-
-    indices = addUnitBatchDim(op.getLoc(), indices, rewriter);
-    if (!indices) {
-      return rewriter.notifyMatchFailure(
-          op, "Unable to add implicit batch dim to indice.");
-    }
-
-    llvm::SmallVector<int64_t> newUpdateWindowDims;
-    for (auto dim : dimNumbers.getUpdateWindowDims()) {
-      // Batch dimension is inserted at the start so window dimensions are shift
-      // forwards.
-      newUpdateWindowDims.push_back(dim + 1);
-    }
-
-    llvm::SmallVector<Value> updates;
-    for (Value update : op.getUpdates()) {
-      update = addUnitBatchDim(op.getLoc(), update, rewriter);
-      if (!update) {
-        return rewriter.notifyMatchFailure(
-            op, "Unable to add implicit batch dim to update.");
-      }
-      updates.push_back(update);
-    }
-
-    auto newDimNumbers = mhlo::ScatterDimensionNumbersAttr::get(
-        op.getContext(), newUpdateWindowDims,
-        dimNumbers.getInsertedWindowDims(),
-        dimNumbers.getScatterDimsToOperandDims(),
-        dimNumbers.getIndexVectorDim() + 1);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(), indices, updates,
-        newDimNumbers, op.getIndicesAreSorted(), op.getUniqueIndices());
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-    return success();
-  }
-};
-
-struct ScatterCollapseBatch : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  static Value collapseBatchDims(Location loc, Value value, int64_t batchCount,
-                                 PatternRewriter &rewriter) {
-    auto valueTy = llvm::dyn_cast<ShapedType>(value.getType());
-    if (!valueTy) return nullptr;
-
-    SmallVector<ReassociationExprs, 4> reassociationMap(1);
-    reassociationMap.reserve(valueTy.getRank() - batchCount + 1);
-    int64_t batchSize = 1;
-    for (int i = 0, s = batchCount; i < s; i++) {
-      reassociationMap.front().push_back(rewriter.getAffineDimExpr(i));
-      bool isDynamic =
-          valueTy.isDynamicDim(i) || batchSize == ShapedType::kDynamic;
-      batchSize =
-          isDynamic ? ShapedType::kDynamic : valueTy.getDimSize(i) * batchSize;
-    }
-
-    SmallVector<int64_t> newShape = {batchSize};
-    for (int i = batchCount, s = valueTy.getRank(); i < s; i++) {
-      reassociationMap.push_back({rewriter.getAffineDimExpr(i)});
-      newShape.push_back(valueTy.getDimSize(i));
-    }
-
-    valueTy = RankedTensorType::get(newShape, valueTy.getElementType());
-    return rewriter.create<tensor::CollapseShapeOp>(loc, valueTy, value,
-                                                    reassociationMap);
-  }
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    auto dimNumbers = op.getScatterDimensionNumbers();
-    auto indexVectorDim = dimNumbers.getIndexVectorDim();
-    auto indices = llvm::cast<Value>(op.getScatterIndices());
-    auto indicesTy = llvm::cast<ShapedType>(indices.getType());
-    auto updatedWindowDims = dimNumbers.getUpdateWindowDims();
-
-    if (!indicesTy.hasRank()) {
-      return rewriter.notifyMatchFailure(op, "indices has unknown rank");
-    }
-
-    // Check for an explicit indice dimension.
-    if (indexVectorDim != indicesTy.getRank() - 1) {
-      return rewriter.notifyMatchFailure(op, "no explicit indices dimension");
-    }
-
-    // Check that there are multiple batch dimensions.
-    if (indicesTy.getRank() < 3) {
-      return rewriter.notifyMatchFailure(op, "no multiple batch dimensions");
-    }
-
-    const int64_t batchCount = indicesTy.getRank() - 1;
-    for (auto it : llvm::enumerate(updatedWindowDims)) {
-      if (it.index() != it.value() - batchCount) {
-        return rewriter.notifyMatchFailure(
-            op, "update windows should be at the end.");
-      }
-    }
-
-    indices = collapseBatchDims(op.getLoc(), indices, batchCount, rewriter);
-    if (!indices) {
-      return rewriter.notifyMatchFailure(op,
-                                         "cannot collapse indices batch dims");
-    }
-
-    llvm::SmallVector<Value> updates;
-    for (Value update : op.getUpdates()) {
-      update = collapseBatchDims(op.getLoc(), update, batchCount, rewriter);
-      if (!update) {
-        return rewriter.notifyMatchFailure(op,
-                                           "cannot collapse update batch dims");
-      }
-      updates.push_back(update);
-    }
-
-    llvm::SmallVector<int64_t> newUpdatedWindowDims;
-    for (auto dim : updatedWindowDims) {
-      newUpdatedWindowDims.push_back(dim - batchCount + 1);
-    }
-
-    auto newDimNumbers = mhlo::ScatterDimensionNumbersAttr::get(
-        op.getContext(), newUpdatedWindowDims,
-        dimNumbers.getInsertedWindowDims(),
-        dimNumbers.getScatterDimsToOperandDims(),
-        /*indexVectorDim=*/1);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(), indices, updates,
-        newDimNumbers, op.getIndicesAreSorted(), op.getUniqueIndices());
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-    return success();
-  }
-};
-
-// Ensure the batch dimensions of both the indices and updates are the first
-// dimensions. If they are not, transpose them to the start.
-struct ScatterBatchFirst : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    ImplicitLocOpBuilder builder(op.getLoc(), rewriter);
-    auto dimNumbers = op.getScatterDimensionNumbers();
-
-    // If the index vector dim is not implicitly or explicitly at the end
-    // we need to transpose the batch dimensions to the start.
-    Value indices = op.getScatterIndices();
-    auto indicesTy = llvm::cast<ShapedType>(indices.getType());
-    auto indexVectorDim = dimNumbers.getIndexVectorDim();
-    if (indexVectorDim < indicesTy.getRank() - 1) {
-      llvm::SmallVector<int64_t> perm;
-      perm.reserve(indicesTy.getRank());
-      for (int i = 0, s = indicesTy.getRank(); i < s; ++i)
-        if (i != indexVectorDim) perm.push_back(i);
-
-      if (perm.size() < indicesTy.getRank()) perm.push_back(indexVectorDim);
-
-      llvm::SmallVector<int64_t> newShape;
-      for (int i = 0, s = perm.size(); i < s; ++i)
-        newShape.push_back(indicesTy.getDimSize(perm[i]));
-
-      indices = builder.create<mhlo::TransposeOp>(
-          indicesTy.clone(newShape), indices, builder.getI64TensorAttr(perm));
-      indicesTy = llvm::cast<RankedTensorType>(indices.getType());
-      indexVectorDim = indicesTy.getRank() - 1;
-    }
-
-    // Compute the permutation require to transpose the batch dimensions to
-    // the beginning.
-    auto updates = op.getUpdates();
-    auto updates0 = updates.front();
-    auto updates0Ty = llvm::cast<ShapedType>(updates0.getType());
-    auto updatedWindowDims = dimNumbers.getUpdateWindowDims();
-
-    // Determine which dimensions are batch dimensions.
-    llvm::SmallVector<bool> isBatch(updates0Ty.getRank(), true);
-    for (int i = 0, s = updatedWindowDims.size(); i < s; ++i)
-      isBatch[updatedWindowDims[i]] = false;
-
-    // Permute batch dimensions to the start of the update tensor.
-    llvm::SmallVector<int64_t> updatePerm;
-    updatePerm.reserve(updates0Ty.getRank());
-    for (int i = 0, s = isBatch.size(); i < s; ++i)
-      if (isBatch[i]) updatePerm.push_back(i);
-    updatePerm.append(updatedWindowDims.begin(), updatedWindowDims.end());
-
-    llvm::SmallVector<int64_t> newUpdatedWindowDims;
-    int64_t batchCount = updates0Ty.getRank() - updatedWindowDims.size();
-    for (int i = batchCount, s = updates0Ty.getRank(); i < s; i++)
-      newUpdatedWindowDims.push_back(i);
-
-    bool indicesChanged = indices != op.getScatterIndices();
-    bool updatesChanged =
-        llvm::any_of(llvm::enumerate(updatePerm),
-                     [](auto it) { return it.index() != it.value(); });
-    llvm::SmallVector<Value> newUpdates(updates.begin(), updates.end());
-    if (updatesChanged) {
-      for (Value &update : newUpdates) {
-        auto updateTy = llvm::cast<ShapedType>(update.getType());
-        llvm::SmallVector<int64_t> newShape;
-        newShape.reserve(updateTy.getRank());
-        for (int i = 0, s = updatePerm.size(); i < s; i++)
-          newShape.push_back(updateTy.getDimSize(updatePerm[i]));
-        update = builder.create<mhlo::TransposeOp>(
-            updateTy.clone(newShape), update,
-            builder.getI64TensorAttr(updatePerm));
-      }
-    }
-
-    if (!indicesChanged && !updatesChanged)
-      return rewriter.notifyMatchFailure(
-          op, "batch dimensions are already leading");
-
-    auto newDimNumbers = mhlo::ScatterDimensionNumbersAttr::get(
-        op.getContext(), newUpdatedWindowDims,
-        dimNumbers.getInsertedWindowDims(),
-        dimNumbers.getScatterDimsToOperandDims(),
-        /*indexVectorDim=*/indexVectorDim);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(), indices, newUpdates,
-        newDimNumbers, op.getIndicesAreSorted(), op.getUniqueIndices());
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-    return success();
-  }
-};
-
-// mhlo.scatter can materialize a unit dimension at both indexed dimensions or
-// at unary dimensions in the destination matrix. linalg_ext.scatter only
-// allows unit dimensions at indexed dimensions. This pattern inserts all
-// unary dimensions that are not index dimensions to be compatible with
-// linalg_ext.scatter.
-//
-// If converts an mhlo.scatter as below:
-//  %result = "mhlo.scatter"(...) ({
-//    indices_are_sorted = true,
-//    scatter_dimension_numbers = #mhlo.scatter<
-//            update_window_dims = [1],
-//            inserted_window_dims = [0, 2],
-//            scatter_dims_to_operand_dims = [0],
-//            index_vector_dim = 1>,
-//    unique_indices = true} :
-//        (tensor<5x4x1xi32>, tensor<1x1xi32>, tensor<1x4xi32>)
-//
-// To:
-//  %result = "mhlo.scatter"(...) ({
-//    indices_are_sorted = true,
-//    scatter_dimension_numbers = #mhlo.scatter<
-//            update_window_dims = [1, 2],
-//            inserted_window_dims = [0],
-//            scatter_dims_to_operand_dims = [0],
-//            index_vector_dim = 1>,
-//     unique_indices = true} :
-//        (tensor<5x4x1xi32>, tensor<1x1xi32>, tensor<1x4x1xi32>)
-//  return %0 : tensor<5x4x1xi32>
-struct ScatterMaterializeInsertedDim
-    : public OpRewritePattern<mhlo::ScatterOp> {
-  using OpRewritePattern<mhlo::ScatterOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::ScatterOp op,
-                                PatternRewriter &rewriter) const final {
-    auto indices = op.getScatterIndices();
-    auto operand = op.getInputs().front();
-    auto indicesTy = llvm::cast<ShapedType>(indices.getType());
-    auto operandTy = llvm::cast<ShapedType>(operand.getType());
-
-    if (!operandTy.hasRank() || !indicesTy.hasRank()) {
-      return rewriter.notifyMatchFailure(op, "operand/indices have no rank");
-    }
-
-    auto dimNumbers = op.getScatterDimensionNumbers();
-    auto updateDims = dimNumbers.getUpdateWindowDims();
-
-    if (indicesTy.getRank() != 2 || dimNumbers.getIndexVectorDim() != 1) {
-      return rewriter.notifyMatchFailure(
-          op, "indices is not of shape [batch, indices]");
-    }
-
-    if (!updateDims.empty() && updateDims.front() == 0) {
-      return rewriter.notifyMatchFailure(
-          op, "updates is not of shape [batch, ...]");
-    }
-
-    auto scatterDimsToOperandDims = dimNumbers.getScatterDimsToOperandDims();
-    llvm::SmallVector<bool> isIndexDim(operandTy.getRank(), false);
-    for (auto val : scatterDimsToOperandDims) {
-      isIndexDim[val] = true;
-    }
-
-    int64_t firstNonIndex = 0;
-    for (int64_t s = scatterDimsToOperandDims.size(); firstNonIndex < s;
-         ++firstNonIndex) {
-      if (!isIndexDim[firstNonIndex]) break;
-    }
-
-    llvm::SmallVector<bool> isInsertDims(operandTy.getRank(), false);
-    for (auto val : dimNumbers.getInsertedWindowDims()) {
-      isInsertDims[val] = true;
-    }
-
-    int64_t frontInsertedDims = 0;
-    for (; frontInsertedDims < firstNonIndex; ++frontInsertedDims) {
-      if (!isInsertDims[frontInsertedDims]) {
-        break;
-      }
-    }
-
-    llvm::ArrayRef<bool> toInsertDims =
-        llvm::ArrayRef<bool>(isInsertDims).drop_front(frontInsertedDims);
-    if (!llvm::any_of(toInsertDims, [](auto d) { return d; })) {
-      return rewriter.notifyMatchFailure(op, "no dimensions to insert");
-    }
-
-    // Create a reassociation map that starts with the batch dims.
-    SmallVector<ReassociationExprs, 4> reassociationMap;
-    reassociationMap.push_back({rewriter.getAffineDimExpr(0)});
-
-    for (auto it : llvm::enumerate(llvm::ArrayRef<bool>(toInsertDims))) {
-      if (!it.value()) reassociationMap.push_back({});
-      reassociationMap.back().push_back(
-          rewriter.getAffineDimExpr(it.index() + 1));
-    }
-
-    llvm::SmallVector<Value> expandedUpdates;
-    for (auto update : op.getUpdates()) {
-      auto updatesTy = llvm::cast<ShapedType>(update.getType());
-
-      llvm::SmallVector<int64_t> newShape;
-      for (int i = 0, s = reassociationMap.size(); i < s; ++i) {
-        newShape.push_back(updatesTy.getDimSize(i));
-        for (int j = 1, s = reassociationMap[i].size(); j < s; ++j) {
-          newShape.push_back(1);
-        }
-      }
-
-      Value expandUpdate = rewriter.create<tensor::ExpandShapeOp>(
-          op.getLoc(),
-          RankedTensorType::get(newShape, updatesTy.getElementType()), update,
-          reassociationMap);
-      expandedUpdates.push_back(expandUpdate);
-    }
-
-    llvm::SmallVector<int64_t> newUpdatedWindowDims(toInsertDims.size());
-    llvm::SmallVector<int64_t> newInsertedWindowDims(frontInsertedDims);
-    std::iota(newUpdatedWindowDims.begin(), newUpdatedWindowDims.end(), 1);
-    std::iota(newInsertedWindowDims.begin(), newInsertedWindowDims.end(), 0);
-
-    auto newDimNumbers = mhlo::ScatterDimensionNumbersAttr::get(
-        op.getContext(), newUpdatedWindowDims, newInsertedWindowDims,
-        dimNumbers.getScatterDimsToOperandDims(),
-        /*indexVectorDim=*/1);
-
-    auto newScatter = rewriter.create<mhlo::ScatterOp>(
-        op.getLoc(), op.getResultTypes(), op.getInputs(),
-        op.getScatterIndices(), expandedUpdates, newDimNumbers,
-        op.getIndicesAreSorted(), op.getUniqueIndices());
-    Region &region = newScatter.getUpdateComputation();
-    rewriter.cloneRegionBefore(op.getUpdateComputation(), region, region.end());
-    rewriter.replaceOp(op, newScatter.getResults());
-    return success();
-  }
-};
-
-// Traverse upward past common operations to see if the value came from a
-// boolean tensor.
-bool isFromBool(Value val) {
-  while (true) {
-    Operation *op = val.getDefiningOp();
-    if (!op) return false;
-
-    if (auto convertOp = dyn_cast<mhlo::ConvertOp>(op)) {
-      auto inTy = llvm::cast<ShapedType>(convertOp.getOperand().getType());
-      if (inTy.getElementType().isInteger(1)) {
-        return true;
-      }
-      val = convertOp.getOperand();
-      continue;
-    }
-
-    if (isa<mhlo::DynamicBroadcastInDimOp>(op) ||
-        isa<mhlo::BroadcastInDimOp>(op) || isa<mhlo::BroadcastOp>(op)) {
-      val = op->getOperand(0);
-      continue;
-    }
-
-    return false;
-  }
-}
-
-// Mhlo of non-finite values (e.g. NaN, inf) and 0.0 produce 0.0 for XLA. For
-// linalg we need to conver these to select operations.
-class MulCastOfBool : public OpRewritePattern<mhlo::MulOp> {
- public:
-  using OpRewritePattern<mhlo::MulOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::MulOp op,
-                                PatternRewriter &rewriter) const override {
-    auto resultTy = llvm::cast<ShapedType>(op.getType());
-    if (!llvm::isa<FloatType>(resultTy.getElementType())) return failure();
-    Value lhs = op.getLhs();
-    Value rhs = op.getRhs();
-    bool lhsIsBool = isFromBool(lhs);
-    bool rhsIsBool = isFromBool(rhs);
-
-    if (lhsIsBool == rhsIsBool) return failure();
-    if (rhsIsBool) std::swap(lhs, rhs);
-
-    Type eType = resultTy.getElementType();
-    auto lhsTy = llvm::cast<ShapedType>(lhs.getType());
-    Value lhsBool = rewriter.create<mhlo::ConvertOp>(
-        op.getLoc(), lhsTy.clone(rewriter.getIntegerType(1)), lhs);
-    Value zero = rewriter.create<mhlo::ConstantOp>(
-        op.getLoc(), DenseElementsAttr::get(RankedTensorType::get({}, eType),
-                                            rewriter.getZeroAttr(eType)));
-
-    auto lhsShape = rewriter.create<shape::ShapeOfOp>(
-        op.getLoc(),
-        RankedTensorType::get({lhsTy.getRank()}, rewriter.getIndexType()), lhs);
-
-    int64_t resultRank = resultTy.getRank();
-    auto broadcast = [&](Value value) -> Value {
-      auto valueTy = llvm::cast<ShapedType>(value.getType());
-      auto newTy =
-          RankedTensorType::get(resultTy.getShape(), valueTy.getElementType());
-      if (valueTy == newTy) return value;
-      auto dimensions = llvm::to_vector<4>(
-          llvm::seq<int64_t>(resultRank - valueTy.getRank(), resultRank));
-      return rewriter.create<mhlo::DynamicBroadcastInDimOp>(
-          op.getLoc(), newTy, value, lhsShape,
-          rewriter.getI64TensorAttr(dimensions));
-    };
-
-    zero = broadcast(zero);
-
-    rewriter.replaceOpWithNewOp<mhlo::SelectOp>(op, resultTy, lhsBool, rhs,
-                                                zero);
-    return success();
-  }
-};
-
-// Generates Gaussian noise with uniform random generator based on Box-Muller
-// transform.
-class ExpandRngNormal : public OpRewritePattern<mhlo::RngOp> {
- public:
-  using OpRewritePattern<mhlo::RngOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::RngOp op,
-                                PatternRewriter &rewriter) const override {
-    if (op.getRngDistribution() != mhlo::RngDistribution::NORMAL)
-      return failure();
-
-    auto resTy = llvm::dyn_cast<RankedTensorType>(op.getType());
-    // We can support static shapes, but it's easier to implement Box-Muller
-    // transform if we know the number of elements.
-    if (!resTy || !resTy.hasStaticShape()) return failure();
-
-    // The algorithm requires even numbers and will generate pairs.
-    auto numElems = resTy.getNumElements();
-    if (numElems & 1) numElems++;
-    auto halfNumElems = numElems / 2;
-
-    ImplicitLocOpBuilder b(op.getLoc(), rewriter);
-
-    // Explicitly set the seed to 0, so we have stateless generator. This is not
-    // a hard limit. Random generator is still a new topic, and we start with
-    // stateless random generator.
-    std::mt19937 rng{0};
-    std::uniform_real_distribution<> runif(0.0, 1.0);
-    SmallVector<float> sqrtValues(halfNumElems), cosValues(halfNumElems),
-        sinValues(halfNumElems);
-    for (auto i : llvm::seq<unsigned>(0, numElems / 2)) {
-      constexpr float kEpsilon = std::numeric_limits<float>::epsilon();
-      constexpr float kTwoPi = static_cast<float>(2.0 * M_PI);
-      float u1, u2;
-      do {
-        u1 = runif(rng);
-        u2 = runif(rng);
-      } while (u1 <= kEpsilon);
-      sqrtValues[i] = -2.0 * log(u1);
-      cosValues[i] = cos(kTwoPi * u2);
-      sinValues[i] = sin(kTwoPi * u2);
-    }
-
-    // mag = sigma * sqrt(-2.0 * log(u1));
-    Value mag = getF32Const(b, /*shapes=*/{halfNumElems}, sqrtValues);
-    Value sigma = b.create<mhlo::BroadcastOp>(
-        mag.getType(), op.getB(), make1DElementsAttr(b, halfNumElems));
-    mag = b.create<mhlo::MulOp>(sigma, b.create<mhlo::SqrtOp>(mag));
-
-    // z0 = mag * cos(two_pi * u2) + mu;
-    // z1 = mag * sin(two_pi * u2) + mu;
-    Value mu = b.create<mhlo::BroadcastOp>(mag.getType(), op.getA(),
-                                           make1DElementsAttr(b, halfNumElems));
-    Value z0 = getF32Const(b, /*shapes=*/{halfNumElems}, cosValues);
-    z0 = b.create<mhlo::MulOp>(mag, z0);
-    z0 = b.create<mhlo::AddOp>(z0, mu);
-    Value z1 = getF32Const(b, /*shapes=*/{halfNumElems}, sinValues);
-    z1 = b.create<mhlo::MulOp>(mag, z1);
-    z1 = b.create<mhlo::AddOp>(z1, mu);
-
-    Value res = b.create<mhlo::ConcatenateOp>(ValueRange{z0, z1},
-                                              b.getI64IntegerAttr(0));
-    if (numElems != resTy.getNumElements()) {
-      OpFoldResult zero = b.getIndexAttr(0);
-      OpFoldResult one = b.getIndexAttr(1);
-      OpFoldResult size = b.getIndexAttr(resTy.getNumElements());
-      res = b.create<tensor::ExtractSliceOp>(res, zero, size, one);
-    }
-    if (resTy.getRank() != 1) {
-      res = b.create<mhlo::ReshapeOp>(resTy, res);
-    }
-    rewriter.replaceOp(op, res);
-    return success();
-  }
-};
-
-// clang-format off
-//
-// Reorder BroadcastInDimOp and N-ary elementwise op.
-//
-// Rewrites the following pattern (take binary elementwise op as example)
-//
-// %bcastx = "mhlo.broadcast_in_dim"(%x) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
-// %bcasty = "mhlo.broadcast_in_dim"(%y) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
-// %result = "BinaryElementwiseOpT"(%bcastx, %bcasty) : (%[[SHAPE_AFTER_BCAST]], %[[SHAPE_AFTER_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
-//
-// into
-//
-// %z = "BinaryElementwiseOpT"(%x, %y) : (%[[SHAPE_BEFORE_BCAST]], %[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_BEFORE_BCAST]]
-// %result = "mhlo.broadcast_in_dim"(%z) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
-//
-// clang-format on
-template <typename ElementwiseOpT>
-class ReorderBroadcastInDimOpAndElementwiseOp
-    : public OpRewritePattern<ElementwiseOpT> {
- public:
-  using OpRewritePattern<ElementwiseOpT>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(ElementwiseOpT op,
-                                PatternRewriter &rewriter) const override {
-    Operation *operation = op.getOperation();
-    assert(operation->getNumOperands() >= 1 && operation->getNumResults() == 1);
-
-    // Verify if all operands are from BroadcastInDimOp and its
-    // broadcast_dimensions is the same.
-    llvm::SmallVector<mhlo::BroadcastInDimOp, 2> bcastOps;
-    for (auto operand : operation->getOperands()) {
-      if (auto bcastOp = operand.getDefiningOp<mhlo::BroadcastInDimOp>()) {
-        bcastOps.push_back(bcastOp);
-      } else {
-        return failure();
-      }
-    }
-
-    if (llvm::any_of(bcastOps, [&bcastOps](mhlo::BroadcastInDimOp bcastOp) {
-          return bcastOp.getBroadcastDimensions() !=
-                 bcastOps[0].getBroadcastDimensions();
-        })) {
-      return failure();
-    }
-
-    // Verify if all operands of BroadcastInDimOp are of same type and have
-    // static shape.
-    auto bcastOperandType =
-        llvm::dyn_cast<ShapedType>(bcastOps[0].getOperand().getType());
-    llvm::SmallVector<Value, 2> bcastOperands;
-    for (auto bcastOp : bcastOps) {
-      auto bcastOperand = bcastOp.getOperand();
-      auto type = llvm::dyn_cast<ShapedType>(bcastOperand.getType());
-      if (!type || !type.hasStaticShape() || type != bcastOperandType) {
-        return failure();
-      }
-      bcastOperands.push_back(bcastOperand);
-    }
-
-    // Some elementwise ops, mhlo::RealOp for example, do not have
-    // SameOperandsAndResultType trait, so resultType might be different
-    // from bcastOperandType.
-    auto elementType = getElementTypeOrSelf(op.getResult());
-    auto resultShape = bcastOperandType.getShape();
-    auto resultType = RankedTensorType::get(resultShape, elementType);
-
-    Value result =
-        rewriter.create<ElementwiseOpT>(op.getLoc(), resultType, bcastOperands);
-    rewriter.replaceOpWithNewOp<mhlo::BroadcastInDimOp>(
-        op, op.getType(), result, bcastOps[0].getBroadcastDimensions());
-
-    for (auto bcastOp : bcastOps) {
-      if (bcastOp.getOperation()->use_empty()) {
-        rewriter.eraseOp(bcastOp);
-      }
-    }
-
-    return success();
-  }
-};
-
-// Identifies cases where a dense operation has inputs that come from widening
-// operations. For instance, a dot product widening from FP16 to FP32 is better
-// to have the casting operation fused into the dot operation. This decreases
-// the loading required during a dense computation.
-template <class Op>
-struct FuseWidenOperands : public OpRewritePattern<Op> {
-  using OpRewritePattern<Op>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(Op op,
-                                PatternRewriter &rewriter) const override {
-    llvm::SmallVector<Value> operands;
-    for (Value operand : op->getOperands()) {
-      auto convertOp =
-          dyn_cast_or_null<mhlo::ConvertOp>(operand.getDefiningOp());
-      if (convertOp) {
-        auto inputType = getElementTypeOrSelf(convertOp.getOperand().getType());
-        auto castedType = getElementTypeOrSelf(convertOp.getResult().getType());
-        if (inputType.getIntOrFloatBitWidth() <
-            castedType.getIntOrFloatBitWidth()) {
-          operands.push_back(convertOp.getOperand());
-          continue;
-        }
-      }
-      operands.push_back(operand);
-    }
-
-    if (llvm::all_of(
-            llvm::zip_equal(operands, op->getOperands()),
-            [](auto pair) { return std::get<0>(pair) == std::get<1>(pair); }))
-      return failure();
-
-    rewriter.replaceOpWithNewOp<Op>(op, op->getResultTypes(), operands,
-                                    op->getAttrs());
-    return success();
-  }
-};
-
-struct DotToMul : public OpRewritePattern<mhlo::DotOp> {
-  using OpRewritePattern<mhlo::DotOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::DotOp op,
-                                PatternRewriter &rewriter) const override {
-    auto lhs = op.getLhs();
-    auto rhs = op.getRhs();
-    auto lhsTy = llvm::dyn_cast<RankedTensorType>(lhs.getType());
-    auto rhsTy = llvm::dyn_cast<RankedTensorType>(rhs.getType());
-    auto resultTy = llvm::cast<RankedTensorType>(op.getType());
-
-    if (!lhsTy || !rhsTy) {
-      return rewriter.notifyMatchFailure(op, "lhs and rhs must be ranked");
-    }
-
-    if (lhsTy.getRank() != 2 || rhsTy.getRank() != 2) {
-      return rewriter.notifyMatchFailure(op, "lhs and rhs must be rank-2");
-    }
-
-    if (lhsTy.getDimSize(1) != 1) return failure();
-
-    // Dynamically compute the shape of the result of the DotOp by querying
-    // the 0-th dimensions, of the left, and the 1st dimension of the right.
-    // Concatenating them togething to make the final shape.
-    Value batchSize = rewriter.create<mhlo::GetDimensionSizeOp>(
-        op.getLoc(), lhs, rewriter.getI64IntegerAttr(0));
-    Value batchSize1 = rewriter.create<mhlo::ReshapeOp>(
-        op.getLoc(), RankedTensorType::get({1}, rewriter.getI32Type()),
-        batchSize);
-
-    Value featureSize = rewriter.create<mhlo::GetDimensionSizeOp>(
-        op.getLoc(), rhs, rewriter.getI64IntegerAttr(1));
-    Value featureSize1 = rewriter.create<mhlo::ReshapeOp>(
-        op.getLoc(), RankedTensorType::get({1}, rewriter.getI32Type()),
-        featureSize);
-
-    Value outSize = rewriter.create<mhlo::ConcatenateOp>(
-        op.getLoc(), RankedTensorType::get({2}, rewriter.getI32Type()),
-        ValueRange{batchSize1, featureSize1}, rewriter.getI64IntegerAttr(0));
-
-    lhs = rewriter.create<mhlo::DynamicBroadcastInDimOp>(
-        op.getLoc(), resultTy.clone(lhsTy.getElementType()), lhs, outSize,
-        rewriter.getI64TensorAttr({0, 1}));
-
-    rhs = rewriter.create<mhlo::DynamicBroadcastInDimOp>(
-        op.getLoc(), resultTy.clone(rhsTy.getElementType()), rhs, outSize,
-        rewriter.getI64TensorAttr({0, 1}));
-
-    auto computeETy = lhsTy.getElementType();
-    if (computeETy.getIntOrFloatBitWidth() < rhsTy.getElementTypeBitWidth())
-      computeETy = rhsTy.getElementType();
-    if (computeETy.getIntOrFloatBitWidth() < resultTy.getElementTypeBitWidth())
-      computeETy = resultTy.getElementType();
-
-    auto computeTy = resultTy.clone(computeETy);
-
-    rhs = rewriter.create<mhlo::ConvertOp>(op.getLoc(), computeTy, rhs);
-    lhs = rewriter.create<mhlo::ConvertOp>(op.getLoc(), computeTy, lhs);
-
-    auto result = rewriter.create<mhlo::MulOp>(
-        op.getLoc(), resultTy.clone(computeETy), lhs, rhs);
-    rewriter.replaceOpWithNewOp<mhlo::ConvertOp>(op, resultTy, result);
-    return success();
-  }
-};
-
-// Similar to DotIsMul, this finds the case where a dot general
-// can be represented using a mul operation. This includes possibly making
-// an implicit cast explicit prior the mul.
-struct DotGeneralIsMul : public OpRewritePattern<mhlo::DotGeneralOp> {
-  using OpRewritePattern<mhlo::DotGeneralOp>::OpRewritePattern;
-
-  LogicalResult matchAndRewrite(mhlo::DotGeneralOp op,
-                                PatternRewriter &rewriter) const override {
-    auto lhs = llvm::cast<Value>(op.getLhs());
-    auto rhs = llvm::cast<Value>(op.getRhs());
-    auto lhsTy = llvm::dyn_cast<RankedTensorType>(lhs.getType());
-    auto rhsTy = llvm::dyn_cast<RankedTensorType>(rhs.getType());
-    auto resultTy = llvm::dyn_cast<RankedTensorType>(op.getType());
-    ImplicitLocOpBuilder builder(op.getLoc(), rewriter);
-
-    if (!lhsTy || !rhsTy || !resultTy) return failure();
-
-    auto dNums = op.getDotDimensionNumbers();
-    auto batchDimsL = dNums.getLhsBatchingDimensions();
-    auto batchDimsR = dNums.getRhsBatchingDimensions();
-    auto contractDimsL = dNums.getLhsContractingDimensions();
-    auto contractDimsR = dNums.getRhsContractingDimensions();
-
-    llvm::SmallVector<bool> isLhsParallelDim(lhsTy.getRank(), true);
-    llvm::SmallVector<bool> isRhsParallelDim(rhsTy.getRank(), true);
-
-    for (auto dim : batchDimsL) isLhsParallelDim[dim] = false;
-    for (auto dim : batchDimsR) isRhsParallelDim[dim] = false;
-    for (auto dim : contractDimsL) isLhsParallelDim[dim] = false;
-    for (auto dim : contractDimsR) isRhsParallelDim[dim] = false;
-
-    for (auto dim : contractDimsL) {
-      if (lhsTy.getDimSize(dim) != 1) {
-        return rewriter.notifyMatchFailure(op, "Non unit contract dimensions");
-      }
-    }
-
-    // Generate the permutation matrix to order BatchDims, ParallelDims,
-    // ContractDims.
-    llvm::SmallVector<int64_t> permLhs;
-    llvm::SmallVector<int64_t> permRhs;
-    permLhs.append(batchDimsL.begin(), batchDimsL.end());
-    permRhs.append(batchDimsR.begin(), batchDimsR.end());
-
-    for (auto it : llvm::enumerate(isLhsParallelDim)) {
-      if (it.value()) permLhs.push_back(it.index());
-    }
-
-    for (auto it : llvm::enumerate(isRhsParallelDim)) {
-      if (it.value()) permRhs.push_back(it.index());
-    }
-
-    permLhs.append(contractDimsL.begin(), contractDimsL.end());
-    permRhs.append(contractDimsR.begin(), contractDimsR.end());
-
-    // Determine the transpose shape based on the generate permutations.
-    llvm::SmallVector<int64_t> lhsTransposeShape;
-    llvm::SmallVector<int64_t> rhsTransposeShape;
-    for (auto dim : permLhs) lhsTransposeShape.push_back(lhsTy.getDimSize(dim));
-    for (auto dim : permRhs) rhsTransposeShape.push_back(rhsTy.getDimSize(dim));
-
-    // Transpose the left hand side and the right hand side.
-    lhs = builder.create<mhlo::TransposeOp>(
-        RankedTensorType::get(lhsTransposeShape, lhsTy.getElementType()), lhs,
-        builder.getI64TensorAttr(permLhs));
-    lhsTy = llvm::cast<RankedTensorType>(lhs.getType());
-
-    rhs = builder.create<mhlo::TransposeOp>(
-        RankedTensorType::get(rhsTransposeShape, rhsTy.getElementType()), rhs,
-        builder.getI64TensorAttr(permRhs));
-    rhsTy = llvm::cast<RankedTensorType>(rhs.getType());
-
-    auto dimI32Ty = RankedTensorType::get({1}, builder.getI32Type());
-
-    // Drop all of the non-concat dimensions from the lhs.
-    llvm::SmallVector<Value> lhsReshapeDims;
-    for (int i = 0, s = lhsTy.getRank() - contractDimsL.size(); i < s; i++) {
-      Value dim = builder.create<mhlo::GetDimensionSizeOp>(lhs, i);
-      lhsReshapeDims.push_back(builder.create<mhlo::ReshapeOp>(dimI32Ty, dim));
-    }
-    Value lhsDynShape = builder.create<mhlo::ConcatenateOp>(
-        RankedTensorType::get({static_cast<int64_t>(lhsReshapeDims.size())},
-                              builder.getI32Type()),
-        lhsReshapeDims, 0);
-    lhsTy =
-        RankedTensorType::get(lhsTy.getShape().drop_back(contractDimsL.size()),
-                              lhsTy.getElementType());
-    lhs = builder.create<mhlo::DynamicReshapeOp>(lhsTy, lhs, lhsDynShape);
-
-    // Drop all of the non concat dimensions from the rhs.
-    llvm::SmallVector<Value> rhsReshapeDims;
-    for (int i = 0, s = rhsTy.getRank() - contractDimsR.size(); i < s; i++) {
-      Value dim = builder.create<mhlo::GetDimensionSizeOp>(rhs, i);
-      rhsReshapeDims.push_back(builder.create<mhlo::ReshapeOp>(dimI32Ty, dim));
-    }
-    Value rhsDynShape = builder.create<mhlo::ConcatenateOp>(
-        RankedTensorType::get({static_cast<int64_t>(rhsReshapeDims.size())},
-                              builder.getI32Type()),
-        rhsReshapeDims, 0);
-    rhsTy =
-        RankedTensorType::get(rhsTy.getShape().drop_back(contractDimsR.size()),
-                              rhsTy.getElementType());
-    rhs = builder.create<mhlo::DynamicReshapeOp>(rhsTy, rhs, rhsDynShape);
-
-    // Compute the size of the output shape with dynamic shape support using the
-    // lhs and rhs dimensions.
-    llvm::SmallVector<Value> outputDims;
-    outputDims.append(lhsReshapeDims);
-    outputDims.append(rhsReshapeDims.begin() + batchDimsR.size(),
-                      rhsReshapeDims.end());
-    Value outputShape = builder.create<mhlo::ConcatenateOp>(
-        RankedTensorType::get({resultTy.getRank()}, builder.getI32Type()),
-        outputDims, 0);
-
-    // Broadcast the left hand side to match the expect output shape.
-    llvm::SmallVector<int64_t> lhsDimMapping(lhsTy.getRank());
-    std::iota(lhsDimMapping.begin(), lhsDimMapping.end(), 0);
-    auto lhsBroadcastTy =
-        RankedTensorType::get(resultTy.getShape(), lhsTy.getElementType());
-    lhs = builder.createOrFold<mhlo::DynamicBroadcastInDimOp>(
-        lhsBroadcastTy, lhs, outputShape,
-        rewriter.getI64TensorAttr(lhsDimMapping));
-
-    // Broadcast the right hand side to match the expected output shape.
-    llvm::SmallVector<int64_t> rhsDimMapping(rhsTy.getRank());
-    std::iota(rhsDimMapping.begin(), rhsDimMapping.begin() + batchDimsR.size(),
-              0);
-    std::iota(rhsDimMapping.begin() + batchDimsR.size(), rhsDimMapping.end(),
-              lhsTy.getRank());
-    auto rhsBroadcastTy =
-        RankedTensorType::get(resultTy.getShape(), rhsTy.getElementType());
-    rhs = builder.createOrFold<mhlo::DynamicBroadcastInDimOp>(
-        rhsBroadcastTy, rhs, outputShape,
-        rewriter.getI64TensorAttr(rhsDimMapping));
-
-    lhs = builder.createOrFold<mhlo::ConvertOp>(resultTy, lhs);
-    rhs = builder.createOrFold<mhlo::ConvertOp>(resultTy, rhs);
-    rewriter.replaceOpWithNewOp<mhlo::MulOp>(op, resultTy, lhs, rhs);
-    return success();
-  }
-};
-
-struct MHLOToMHLOPreprocessingPass
-    : public MHLOToMHLOPreprocessingBase<MHLOToMHLOPreprocessingPass> {
-  void getDependentDialects(DialectRegistry &registry) const override {
-    registry.insert<shape::ShapeDialect, mhlo::MhloDialect,
-                    tensor::TensorDialect>();
-  }
-
-  void runOnOperation() override {
-    MLIRContext *context = &getContext();
-    ConversionTarget conversionTarget(*context);
-    RewritePatternSet conversionPatterns(&getContext());
-    // Note that various input modalities may do their own legalization of
-    // CHLO. Converting here allows IREE to accept CHLO dialect regardless of
-    // whether it was legalized away at a higher level.
-    // chlo::PopulateLegalizeChloToHloPatterns(context, &conversionPatterns);
-    conversionTarget.addLegalDialect<
-        shape::ShapeDialect, chlo::ChloDialect, mhlo::MhloDialect,
-        math::MathDialect, mlir::func::FuncDialect, mlir::arith::ArithDialect,
-        mlir::tensor::TensorDialect>();
-    // conversionTarget.addIllegalDialect<chlo::ChloDialect>();
-    if (failed(applyPartialConversion(getOperation(), conversionTarget,
-                                      std::move(conversionPatterns)))) {
-      return signalPassFailure();
-    }
-
-    RewritePatternSet patterns(&getContext());
-    // TODO: Remove once we have a general contraction to matmul pass.
-    mhlo::populateEinsumToDotGeneralPatterns(context, &patterns);
-    mhlo::populateUnfuseBatchNormPatterns(context, &patterns);
-    mhlo::populateComplexLoweringPatterns(context, &patterns);
-    mhlo::populateGatherToTorchIndexSelectPatterns(context, &patterns);
-    patterns.insert<ExpandRngNormal, MulCastOfBool>(context);
-
-    // scatter canonicalization patterns
-    patterns.insert<ScatterInt64Indices, ScatterImplicitIndex,
-                    ScatterImplicitBatch, ScatterMaterializeInsertedDim,
-                    ScatterCollapseBatch, ScatterBatchFirst>(context);
-
-    // dot_general canoncalization patterns.
-    mhlo::populateGeneralDotOpLoweringPatterns(&patterns, context);
-    // TODO(jpienaar): This may be redundant with lower_general_dot. Remove if
-    // so.
-    patterns.insert<TransposeReshapeGenericDotGeneral>(context,
-                                                       /*benefit=*/200);
-    patterns.insert<DotGeneralIsMul>(context, /*benefit=*/300);
-
-    // Fusion operations.
-    patterns.insert<FuseWidenOperands<mhlo::DotOp>,
-                    FuseWidenOperands<mhlo::DotGeneralOp>,
-                    FuseWidenOperands<mhlo::ConvolutionOp>>(context,
-                                                            /*benefit=*/400);
-
-    // Additional canonicalizers that simplify to computationally
-    // less-complex operations.
-    patterns.insert<DotToMul>(context);
-
-    // Unary elementwise op.
-    patterns.insert<
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::AbsOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::CeilOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ConvertOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ClzOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::CosineOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ExpOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::Expm1Op>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::FloorOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ImagOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::IsFiniteOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::LogOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::Log1pOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::LogisticOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::NotOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::NegOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::PopulationCountOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::RealOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::RoundOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::RsqrtOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::SignOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::SineOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::SqrtOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::TanhOp>>(context);
-    // Binary elementwise op.
-    patterns.insert<
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::AddOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::Atan2Op>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ComplexOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::DivOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::MaxOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::MinOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::MulOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::PowOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::RemOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ShiftLeftOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ShiftRightArithmeticOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::ShiftRightLogicalOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::SubtractOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::AndOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::OrOp>,
-        ReorderBroadcastInDimOpAndElementwiseOp<mhlo::XorOp>>(context);
-    if (orderConvFeatures) {
-      patterns.insert<ReorderConvOpInputDimensions>(context);
-      patterns.insert<ReorderConvOpKernelDimensions>(context);
-      patterns.insert<ReorderConvOpOutputDimensions>(context);
-    }
-    if (failed(applyPatternsAndFoldGreedily(getOperation(),
-                                            std::move(patterns)))) {
-      return signalPassFailure();
-    }
-  }
-};
-
-}  // namespace
-
-std::unique_ptr<OperationPass<func::FuncOp>>
-createMHLOToMHLOPreprocessingPass() {
-  return std::make_unique<MHLOToMHLOPreprocessingPass>();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/PassDetail.h b/compiler/src/iree/compiler/InputConversion/MHLO/PassDetail.h
deleted file mode 100644
index a1320a8..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/PassDetail.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2021 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_INPUTCONVERSION_MHLO_PASSDETAIL_H_
-#define IREE_COMPILER_INPUTCONVERSION_MHLO_PASSDETAIL_H_
-
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/Pass/Pass.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-#define GEN_PASS_CLASSES
-#include "iree/compiler/InputConversion/MHLO/Passes.h.inc"
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
-
-#endif  // IREE_COMPILER_INPUTCONVERSION_MHLO_PASSDETAIL_H_
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/Passes.cpp
deleted file mode 100644
index edd2675..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2021 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/InputConversion/MHLO/Passes.h"
-
-#include "iree/compiler/Dialect/Util/Transforms/Passes.h"
-#include "iree/compiler/InputConversion/Common/Passes.h"
-#include "mhlo/transforms/passes.h"
-#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
-#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
-#include "mlir/Conversion/ShapeToStandard/ShapeToStandard.h"
-#include "mlir/Dialect/SCF/Transforms/Passes.h"
-#include "mlir/Dialect/Shape/Transforms/Passes.h"
-#include "mlir/Pass/PassManager.h"
-#include "mlir/Pass/PassOptions.h"
-#include "mlir/Pass/PassRegistry.h"
-#include "mlir/Transforms/Passes.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-// TODO(#8745): remove these flags when the -iree-flow-demote-* flags can be
-// used without tripping upstream verifier issues.
-static llvm::cl::opt<bool> clDemoteI64ToI32(
-    "iree-mhlo-demote-i64-to-i32",
-    llvm::cl::desc(
-        "Converts all MHLO i64 ops and values into i32 counterparts."),
-    llvm::cl::init(true));
-static llvm::cl::opt<bool> clDemoteF64ToF32(
-    "iree-mhlo-demote-f64-to-f32",
-    llvm::cl::desc(
-        "Converts all MHLO f64 ops and values into f32 counterparts."),
-    llvm::cl::init(true));
-static llvm::cl::opt<bool> clPromoteBF16ToF32(
-    "iree-mhlo-promote-bf16-to-f32",
-    llvm::cl::desc(
-        "Converts all MHLO bf16 ops and values into f32 counterparts."),
-    llvm::cl::init(false));
-
-void registerMHLOConversionPassPipeline() {
-  PassPipelineRegistration<> mhlo(
-      "iree-mhlo-input-transformation-pipeline",
-      "Runs the MHLO IREE flow dialect transformation pipeline",
-      [](OpPassManager &passManager) {
-        buildMHLOInputConversionPassPipeline(passManager);
-      });
-  PassPipelineRegistration<> xla(
-      "iree-xla-input-transformation-pipeline",
-      "Runs the XLA IREE flow dialect transformation pipeline",
-      [](OpPassManager &passManager) {
-        buildXLAInputConversionPassPipeline(passManager);
-      });
-}
-
-// Prepare HLO for use as an input to the Flow dialect.
-static void buildMHLOInputConversionPassPipelineImpl(OpPassManager &passManager,
-                                                     bool detuple) {
-  passManager.addPass(mlir::mhlo::createStablehloLegalizeToHloPass());
-  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());
-  passManager.addNestedPass<func::FuncOp>(
-      mhlo::createLegalizeControlFlowPass());
-
-  // Currently we don't handle SCF ops well and have to convert them all to CFG.
-  // In the future it would be nice if we could have all of flow be both scf
-  // and cfg compatible.
-  passManager.addNestedPass<func::FuncOp>(createTopLevelSCFToCFGPass());
-  if (detuple) passManager.addPass(createFlattenTuplesInCFGPass());
-
-  passManager.addNestedPass<func::FuncOp>(createMHLOToMHLOPreprocessingPass());
-  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());
-
-  // Various shape functions may have been materialized in the `shape.shape_of`
-  // style of treating shapes as tensors. We prefer to legalize these to
-  // scalar ops as early as possible to avoid having them persist as tensor
-  // computations.
-  passManager.addNestedPass<func::FuncOp>(createShapeToShapeLowering());
-  passManager.addPass(createConvertShapeToStandardPass());
-  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());
-
-  // We also don't handle calls well on the old codepath; until we remove the
-  // use of the CFG we can continue inlining.
-  passManager.addPass(mlir::createInlinerPass());
-
-  // Hacky type conversion to work around lack of type support lower in the
-  // stack. This is often required because of implicit i64 insertion by JAX/HLO
-  // that we don't want forcing 32-bit embedded devices to support.
-  // TODO(#8745): remove these and prefer the flow pipeline options instead.
-  if (clDemoteI64ToI32) {
-    passManager.addPass(IREE::Util::createDemoteI64ToI32Pass());
-  }
-  if (clDemoteF64ToF32) {
-    passManager.addPass(IREE::Util::createDemoteF64ToF32Pass());
-  }
-  if (clPromoteBF16ToF32) {
-    passManager.addPass(IREE::Util::createPromoteBF16ToF32Pass());
-  }
-
-  // Perform initial cleanup. createLegalizeInputTypes could rewrite types. In
-  // this context, some operations could be folded away.
-  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());
-  passManager.addNestedPass<func::FuncOp>(mlir::createCSEPass());
-
-  // Convert to Linalg. After this point, MHLO will be eliminated.
-  passManager.addNestedPass<func::FuncOp>(
-      mhlo::createLegalizeShapeComputationsPass());
-  passManager.addNestedPass<func::FuncOp>(createConvertMHLOToLinalgExtPass());
-  passManager.addPass(createMHLOToLinalgOnTensorsPass());
-  // Ensure conversion completed.
-  passManager.addPass(createReconcileUnrealizedCastsPass());
-
-  // Note that some MHLO ops are left by the above and must resolve via
-  // canonicalization. See comments in the above pass and find a better way.
-  passManager.addNestedPass<func::FuncOp>(mlir::createCanonicalizerPass());
-
-  //----------------------------------------------------------------------------
-  // Entry dialect cleanup
-  //----------------------------------------------------------------------------
-  passManager.addPass(createVerifyCompilerMHLOInputLegality());
-}
-
-void buildMHLOInputConversionPassPipeline(OpPassManager &passManager) {
-  buildMHLOInputConversionPassPipelineImpl(passManager, /*detuple=*/false);
-}
-
-void buildXLAInputConversionPassPipeline(OpPassManager &passManager) {
-  buildMHLOInputConversionPassPipelineImpl(passManager, /*detuple=*/true);
-}
-
-namespace {
-#define GEN_PASS_REGISTRATION
-#include "iree/compiler/InputConversion/MHLO/Passes.h.inc"  // IWYU pragma: export
-}  // namespace
-
-void registerMHLOConversionPasses() {
-  // Generated.
-  registerPasses();
-
-  // Pipelines.
-  registerMHLOConversionPassPipeline();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.h b/compiler/src/iree/compiler/InputConversion/MHLO/Passes.h
deleted file mode 100644
index 15c9454..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2021 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_INPUTCONVERSION_MHLO_PASSES_H_
-#define IREE_COMPILER_INPUTCONVERSION_MHLO_PASSES_H_
-
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/Pass/Pass.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-//===----------------------------------------------------------------------===//
-// Pipelines
-//===----------------------------------------------------------------------===//
-
-// Performs input legalization for specific combination of input dialects.
-void buildMHLOInputConversionPassPipeline(OpPassManager &passManager);
-
-// Performs input legalization on programs that may have originated from an XLA
-// import (or made to interop with it).
-void buildXLAInputConversionPassPipeline(OpPassManager &passManager);
-
-void registerMHLOConversionPassPipelines();
-
-//------------------------------------------------------------------------------
-// Cleanup passes
-//------------------------------------------------------------------------------
-
-// Flattens tuples in functions and CFG control flow. This is a common
-// form of MHLO as produced by XLA based systems.
-std::unique_ptr<OperationPass<ModuleOp>> createFlattenTuplesInCFGPass();
-
-//------------------------------------------------------------------------------
-// Conversions into Linalg
-//------------------------------------------------------------------------------
-
-/// Creates XLA-HLO to Linalg on tensors transformation pass.
-std::unique_ptr<OperationPass<ModuleOp>> createMHLOToLinalgOnTensorsPass();
-
-/// Creates XLA-HLO to LinalgExt pass.
-std::unique_ptr<OperationPass<func::FuncOp>> createConvertMHLOToLinalgExtPass();
-
-/// Creates XLA-HLO preprocessing transformation pass. In this pass we should
-/// have all mhlo -> mhlo transformations that are shared between all
-/// backends.
-std::unique_ptr<OperationPass<func::FuncOp>>
-createMHLOToMHLOPreprocessingPass();
-
-// Verifies a module being input to the core compiler pipeline only contains
-// IR structures that are supported at that level.
-std::unique_ptr<OperationPass<ModuleOp>>
-createVerifyCompilerMHLOInputLegality();
-
-//------------------------------------------------------------------------------
-// Passes to aid in the MHLO to StableHLO transition
-//------------------------------------------------------------------------------
-
-std::unique_ptr<OperationPass<ModuleOp>> createConvertMHLOToStableHLOPass();
-
-//------------------------------------------------------------------------------
-// Test passes
-//------------------------------------------------------------------------------
-
-std::unique_ptr<OperationPass<func::FuncOp>>
-createTestMHLOConvertComplexToRealPass();
-
-//===----------------------------------------------------------------------===//
-// Register all Passes
-//===----------------------------------------------------------------------===//
-
-void registerMHLOConversionPasses();
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
-
-#endif  // IREE_COMPILER_INPUTCONVERSION_MHLO_PASSES_H_
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.td b/compiler/src/iree/compiler/InputConversion/MHLO/Passes.td
deleted file mode 100644
index 85d5ed2..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/Passes.td
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2021 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_INPUTCONVERSION_MHLO_PASSES
-#define IREE_COMPILER_INPUTCONVERSION_MHLO_PASSES
-
-include "mlir/Pass/PassBase.td"
-
-def ConvertMHLOToLinalgOnTensors :
-    Pass<"iree-mhlo-to-linalg-on-tensors", "ModuleOp"> {
-  let summary = "Convert from XLA-HLO ops to Linalg ops on tensors";
-  let constructor = "mlir::iree_compiler::MHLO::createMHLOToLinalgOnTensorsPass()";
-}
-
-def ConvertMHLOToLinalgExt
-    : Pass<"iree-mhlo-to-linalg-ext", "func::FuncOp"> {
-  let summary =
-      "Convert from XLA-HLO ops to LinalgExt ops and distribute to Flow ops";
-  let constructor =
-      "mlir::iree_compiler::MHLO::createConvertMHLOToLinalgExtPass()";
-}
-
-def FlattenTuplesInCFG :
-    Pass<"iree-mhlo-flatten-tuples-in-cfg", "ModuleOp"> {
-  let summary = "Flattens tuples in a CFG form of MHLO";
-  let constructor = "mlir::iree_compiler::MHLO::createFlattenTuplesInCFGPass()";
-}
-
-def MHLOToMHLOPreprocessing :
-    Pass<"iree-mhlo-to-mhlo-preprocessing", "func::FuncOp"> {
-  let summary = "Apply mhlo to mhlo transformations for some mhlo ops";
-  let constructor = "mlir::iree_compiler::MHLO::createMHLOToMHLOPreprocessingPass()";
-  let options = [
-    Option<"orderConvFeatures", "order-conv-features", "bool", /*default=*/"true",
-           "Guarantees input/output features ordered from conv kernel">
-  ];
-}
-
-def VerifyCompilerMHLOInputLegality :
-    Pass<"iree-mhlo-verify-compiler-input-legality", "ModuleOp"> {
-  let summary = "Verifies that only supported IR constructs are passed to the compiler.";
-  let constructor = "mlir::iree_compiler::MHLO::createVerifyCompilerMHLOInputLegality()";
-}
-
-def ConvertMHLOToStableHLOPass : Pass<"iree-convert-mhlo-to-stablehlo", "ModuleOp"> {
-  let summary = "Convert MHLO to StableHLO, to aid in transition to StableHLO.";
-  let constructor = "mlir::iree_compiler::MHLO::createConvertMHLOToStableHLOPass()";
-}
-
-//------------------------------------------------------------------------------
-// Test passes
-//------------------------------------------------------------------------------
-
-def TestMHLOConvertComplexToReal :
-    Pass<"iree-test-mhlo-convert-complex-to-real", "func::FuncOp"> {
-  let summary = "Test pass that does an MHLO->MHLO conversion of just complex arithmetic ops.";
-  let constructor = "mlir::iree_compiler::MHLO::createTestMHLOConvertComplexToRealPass()";
-}
-
-#endif // IREE_COMPILER_INPUTCONVERSION_MHLO_PASSES
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/Rewriters.h b/compiler/src/iree/compiler/InputConversion/MHLO/Rewriters.h
deleted file mode 100644
index e839f38..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/Rewriters.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021 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_INPUTCONVERSION_MHLO_REWRITER_H_
-#define IREE_COMPILER_INPUTCONVERSION_MHLO_REWRITER_H_
-
-#include "mlir/Transforms/DialectConversion.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-/// Populates the patterns that convert from MHLO to Linalg on tensors. Imports
-/// patterns from XLA, as well as some IREE specific modifications.
-void populateMHLOToLinalgOnTensorsConversionPatterns(
-    MLIRContext *context, TypeConverter &typeConverter,
-    RewritePatternSet &patterns);
-
-/// Populates IREE specific patterns to convert HLO broadcasting ops to Linalg.
-/// These are being maintained separately because they are a standalone unit
-/// that is both intricate and possible to upstream, should there be alignment
-/// to do so.
-void populateMHLOBroadcastingToLinalgPatterns(MLIRContext *context,
-                                              TypeConverter &typeConverter,
-                                              RewritePatternSet &patterns);
-
-/// Populates patterns to convert MHLO collective ops to Stream ops.
-void populateMHLOCollectiveOpsConversionPatterns(MLIRContext *context,
-                                                 TypeConverter &typeConverter,
-                                                 RewritePatternSet &patterns);
-
-/// Populates patterns to convert MHLO/CHLO arithmetic on complex tensors to
-/// equivalent HLO level real arithmetic.
-void populateMHLOComplexToRealPatterns(MLIRContext *context,
-                                       TypeConverter &typeConverter,
-                                       RewritePatternSet &patterns);
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
-
-#endif  // IREE_COMPILER_INPUTCONVERSION_MHLO_REWRITER_H_
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/VerifyCompilerMHLOInputLegality.cpp b/compiler/src/iree/compiler/InputConversion/MHLO/VerifyCompilerMHLOInputLegality.cpp
deleted file mode 100644
index bde4fa5..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/VerifyCompilerMHLOInputLegality.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2021 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/InputConversion/MHLO/PassDetail.h"
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
-#include "mhlo/IR/hlo_ops.h"
-#include "mlir/Dialect/Shape/IR/Shape.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Pass/PassManager.h"
-#include "mlir/Transforms/DialectConversion.h"
-#include "stablehlo/dialect/ChloOps.h"
-
-namespace mlir {
-namespace iree_compiler {
-namespace MHLO {
-
-struct VerifyCompilerMHLOInputLegalityPass
-    : public VerifyCompilerMHLOInputLegalityBase<
-          VerifyCompilerMHLOInputLegalityPass> {
-  void runOnOperation() override {
-    auto *context = &getContext();
-    ConversionTarget conversionTarget(*context);
-    RewritePatternSet conversionPatterns(&getContext());
-
-    // Note that we would prefer allow-lists of what we positively support.
-    // However, it is so common to sneak input-level ops into the pipeline
-    // that we explicitly deny the dialects we know about.
-    conversionTarget.addIllegalDialect<mhlo::MhloDialect>();
-    conversionTarget.addIllegalDialect<chlo::ChloDialect>();
-    conversionTarget.addIllegalDialect<mlir::shape::ShapeDialect>();
-
-    // NOTE: It is not fully illegal to tunnel input dialect ops through to
-    // backends that expect them. When such situations arise, the container
-    // op should be marked recursively legal here.
-    SmallVector<Diagnostic> failures;
-    {
-      ScopedDiagnosticHandler diag(context,
-                                   [&](Diagnostic &d) -> LogicalResult {
-                                     failures.push_back(std::move(d));
-                                     return success();
-                                   });
-      if (succeeded(applyPartialConversion(getOperation(), conversionTarget,
-                                           std::move(conversionPatterns)))) {
-        return;
-      }
-    }
-
-    // Error fall-through. Attach all reported issues as notes.
-    InFlightDiagnostic errorDiag =
-        emitError(getOperation().getLoc())
-        << "one or more illegal operations were found in the compiler input "
-           "(are you missing an --iree-input-type= flag, or did you mean to "
-           "pre-process through an IREE importer frontend?)";
-    for (auto &failureDiag : failures) {
-      Diagnostic &note = errorDiag.attachNote(failureDiag.getLocation());
-      for (auto &arg : failureDiag.getArguments()) {
-        note.append(arg);
-      }
-    }
-
-    signalPassFailure();
-  }
-};
-
-std::unique_ptr<OperationPass<ModuleOp>>
-createVerifyCompilerMHLOInputLegality() {
-  return std::make_unique<VerifyCompilerMHLOInputLegalityPass>();
-}
-
-}  // namespace MHLO
-}  // namespace iree_compiler
-}  // namespace mlir
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/BUILD.bazel b/compiler/src/iree/compiler/InputConversion/MHLO/test/BUILD.bazel
deleted file mode 100644
index a9ff945..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/BUILD.bazel
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2019 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
-
-# Tests for common transforms.
-
-load("//build_tools/bazel:iree_lit_test.bzl", "iree_lit_test_suite")
-load("//build_tools/bazel:enforce_glob.bzl", "enforce_glob")
-
-package(
-    features = ["layering_check"],
-    licenses = ["notice"],  # Apache 2.0
-)
-
-iree_lit_test_suite(
-    name = "lit",
-    srcs = enforce_glob(
-        [
-            "broadcasting.mlir",
-            "convert_mhlo_to_linalg_ext.mlir",
-            "convert_mhlo_to_stablehlo.mlir",
-            "convert_collective_ops.mlir",
-            "convert_complex_to_real.mlir",
-            "convert_structural_types.mlir",
-            "dynamic_shape.mlir",
-            "fft.mlir",
-            "flatten_tuples_in_cfg.mlir",
-            "mhlo_to_linalg.mlir",
-            "mhlo_to_mhlo_preprocessing.mlir",
-            "mhlo_to_mhlo_preprocessing_canonicalize_dot_general.mlir",
-            "mhlo_to_mhlo_scatter.mlir",
-            "missing_legalizations.mlir",
-            "transformation_pipeline.mlir",
-            "verify_compiler_mhlo_input_legality.mlir",
-        ],
-        include = ["*.mlir"],
-    ),
-    cfg = "//compiler:lit.cfg.py",
-    tools = [
-        "//tools:iree-opt",
-        "@llvm-project//llvm:FileCheck",
-    ],
-)
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/CMakeLists.txt b/compiler/src/iree/compiler/InputConversion/MHLO/test/CMakeLists.txt
deleted file mode 100644
index 679cebd..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-################################################################################
-# Autogenerated by build_tools/bazel_to_cmake/bazel_to_cmake.py from           #
-# compiler/src/iree/compiler/InputConversion/MHLO/test/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_lit_test_suite(
-  NAME
-    lit
-  SRCS
-    "broadcasting.mlir"
-    "convert_collective_ops.mlir"
-    "convert_complex_to_real.mlir"
-    "convert_mhlo_to_linalg_ext.mlir"
-    "convert_mhlo_to_stablehlo.mlir"
-    "convert_structural_types.mlir"
-    "dynamic_shape.mlir"
-    "fft.mlir"
-    "flatten_tuples_in_cfg.mlir"
-    "mhlo_to_linalg.mlir"
-    "mhlo_to_mhlo_preprocessing.mlir"
-    "mhlo_to_mhlo_preprocessing_canonicalize_dot_general.mlir"
-    "mhlo_to_mhlo_scatter.mlir"
-    "missing_legalizations.mlir"
-    "transformation_pipeline.mlir"
-    "verify_compiler_mhlo_input_legality.mlir"
-  TOOLS
-    FileCheck
-    iree-opt
-)
-
-### BAZEL_TO_CMAKE_PRESERVES_ALL_CONTENT_BELOW_THIS_LINE ###
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/broadcasting.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/broadcasting.mlir
deleted file mode 100644
index 39da165..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/broadcasting.mlir
+++ /dev/null
@@ -1,442 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors %s | FileCheck %s
-
-// Check the non-broadcast case for each registered op, then just check a
-// representative op for detailed broadcast semantics. Since the broadcasting
-// implementation lowers through mhlo ops, we are primarily checking broadcast
-// semantics and not exhaustively checking that the non broadcasting ops lower
-// to the right linalg sequences.
-
-// CHECK-LABEL: @addWithoutBroadcast
-func.func @addWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK: linalg.generic
-  // CHECK-SAME: outs(%0 : tensor<4xf32>
-  // CHECK: addf
-  // CHECK-NOT: linalg.generic
-  %0 = chlo.broadcast_add %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1) -> (d1)>
-// CHECK: #map1 = affine_map<(d0, d1) -> (d0, d1)>
-// CHECK-LABEL: @dynamicBroadcast
-func.func @dynamicBroadcast(%arg0: tensor<?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
-  // Should broadcast %arg0 -> %arg1 and cf.assert on dynamic expansion.
-
-  // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
-  // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-  // CHECK-DAG: %[[ARG0_D0:.*]] = tensor.dim %arg0, %[[C0]]
-  // CHECK-DAG: %[[ARG1_D0:.*]] = tensor.dim %arg1, %[[C0]] : tensor<?x?xf32>
-  // CHECK-DAG: %[[ARG1_D1:.*]] = tensor.dim %arg1, %[[C1]] : tensor<?x?xf32>
-  // CHECK: %[[EQ:.*]] = arith.cmpi eq, %[[ARG0_D0]], %[[ARG1_D1]] : index
-  // CHECK: cf.assert %[[EQ]], "mismatched dynamic broadcast extents"
-
-  // CHECK: %[[INIT_0:.*]] = tensor.empty(%[[ARG1_D0]], %[[ARG0_D0]]) : tensor<?x?xf32>
-  // CHECK: %[[BCAST_ARG0:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel"]}
-  // CHECK-SAME: ins(%arg0 : tensor<?xf32>) outs(%[[INIT_0]] : tensor<?x?xf32>)
-
-  // CHECK: %[[RESULT:.*]] = linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_ARG0]], %arg1 : tensor<?x?xf32>, tensor<?x?xf32>)
-
-  // CHECK-NOT: mhlo.add
-  %0 = chlo.broadcast_add %arg0, %arg1 : (tensor<?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
-  return %0 : tensor<?x?xf32>
-}
-
-// -----
-// Verifies that broadcast_dimensions validity checks are valid.
-// CHECK-LABEL: @dynamicNonScalarBroadcastDimensions
-func.func @dynamicNonScalarBroadcastDimensions(%arg0: tensor<1x4xf32>, %arg1: tensor<4xf32>) -> tensor<1x4xf32> {
-  %0 = chlo.broadcast_add %arg0, %arg1 {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<1x4xf32>, tensor<4xf32>) -> tensor<1x4xf32>
-  return %0 : tensor<1x4xf32>
-}
-
-// -----
-// Verifies that broadcast_dimensions validity checks are valid.
-// CHECK-LABEL: @dynamicNonScalarByScalarBroadcastDimensions
-func.func @dynamicNonScalarByScalarBroadcastDimensions(%arg0: tensor<1x4xf32>, %arg1: tensor<f32>) -> tensor<1x4xf32> {
-  %0 = chlo.broadcast_add %arg0, %arg1 {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<1x4xf32>, tensor<f32>) -> tensor<1x4xf32>
-  return %0 : tensor<1x4xf32>
-}
-
-// -----
-// CHECK-LABEL: @dynamicBroadcastComplex
-func.func @dynamicBroadcastComplex(%arg0: tensor<?xf32>, %arg1: tensor<?x?xf32>) -> (tensor<?x?xf32>, tensor<?x?xf32>) {
-  // CHECK-NOT: mhlo.complex
-  // CHECK-NOT: chlo.broadcast_complex
-  %0 = chlo.broadcast_complex %arg0, %arg1 : (tensor<?xf32>, tensor<?x?xf32>) -> tensor<?x?xcomplex<f32>>
-
-  %1 = "mhlo.real"(%0) : (tensor<?x?xcomplex<f32>>) -> tensor<?x?xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<?x?xcomplex<f32>>) -> tensor<?x?xf32>
-
-  return %1, %2 : tensor<?x?xf32>, tensor<?x?xf32>
-}
-
-// -----
-// CHECK-LABEL: @dynamicBroadcastCompare
-func.func @dynamicBroadcastCompare(%arg0: tensor<?xf32>, %arg1: tensor<?x?xf32>) -> tensor<?x?xi1> {
-  // NOTE: compare is unique because of the element type switch. The pattern
-  // will fail or the verifier will catch it if wrong.
-  // CHECK-NOT: mhlo.compare
-  %0 = chlo.broadcast_compare %arg0, %arg1 {comparison_direction = #chlo<comparison_direction EQ>} : (tensor<?xf32>, tensor<?x?xf32>) -> tensor<?x?xi1>
-  return %0 : tensor<?x?xi1>
-}
-
-// -----
-// CHECK-LABEL: func.func @selectv2
-func.func @selectv2(%arg0: tensor<2xi1>, %arg1: tensor<2xi32>, %arg2: tensor<2xi32>) -> tensor<2xi32> {
-  // All same type: should just short-circtuit to one mhlo.select / one generic.
-  // CHECK: linalg.generic
-  // CHECK:   %[[BODY:.*]] = arith.select
-  // CHECK-NOT: linalg.generic
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<2xi1>, tensor<2xi32>, tensor<2xi32>) -> tensor<2xi32>
-  return %0: tensor<2xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0) -> ()>
-// CHECK: #map1 = affine_map<(d0) -> (d0)>
-// CHECK-LABEL: func.func @selectv2_pred_scalar
-func.func @selectv2_pred_scalar(%arg0: tensor<i1>, %arg1: tensor<2xi32>, %arg2: tensor<2xi32>) -> tensor<2xi32> {
-  // CHECK: %[[INIT_0:.*]] = tensor.empty() : tensor<2xi1>
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel"]} ins(%arg0 : tensor<i1>) outs(%[[INIT_0]] : tensor<2xi1>)
-  // CHECK: %[[INIT_1:.*]] = tensor.empty() : tensor<2xi32>
-  // CHECK: linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_PRED]], %arg1, %arg2 : tensor<2xi1>, tensor<2xi32>, tensor<2xi32>) outs(%[[INIT_1]] : tensor<2xi32>)
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<i1>, tensor<2xi32>, tensor<2xi32>) -> tensor<2xi32>
-  return %0: tensor<2xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1, d2) -> ()>
-// CHECK: #map1 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-// CHECK: #map2 = affine_map<(d0, d1, d2) -> (d1, 0)>
-// CHECK-LABEL: func.func @selectv2_broadcast_then
-func.func @selectv2_broadcast_then(%arg0: tensor<i1>, %arg1: tensor<8x1xi32>, %arg2: tensor<2x8x8xi32>) -> tensor<2x8x8xi32> {
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg0 : tensor<i1>)
-  // CHECK: %[[BCAST_THEN:.*]] = linalg.generic {indexing_maps = [#map2, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg1 : tensor<8x1xi32>)
-  // CHECK: linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_PRED]], %[[BCAST_THEN]], %arg2 : tensor<2x8x8xi1>, tensor<2x8x8xi32>, tensor<2x8x8xi32>)
-  // CHECK: arith.select
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<i1>, tensor<8x1xi32>, tensor<2x8x8xi32>) -> tensor<2x8x8xi32>
-  return %0: tensor<2x8x8xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1, d2) -> ()>
-// CHECK: #map1 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-// CHECK: #map2 = affine_map<(d0, d1, d2) -> (d1, 0)>
-// CHECK-LABEL: func.func @selectv2_broadcast_else
-func.func @selectv2_broadcast_else(%arg0: tensor<i1>, %arg1: tensor<2x8x8xi32>, %arg2: tensor<8x1xi32>) -> tensor<2x8x8xi32> {
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg0 : tensor<i1>)
-  // CHECK: %[[BCAST_ELSE:.*]] = linalg.generic {indexing_maps = [#map2, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg2 : tensor<8x1xi32>)
-  // CHECK: linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_PRED]], %arg1, %[[BCAST_ELSE]] : tensor<2x8x8xi1>, tensor<2x8x8xi32>, tensor<2x8x8xi32>)
-  // CHECK: arith.select
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<i1>, tensor<2x8x8xi32>, tensor<8x1xi32>) -> tensor<2x8x8xi32>
-  return %0: tensor<2x8x8xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1, d2) -> (0)>
-// CHECK: #map1 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-// CHECK-LABEL: func.func @selectv2_broadcast_pred
-func.func @selectv2_broadcast_pred(%arg0: tensor<1xi1>, %arg1: tensor<2x8x8xi32>, %arg2: tensor<2x8x8xi32>) -> tensor<2x8x8xi32> {
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg0 : tensor<1xi1>)
-  // CHECK: linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_PRED]], %arg1, %arg2 : tensor<2x8x8xi1>, tensor<2x8x8xi32>, tensor<2x8x8xi32>)
-  // CHECK: arith.select
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<1xi1>, tensor<2x8x8xi32>, tensor<2x8x8xi32>) -> tensor<2x8x8xi32>
-  return %0: tensor<2x8x8xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1, d2) -> (d0, 0, 0)>
-// CHECK: #map1 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-// CHECK: #map2 = affine_map<(d0, d1, d2) -> (0, d1, 0)>
-// CHECK: #map3 = affine_map<(d0, d1, d2) -> (0, 0, d2)>
-// CHECK-LABEL: func.func @selectv2_broadcast_all
-func.func @selectv2_broadcast_all(%arg0: tensor<8x1x1xi1>, %arg1: tensor<1x8x1xi32>, %arg2: tensor<1x1x8xi32>) -> tensor<8x8x8xi32> {
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg0 : tensor<8x1x1xi1>)
-  // CHECK: %[[BCAST_THEN:.*]] = linalg.generic {indexing_maps = [#map2, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg1 : tensor<1x8x1xi32>)
-  // CHECK: %[[BCAST_ELSE:.*]] = linalg.generic {indexing_maps = [#map3, #map1], iterator_types = ["parallel", "parallel", "parallel"]} ins(%arg2 : tensor<1x1x8xi32>)
-  // CHECK: linalg.generic
-  // CHECK-SAME: ins(%[[BCAST_PRED]], %[[BCAST_THEN]], %[[BCAST_ELSE]] : tensor<8x8x8xi1>, tensor<8x8x8xi32>, tensor<8x8x8xi32>)
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<8x1x1xi1>, tensor<1x8x1xi32>, tensor<1x1x8xi32>) -> tensor<8x8x8xi32>
-  return %0: tensor<8x8x8xi32>
-}
-
-// -----
-// CHECK: #map = affine_map<(d0, d1, d2) -> (d0, 0, 0)>
-// CHECK: #map1 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
-// CHECK: #map2 = affine_map<(d0, d1, d2) -> (0, d1, 0)>
-// CHECK: #map3 = affine_map<(d0, d1, d2) -> (0, 0, d2)>
-// CHECK-LABEL: func.func @selectv2_broadcast_dyn_pred
-func.func @selectv2_broadcast_dyn_pred(%arg0: tensor<?x1x1xi1>, %arg1: tensor<1x8x1xi32>, %arg2: tensor<1x1x8xi32>) -> tensor<?x8x8xi32> {
-  // CHECK: %[[C0:.*]] = arith.constant 0 : index
-  // CHECK: %[[DIM_PRED_0:.*]] = tensor.dim %arg0, %[[C0]]
-  // CHECK: %[[INIT_PRED:.*]] = tensor.empty(%[[DIM_PRED_0]])
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map, #map1]
-  //     CHECK-SAME: ins(%arg0 : tensor<?x1x1xi1>) outs(%[[INIT_PRED]] : tensor<?x8x8xi1>)
-  // CHECK: %[[INIT_THEN:.*]] = tensor.empty(%[[DIM_PRED_0]])
-  // CHECK: %[[BCAST_THEN:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map2, #map1]
-  //     CHECK-SAME: ins(%arg1 : tensor<1x8x1xi32>) outs(%[[INIT_THEN]] : tensor<?x8x8xi32>)
-  // CHECK: %[[INIT_ELSE:.*]] = tensor.empty(%[[DIM_PRED_0]])
-  // CHECK: %[[BCAST_ELSE:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map3, #map1]
-  //     CHECK-SAME: ins(%arg2 : tensor<1x1x8xi32>) outs(%[[INIT_ELSE]] : tensor<?x8x8xi32>)
-  // CHECK: %[[SHAPE_BCAST_THEN:.*]] = shape.shape_of %[[BCAST_THEN]]
-  // CHECK: %[[DIM_BCAST_THEN_0:.*]] = tensor.extract %[[SHAPE_BCAST_THEN]][%[[C0]]]
-  // CHECK: %[[INIT_RESULT:.*]] = tensor.empty(%[[DIM_BCAST_THEN_0]])
-  // CHECK: linalg.generic
-  //     CHECK-SAME: ins(%[[BCAST_PRED]], %[[BCAST_THEN]], %[[BCAST_ELSE]] : tensor<?x8x8xi1>, tensor<?x8x8xi32>, tensor<?x8x8xi32>) outs(%[[INIT_RESULT]] : tensor<?x8x8xi32>)
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<?x1x1xi1>, tensor<1x8x1xi32>, tensor<1x1x8xi32>) -> tensor<?x8x8xi32>
-  return %0: tensor<?x8x8xi32>
-}
-
-// -----
-// CHECK-LABEL: func.func @selectv2_broadcast_dyn_then
-func.func @selectv2_broadcast_dyn_then(%arg0: tensor<8x1x1xi1>, %arg1: tensor<1x?x1xi32>, %arg2: tensor<1x1x8xi32>) -> tensor<8x?x8xi32> {
-  // CHECK: %[[C1:.*]] = arith.constant 1 : index
-  // CHECK: %[[DIM_THEN_1:.*]] = tensor.dim %arg1, %[[C1]]
-  // CHECK: %[[INIT_PRED:.*]] = tensor.empty(%[[DIM_THEN_1]])
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map, #map1]
-  //     CHECK-SAME: ins(%arg0 : tensor<8x1x1xi1>) outs(%[[INIT_PRED]] : tensor<8x?x8xi1>)
-  // CHECK: %[[INIT_THEN:.*]] = tensor.empty(%[[DIM_THEN_1]])
-  // CHECK: %[[BCAST_THEN:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map2, #map1]
-  //     CHECK-SAME: ins(%arg1 : tensor<1x?x1xi32>) outs(%[[INIT_THEN]] : tensor<8x?x8xi32>)
-  // CHECK: %[[INIT_ELSE:.*]] = tensor.empty(%[[DIM_THEN_1]])
-  // CHECK: %[[BCAST_ELSE:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map3, #map1]
-  //     CHECK-SAME: ins(%arg2 : tensor<1x1x8xi32>) outs(%[[INIT_ELSE]] : tensor<8x?x8xi32>)
-  // CHECK: %[[SHAPE_BCAST_THEN:.*]] = shape.shape_of %[[BCAST_THEN]]
-  // CHECK: %[[DIM_BCAST_THEN_1:.*]] = tensor.extract %[[SHAPE_BCAST_THEN]][%[[C1]]]
-  // CHECK: %[[INIT_RESULT:.*]] = tensor.empty(%[[DIM_BCAST_THEN_1]])
-  // CHECK: linalg.generic
-  //     CHECK-SAME: ins(%[[BCAST_PRED]], %[[BCAST_THEN]], %[[BCAST_ELSE]] : tensor<8x?x8xi1>, tensor<8x?x8xi32>, tensor<8x?x8xi32>) outs(%[[INIT_RESULT]] : tensor<8x?x8xi32>)
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<8x1x1xi1>, tensor<1x?x1xi32>, tensor<1x1x8xi32>) -> tensor<8x?x8xi32>
-  return %0: tensor<8x?x8xi32>
-}
-
-// -----
-// CHECK-LABEL: func.func @selectv2_broadcast_dyn_else
-func.func @selectv2_broadcast_dyn_else(%arg0: tensor<8x1x1xi1>, %arg1: tensor<1x8x1xi32>, %arg2: tensor<1x1x?xi32>) -> tensor<8x8x?xi32> {
-  // CHECK: %[[C2:.*]] = arith.constant 2 : index
-  // CHECK: %[[DIM_ELSE_2:.*]] = tensor.dim %arg2, %[[C2]]
-  // CHECK: %[[INIT_PRED:.*]] = tensor.empty(%[[DIM_ELSE_2]])
-  // CHECK: %[[BCAST_PRED:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map, #map1]
-  //     CHECK-SAME: ins(%arg0 : tensor<8x1x1xi1>) outs(%[[INIT_PRED]] : tensor<8x8x?xi1>)
-
-  // CHECK: %[[INIT_THEN:.*]] = tensor.empty(%[[DIM_ELSE_2]])
-  // CHECK: %[[BCAST_THEN:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map2, #map1]
-  //     CHECK-SAME: ins(%arg1 : tensor<1x8x1xi32>) outs(%[[INIT_THEN]] : tensor<8x8x?xi32>)
-  // CHECK: %[[INIT_ELSE:.*]] = tensor.empty(%[[DIM_ELSE_2]])
-  // CHECK: %[[BCAST_ELSE:.*]] = linalg.generic
-  //     CHECK-SAME: indexing_maps = [#map3, #map1]
-  //     CHECK-SAME: ins(%arg2 : tensor<1x1x?xi32>) outs(%[[INIT_ELSE]] : tensor<8x8x?xi32>)
-  // CHECK: %[[SHAPE_BCAST_THEN:.*]] = shape.shape_of %[[BCAST_THEN]]
-  // CHECK: %[[DIM_BCAST_THEN_1:.*]] = tensor.extract %[[SHAPE_BCAST_THEN]][%[[C2]]]
-  // CHECK: %[[INIT_RESULT:.*]] = tensor.empty(%[[DIM_BCAST_THEN_1]])
-  // CHECK: linalg.generic
-  //     CHECK-SAME: ins(%[[BCAST_PRED]], %[[BCAST_THEN]], %[[BCAST_ELSE]] : tensor<8x8x?xi1>, tensor<8x8x?xi32>, tensor<8x8x?xi32>) outs(%[[INIT_RESULT]] : tensor<8x8x?xi32>)
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<8x1x1xi1>, tensor<1x8x1xi32>, tensor<1x1x?xi32>) -> tensor<8x8x?xi32>
-  return %0: tensor<8x8x?xi32>
-}
-
-// -----
-// CHECK-LABEL: func.func @selectv2_broadcast_dyn_all
-func.func @selectv2_broadcast_dyn_all(%arg0: tensor<?x1x1xi1>, %arg1: tensor<?x8x1xi32>, %arg2: tensor<?x1x?xi32>) -> tensor<?x8x?xi32> {
-  // CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
-  // CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
-  // CHECK-DAG: %[[PRED_D0:.*]] = tensor.dim %arg0, %[[C0]] : tensor<?x1x1xi1>
-  // CHECK-DAG: %[[THEN_D0:.*]] = tensor.dim %arg1, %[[C0]] : tensor<?x8x1xi32>
-  // CHECK-DAG: %[[ELSE_D0:.*]] = tensor.dim %arg2, %[[C0]] : tensor<?x1x?xi32>
-  // CHECK-DAG: %[[ELSE_D2:.*]] = tensor.dim %arg2, %[[C2]] : tensor<?x1x?xi32>
-  // CHECK: %[[CMP_0:.*]] = arith.cmpi eq, %[[PRED_D0]], %[[THEN_D0]] : index
-  // CHECK: cf.assert %[[CMP_0]], "mismatched dynamic broadcast extents"
-  // CHECK: %[[CMP_1:.*]] = arith.cmpi eq, %[[PRED_D0]], %[[ELSE_D0]] : index
-  // CHECK: cf.assert %[[CMP_1]], "mismatched dynamic broadcast extents"
-  // Only two cf.asserts are needed. The rest are statically verified.
-  // CHECK-NOT: cf.assert
-  %0 = "chlo.broadcast_select"(%arg0, %arg1, %arg2) : (tensor<?x1x1xi1>, tensor<?x8x1xi32>, tensor<?x1x?xi32>) -> tensor<?x8x?xi32>
-  return %0: tensor<?x8x?xi32>
-}
-
-// -----
-// Note that broadcast_add is used as a proxy for all of the template
-// expansions. Tests below merely verify that the op has an expansion.
-// CHECK-LABEL: @andWithoutBroadcast
-func.func @andWithoutBroadcast(%arg0: tensor<4xi1>, %arg1: tensor<4xi1>) -> tensor<4xi1> {
-  // CHECK-NOT: mhlo.and
-  %0 = chlo.broadcast_and %arg0, %arg1 : (tensor<4xi1>, tensor<4xi1>) -> tensor<4xi1>
-  return %0 : tensor<4xi1>
-}
-
-// -----
-// CHECK-LABEL: @atan2WithoutBroadcast
-func.func @atan2WithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.atan2
-  %0 = chlo.broadcast_atan2 %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @compareWithoutBroadcast
-func.func @compareWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xi1> {
-  // CHECK-NOT: mhlo.compare
-  %0 = chlo.broadcast_compare %arg0, %arg1 {comparison_direction = #chlo<comparison_direction EQ>} : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xi1>
-  return %0 : tensor<4xi1>
-}
-
-// -----
-// CHECK-LABEL: @complexWithoutBroadcast
-func.func @complexWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> (tensor<4xf32>, tensor<4xf32>) {
-  // CHECK-NOT: mhlo.complex
-  // CHECK-NOT: chlo.broadcast_complex
-  %0 = chlo.broadcast_complex %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xcomplex<f32>>
-
-  %1 = "mhlo.real"(%0) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-
-  return %1, %2 : tensor<4xf32>, tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @divideWithoutBroadcast
-func.func @divideWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.divide
-  %0 = chlo.broadcast_divide %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @maximumWithoutBroadcast
-func.func @maximumWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.maximum
-  %0 = chlo.broadcast_maximum %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @minimumWithoutBroadcast
-func.func @minimumWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.minimum
-  %0 = chlo.broadcast_minimum %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @multiplyWithoutBroadcast
-func.func @multiplyWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.multiply
-  %0 = chlo.broadcast_multiply %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @orWithoutBroadcast
-func.func @orWithoutBroadcast(%arg0: tensor<4xi1>, %arg1: tensor<4xi1>) -> tensor<4xi1> {
-  // CHECK-NOT: mhlo.or
-  %0 = chlo.broadcast_or %arg0, %arg1 : (tensor<4xi1>, tensor<4xi1>) -> tensor<4xi1>
-  return %0 : tensor<4xi1>
-}
-
-// -----
-// CHECK-LABEL: @powerWithoutBroadcast
-func.func @powerWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.power
-  %0 = chlo.broadcast_power %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @remainderWithoutBroadcast
-func.func @remainderWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.remainder
-  %0 = chlo.broadcast_remainder %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @subWithoutBroadcast
-func.func @subWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // CHECK-NOT: mhlo.subtract
-  %0 = chlo.broadcast_subtract %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @xorWithoutBroadcast
-func.func @xorWithoutBroadcast(%arg0: tensor<4xi1>, %arg1: tensor<4xi1>) -> tensor<4xi1> {
-  // CHECK-NOT: mhlo.xor
-  %0 = chlo.broadcast_xor %arg0, %arg1 : (tensor<4xi1>, tensor<4xi1>) -> tensor<4xi1>
-  return %0 : tensor<4xi1>
-}
-
-// -----
-// CHECK-LABEL: @ZetaWithoutBroadcast
-func.func @ZetaWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>)
-    -> tensor<4xf32> {
-  // This is a composition: it should lower completely.
-  // CHECK-NOT: mhlo.
-  %0 = chlo.broadcast_zeta %arg0, %arg1
-      : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @PolygammaWithoutBroadcast
-// CHECK-SAME: (%[[LHS:.*]]: tensor<4xf32>, %[[RHS:.*]]: tensor<4xf32>)
-func.func @PolygammaWithoutBroadcast(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>)
-    -> tensor<4xf32> {
-  // This is a composition: it should lower completely.
-  // CHECK-NOT: mhlo.
-  %0 = chlo.broadcast_polygamma %arg0, %arg1
-      : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-
-// -----
-// CHECK-LABEL: @fallbackDynamicReshape
-func.func @fallbackDynamicReshape(%arg0 : tensor<4x?x3x?xui32>, %arg1 : tensor<5xindex>) -> tensor<12x?x?x1x?xui32> {
-  // CHECK-DAG: %[[C3:.*]] = arith.constant 3 : index
-  // CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index
-  // CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
-  // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-  // CHECK-DAG: %[[RESULT_D1:.*]] = tensor.extract %arg1[%[[C1]]] : tensor<5xindex>
-  // CHECK-DAG: %[[RESULT_D2:.*]] = tensor.extract %arg1[%[[C2]]] : tensor<5xindex>
-  // CHECK-DAG: %[[RESULT_D4:.*]] = tensor.extract %arg1[%[[C4]]] : tensor<5xindex>
-  // CHECK-DAG: %[[ARG_D1:.*]] = tensor.dim %arg0, %[[C1]] : tensor<4x?x3x?xi32>
-  // CHECK-DAG: %[[ARG_D3:.*]] = tensor.dim %arg0, %[[C3]] : tensor<4x?x3x?xi32>
-  // CHECK-DAG: %[[RESULT:.*]] = flow.tensor.reshape %arg0 : tensor<4x?x3x?xi32>{%[[ARG_D1]], %[[ARG_D3]]} -> tensor<12x?x?x1x?xi32>{%[[RESULT_D1]], %[[RESULT_D2]], %[[RESULT_D4]]}
-  %0 = "mhlo.dynamic_reshape"(%arg0, %arg1) : (tensor<4x?x3x?xui32>, tensor<5xindex>) -> tensor<12x?x?x1x?xui32>
-  // CHECK: return %[[RESULT]]
-  return %0 : tensor<12x?x?x1x?xui32>
-}
-
-// -----
-// CHECK-LABEL: @fallbackDynamicReshapeInt
-func.func @fallbackDynamicReshapeInt(%arg0 : tensor<4x?x3x?xui32>, %arg1 : tensor<5xi32>) -> tensor<12x?x?x1x?xui32> {
-  // CHECK-DAG: %[[C3:.*]] = arith.constant 3 : index
-  // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
-  // CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
-  // CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index
-  // CHECK-DAG: %[[D1:.*]] = tensor.extract %arg1[%[[C1]]] : tensor<5xi32>
-  // CHECK-DAG: %[[D2:.*]] = tensor.extract %arg1[%[[C2]]] : tensor<5xi32>
-  // CHECK-DAG: %[[D4:.*]] = tensor.extract %arg1[%[[C4]]] : tensor<5xi32>
-  // CHECK-DAG: %[[RESULT_D1:.*]] = arith.index_cast %[[D1]] : i32 to index
-  // CHECK-DAG: %[[RESULT_D2:.*]] = arith.index_cast %[[D2]] : i32 to index
-  // CHECK-DAG: %[[RESULT_D4:.*]] = arith.index_cast %[[D4]] : i32 to index
-  // CHECK-DAG: %[[ARG_D1:.*]] = tensor.dim %arg0, %[[C1]] : tensor<4x?x3x?xi32>
-  // CHECK-DAG: %[[ARG_D3:.*]] = tensor.dim %arg0, %[[C3]] : tensor<4x?x3x?xi32>
-  // CHECK-DAG: %[[RESULT:.*]] = flow.tensor.reshape %arg0 : tensor<4x?x3x?xi32>{%[[ARG_D1]], %[[ARG_D3]]} -> tensor<12x?x?x1x?xi32>{%[[RESULT_D1]], %[[RESULT_D2]], %[[RESULT_D4]]}
-  %0 = "mhlo.dynamic_reshape"(%arg0, %arg1) : (tensor<4x?x3x?xui32>, tensor<5xi32>) -> tensor<12x?x?x1x?xui32>
-  // CHECK: return %[[RESULT]]
-  return %0 : tensor<12x?x?x1x?xui32>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_collective_ops.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_collective_ops.mlir
deleted file mode 100644
index 14cd307..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_collective_ops.mlir
+++ /dev/null
@@ -1,658 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors --canonicalize -cse %s | FileCheck %s
-
-// CHECK-LABEL: @replica_id
-func.func @replica_id() -> tensor<ui32> {
-  // CHECK-DAG: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK-DAG: %[[RANK:.+]] = flow.channel.rank %[[CHANNEL]] : index
-  // CHECK-DAG: %[[CAST:.+]] = arith.index_castui %[[RANK]] : index to i32
-  // CHECK-DAG: %[[TENSOR:.+]] = tensor.from_elements %[[CAST]] : tensor<i32>
-  // CHECK-DAG: return %[[TENSOR]] : tensor<i32>
-  %id = mhlo.replica_id : tensor<ui32>
-  return %id : tensor<ui32>
-}
-
-// -----
-
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @replica_id_with_partitions
-  func.func @replica_id_with_partitions() -> tensor<ui32> {
-    // CHECK-DAG: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-    // CHECK-DAG: %[[RANK:.+]] = flow.channel.rank %[[CHANNEL]] : index
-    // CHECK-DAG: %[[DIV2:.+]] = arith.divui %[[RANK]], %c2 : index
-    // CHECK-DAG: %[[CAST:.+]] = arith.index_castui %[[DIV2]] : index to i32
-    // CHECK-DAG: %[[TENSOR:.+]] = tensor.from_elements %[[CAST]] : tensor<i32>
-    // CHECK-DAG: return %[[TENSOR]] : tensor<i32>
-    %id = mhlo.replica_id : tensor<ui32>
-    return %id : tensor<ui32>
-  }
-}
-
-// -----
-
-// Returns 0 since num_partitions is not set.
-
-// CHECK-LABEL: @partition_id
-func.func @partition_id() -> tensor<ui32> {
-  // CHECK-DAG: %[[CST0:.+]] = arith.constant dense<0> : tensor<i32>
-  // CHECK-DAG: return %[[CST0]] : tensor<i32>
-  %id = mhlo.partition_id : tensor<ui32>
-  return %id : tensor<ui32>
-}
-
-// -----
-
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @partition_id_with_partitions
-  func.func @partition_id_with_partitions() -> tensor<ui32> {
-    // CHECK-DAG: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-    // CHECK-DAG: %[[RANK:.+]] = flow.channel.rank %[[CHANNEL]] : index
-    // CHECK-DAG: %[[REM2:.+]] = arith.remui %[[RANK]], %c2 : index
-    // CHECK-DAG: %[[CAST:.+]] = arith.index_castui %[[REM2]] : index to i32
-    // CHECK-DAG: %[[TENSOR:.+]] = tensor.from_elements %[[CAST]] : tensor<i32>
-    // CHECK-DAG: return %[[TENSOR]] : tensor<i32>
-    %id = mhlo.partition_id : tensor<ui32>
-    return %id : tensor<ui32>
-  }
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_sum
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xf32>)
-func.func @all_reduce_sum(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce sum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xf32>
-  // CHECK: return %[[OP]] : tensor<2304xf32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-      mhlo.return %sum : tensor<f32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-        use_global_device_ids} : (tensor<2304xf32>) -> tensor<2304xf32>
-  return %out : tensor<2304xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_sum_uint
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xi32>
-func.func @all_reduce_sum_uint(%input : tensor<2304xui32>) -> tensor<2304xui32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce sum, ui32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xi32>, tensor<2304xi32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xi32>
-  // CHECK: return %[[OP]] : tensor<2304xi32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<ui32>, %arg1: tensor<ui32>):
-      %sum = mhlo.add %arg0, %arg1 : tensor<ui32>
-      mhlo.return %sum : tensor<ui32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-        use_global_device_ids} : (tensor<2304xui32>) -> tensor<2304xui32>
-  return %out : tensor<2304xui32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_product
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xf32>)
-func.func @all_reduce_product(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce product, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xf32>
-  // CHECK: return %[[OP]] : tensor<2304xf32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %mul = mhlo.multiply %arg0, %arg1 : tensor<f32>
-      mhlo.return %mul : tensor<f32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-        use_global_device_ids} : (tensor<2304xf32>) -> tensor<2304xf32>
-  return %out : tensor<2304xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_minimum
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xf32>)
-func.func @all_reduce_minimum(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce minimum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xf32>
-  // CHECK: return %[[OP]] : tensor<2304xf32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %mul = mhlo.minimum %arg0, %arg1 : tensor<f32>
-      mhlo.return %mul : tensor<f32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-        use_global_device_ids} : (tensor<2304xf32>) -> tensor<2304xf32>
-  return %out : tensor<2304xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_maximum
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xf32>)
-func.func @all_reduce_maximum(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce maximum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xf32>
-  // CHECK: return %[[OP]] : tensor<2304xf32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %mul = mhlo.maximum %arg0, %arg1 : tensor<f32>
-      mhlo.return %mul : tensor<f32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-        use_global_device_ids} : (tensor<2304xf32>) -> tensor<2304xf32>
-  return %out : tensor<2304xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_maximum_optional_attrs
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2304xf32>)
-func.func @all_reduce_maximum_optional_attrs(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2304xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce maximum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2304xf32>
-  // CHECK: return %[[OP]] : tensor<2304xf32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %mul = mhlo.maximum %arg0, %arg1 : tensor<f32>
-      mhlo.return %mul : tensor<f32>
-    }) {replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>} : (tensor<2304xf32>) -> tensor<2304xf32>
-  return %out : tensor<2304xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_reduce_sum_with_groups
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2x4xi32>)
-func.func @all_reduce_sum_with_groups(%input : tensor<2x4xi32>) -> tensor<2x4xi32> {
-  // CHECK: %[[BASE_CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[BASE_RANK:.+]] = flow.channel.rank %[[BASE_CHANNEL]]
-  // CHECK: %[[SPLIT_COLOR:.+]] = util.switch index from [%c0, %c1] at %[[BASE_RANK]] else %c-1
-  // CHECK: %[[SPLIT_KEY:.+]] = util.switch index from [%c0, %c0] at %[[BASE_RANK]] else %c-1
-  // CHECK: %[[SPLIT_CHANNEL:.+]] = flow.channel.split %[[BASE_CHANNEL]], %[[SPLIT_COLOR]], %[[SPLIT_KEY]] : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2x4xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_reduce sum, ui32, %[[EMPTY]], %[[ARG0]], %[[SPLIT_CHANNEL]] : (tensor<2x4xi32>, tensor<2x4xi32>, !flow.channel) -> %[[EMPTY]] as tensor<2x4xi32>
-  // CHECK: return %[[OP]] : tensor<2x4xi32>
-  %out = "mhlo.all_reduce"(%input) ({
-    ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):
-      %sum = mhlo.add %arg0, %arg1 : tensor<i32>
-      mhlo.return %sum : tensor<i32>
-    }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-        replica_groups = dense<[[0], [1]]> : tensor<2x1xi64>,
-        use_global_device_ids} : (tensor<2x4xi32>) -> tensor<2x4xi32>
-  return %out : tensor<2x4xi32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_gather_dim_0
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<512xf32>) -> tensor<1024xf32>
-func.func @all_gather_dim_0(%input : tensor<512xf32>) -> tensor<1024xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1024xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_gather f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<1024xf32>, tensor<512xf32>, !flow.channel) -> %[[EMPTY]] as tensor<1024xf32>
-  // CHECK: return %[[OP]] : tensor<1024xf32>
-  %out = "mhlo.all_gather"(%input) {all_gather_dim = 0 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-     use_global_device_ids} : (tensor<512xf32>) -> tensor<1024xf32>
-  return %out : tensor<1024xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_gather_dim_0_uint
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<512xi32>
-func.func @all_gather_dim_0_uint(%input : tensor<512xui32>) -> tensor<1024xui32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1024xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_gather ui32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<1024xi32>, tensor<512xi32>, !flow.channel) -> %[[EMPTY]] as tensor<1024xi32>
-  // CHECK: return %[[OP]] : tensor<1024xi32>
-  %out = "mhlo.all_gather"(%input) {all_gather_dim = 0 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-     use_global_device_ids} : (tensor<512xui32>) -> tensor<1024xui32>
-  return %out : tensor<1024xui32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_gather_dim_1
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2x2xf32>) -> tensor<2x4xf32>
-func.func @all_gather_dim_1(%input : tensor<2x2xf32>) -> tensor<2x4xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: tensor.empty() : tensor<2x2xf32>
-  // CHECK: %[[TRANSPOSE_ARG:.+]] = linalg.generic
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x2xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_gather f32, %[[EMPTY]], %[[TRANSPOSE_ARG]], %[[CHANNEL]]  : (tensor<4x2xf32>, tensor<2x2xf32>, !flow.channel) -> %[[EMPTY]] as tensor<4x2xf32>
-  // CHECK: tensor.empty() : tensor<2x4xf32>
-  // CHECK: %[[TRANSPOSE_OUT:.+]] = linalg.generic
-  // CHECK: return %[[TRANSPOSE_OUT]] : tensor<2x4xf32>
-  %out = "mhlo.all_gather"(%input) {all_gather_dim = 1 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-     use_global_device_ids} : (tensor<2x2xf32>) -> tensor<2x4xf32>
-  return %out : tensor<2x4xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_gather_dim_0_optional_attrs
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<512xf32>) -> tensor<1024xf32>
-func.func @all_gather_dim_0_optional_attrs(%input : tensor<512xf32>) -> tensor<1024xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1024xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_gather f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<1024xf32>, tensor<512xf32>, !flow.channel) -> %[[EMPTY]] as tensor<1024xf32>
-  // CHECK: return %[[OP]] : tensor<1024xf32>
-  %out = "mhlo.all_gather"(%input) {all_gather_dim = 0 : i64,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<512xf32>) -> tensor<1024xf32>
-  return %out : tensor<1024xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_split_concat_same
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<1024xf32>) -> tensor<1024xf32>
-func.func @all_to_all_split_concat_same(%input : tensor<1024xf32>) -> tensor<1024xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1024xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<1024xf32>, tensor<1024xf32>, !flow.channel) -> %[[EMPTY]] as tensor<1024xf32>
-  // CHECK: return %[[OP]] : tensor<1024xf32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 0 : i64,
-     concat_dimension = 0 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<1024xf32>) -> tensor<1024xf32>
-  return %out : tensor<1024xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_split_concat_same_uint
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<1024xi32>
-func.func @all_to_all_split_concat_same_uint(%input : tensor<1024xui32>) -> tensor<1024xui32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1024xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all ui32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<1024xi32>, tensor<1024xi32>, !flow.channel) -> %[[EMPTY]] as tensor<1024xi32>
-  // CHECK: return %[[OP]] : tensor<1024xi32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 0 : i64,
-     concat_dimension = 0 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<1024xui32>) -> tensor<1024xui32>
-  return %out : tensor<1024xui32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_split_concat_same_dim_1
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2x4xf32>) -> tensor<2x4xf32>
-func.func @all_to_all_split_concat_same_dim_1(%input : tensor<2x4xf32>) -> tensor<2x4xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x2xf32>
-  // CHECK: %[[TRANSPOSE_ARG:.+]] = linalg.generic
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all f32, %[[EMPTY]], %[[TRANSPOSE_ARG]], %[[CHANNEL]]  : (tensor<4x2xf32>, tensor<4x2xf32>, !flow.channel) -> %[[EMPTY]] as tensor<4x2xf32>
-  // CHECK: %[[TRANSPOSE_OUT:.+]] = linalg.generic
-  // CHECK: return %[[TRANSPOSE_OUT]] : tensor<2x4xf32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 1 : i64,
-     concat_dimension = 1 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<2x4xf32>) -> tensor<2x4xf32>
-  return %out : tensor<2x4xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_split_dim_0
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x4xf32>) -> tensor<2x8xf32>
-func.func @all_to_all_split_dim_0(%input : tensor<4x4xf32>) -> tensor<2x8xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x4xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<4x4xf32>, tensor<4x4xf32>, !flow.channel) -> %[[EMPTY]] as tensor<4x4xf32>
-  // CHECK: %[[REARRANGE_RESHAPE:.+]] = tensor.expand_shape %[[OP]] {{\[}}[0, 1], [2]] : tensor<4x4xf32> into tensor<2x2x4xf32>
-  // CHECK: %[[REARRANGE_TRANSPOSE:.+]] = linalg.generic
-  // CHECK: %[[RESHAPE_OUT:.+]] = tensor.collapse_shape %[[REARRANGE_TRANSPOSE]] {{\[}}[0], [1, 2]] : tensor<2x2x4xf32> into tensor<2x8xf32>
-  // CHECK: return %[[RESHAPE_OUT]] : tensor<2x8xf32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 0 : i64,
-     concat_dimension = 1 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<4x4xf32>) -> tensor<2x8xf32>
-  return %out : tensor<2x8xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_split_dim_1
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x4xf32>) -> tensor<8x2xf32>
-func.func @all_to_all_split_dim_1(%input : tensor<4x4xf32>) -> tensor<8x2xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x4xf32>
-  // CHECK: %[[TRANSPOSE_ARG:.+]] = linalg.generic
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all f32, %[[EMPTY]], %[[TRANSPOSE_ARG]], %[[CHANNEL]]  : (tensor<4x4xf32>, tensor<4x4xf32>, !flow.channel) -> %[[EMPTY]] as tensor<4x4xf32>
-  // CHECK: %[[TRANSPOSE_OUT:.+]] = linalg.generic
-  // CHECK: %[[REARRANGE_RESHAPE1:.+]] = tensor.expand_shape %[[TRANSPOSE_OUT]] {{\[}}[0], [1, 2]] : tensor<4x4xf32> into tensor<4x2x2xf32>
-  // CHECK: %[[EMPTY2:.+]] = tensor.empty() : tensor<2x4x2xf32>
-  // CHECK: %[[REARRANGE_TRANSPOSE:.+]] = linalg.generic
-  // CHECK: %[[REARRANGE_RESHAPE2:.+]] = tensor.collapse_shape %[[REARRANGE_TRANSPOSE]] {{\[}}[0, 1], [2]] : tensor<2x4x2xf32> into tensor<8x2xf32>
-  // CHECK: return %[[REARRANGE_RESHAPE2]] : tensor<8x2xf32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 1 : i64,
-     concat_dimension = 0 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<4x4xf32>) -> tensor<8x2xf32>
-  return %out : tensor<8x2xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @all_to_all_3d_split_dim_1
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x4x4xf32>) -> tensor<4x2x8xf32>
-func.func @all_to_all_3d_split_dim_1(%input : tensor<4x4x4xf32>) -> tensor<4x2x8xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x4x4xf32>
-  // CHECK: %[[TRANSPOSE_ARG:.+]] = linalg.generic
-  // CHECK: %[[OP:.+]] = flow.collective.all_to_all f32, %[[EMPTY]], %[[TRANSPOSE_ARG]], %[[CHANNEL]]  : (tensor<4x4x4xf32>, tensor<4x4x4xf32>, !flow.channel) -> %[[EMPTY]] as tensor<4x4x4xf32>
-  // CHECK: %[[TRANSPOSE_OUT:.+]] = linalg.generic
-  // CHECK: %[[REARRANGE_RESHAPE1:.+]] = tensor.expand_shape %[[TRANSPOSE_OUT]] {{\[}}[0], [1, 2], [3]] : tensor<4x4x4xf32> into tensor<4x2x2x4xf32>
-  // CHECK: %[[EMPTY_1:.+]] = tensor.empty() : tensor<4x2x2x4xf32>
-  // CHECK: %[[REARRANGE_TRANSPOSE:.+]] = linalg.generic
-  // CHECK: %[[REARRANGE_RESHAPE2:.+]] = tensor.collapse_shape %[[REARRANGE_TRANSPOSE]] {{\[}}[0], [1], [2, 3]] : tensor<4x2x2x4xf32> into tensor<4x2x8xf32>
-  // CHECK: return %[[REARRANGE_RESHAPE2]] : tensor<4x2x8xf32>
-  %out = "mhlo.all_to_all"(%input) {
-     split_dimension = 1 : i64,
-     concat_dimension = 2 : i64,
-     split_count = 2 : i64,
-     channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-     replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<4x4x4xf32>) -> tensor<4x2x8xf32>
-  return %out : tensor<4x2x8xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @reduce_scatter_dim_0
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x2xf32>) -> tensor<2x2xf32>
-func.func @reduce_scatter_dim_0(%input : tensor<4x2xf32>) -> tensor<2x2xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2x2xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.reduce_scatter sum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2x2xf32>, tensor<4x2xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2x2xf32>
-  // CHECK: return %[[OP]] : tensor<2x2xf32>
-  %out = "mhlo.reduce_scatter"(%input) ({
-  ^bb0(%arg0: tensor<f32> , %arg1: tensor<f32>) :
-    %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-    mhlo.return %sum : tensor<f32>
-  }) {scatter_dimension = 0 : i64,
-      channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-      use_global_device_ids} : (tensor<4x2xf32>) -> tensor<2x2xf32>
-  return %out : tensor<2x2xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @reduce_scatter_dim_0_uint
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x2xi32>
-func.func @reduce_scatter_dim_0_uint(%input : tensor<4x2xui32>) -> tensor<2x2xui32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2x2xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.reduce_scatter sum, ui32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2x2xi32>, tensor<4x2xi32>, !flow.channel) -> %[[EMPTY]] as tensor<2x2xi32>
-  // CHECK: return %[[OP]] : tensor<2x2xi32>
-  %out = "mhlo.reduce_scatter"(%input) ({
-  ^bb0(%arg0: tensor<ui32> , %arg1: tensor<ui32>) :
-    %sum = mhlo.add %arg0, %arg1 : tensor<ui32>
-    mhlo.return %sum : tensor<ui32>
-  }) {scatter_dimension = 0 : i64,
-      channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-      use_global_device_ids} : (tensor<4x2xui32>) -> tensor<2x2xui32>
-  return %out : tensor<2x2xui32>
-}
-
-// -----
-
-// CHECK-LABEL: @reduce_scatter_dim_1
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<2x4xf32>) -> tensor<2x2xf32>
-func.func @reduce_scatter_dim_1(%input : tensor<2x4xf32>) -> tensor<2x2xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: tensor.empty() : tensor<4x2xf32>
-  // CHECK: %[[TRANSPOSE_ARG:.+]] = linalg.generic
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2x2xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.reduce_scatter sum, f32, %[[EMPTY]], %[[TRANSPOSE_ARG]], %[[CHANNEL]]  : (tensor<2x2xf32>, tensor<4x2xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2x2xf32>
-  // CHECK: %[[TRANSPOSE_OUT:.+]] = linalg.generic
-  // CHECK: return %[[TRANSPOSE_OUT]] : tensor<2x2xf32>
-  %out = "mhlo.reduce_scatter"(%input) ({
-  ^bb0(%arg0: tensor<f32> , %arg1: tensor<f32>) :
-    %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-    mhlo.return %sum : tensor<f32>
-  }) {scatter_dimension = 1 : i64,
-      channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
-      use_global_device_ids} : (tensor<2x4xf32>) -> tensor<2x2xf32>
-  return %out : tensor<2x2xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @reduce_scatter_dim_0_optional_attrs
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<4x2xf32>) -> tensor<2x2xf32>
-func.func @reduce_scatter_dim_0_optional_attrs(%input : tensor<4x2xf32>) -> tensor<2x2xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<2x2xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.reduce_scatter sum, f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]]  : (tensor<2x2xf32>, tensor<4x2xf32>, !flow.channel) -> %[[EMPTY]] as tensor<2x2xf32>
-  // CHECK: return %[[OP]] : tensor<2x2xf32>
-  %out = "mhlo.reduce_scatter"(%input) ({
-  ^bb0(%arg0: tensor<f32> , %arg1: tensor<f32>) :
-    %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-    mhlo.return %sum : tensor<f32>
-  }) {scatter_dimension = 0 : i64,
-      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<4x2xf32>) -> tensor<2x2xf32>
-  return %out : tensor<2x2xf32>
-}
-
-// -----
-
-// flattened_ids: channel_id > 0 && use_global_device_ids = true
-module @jit_fn attributes {mhlo.num_partitions = 1 : i32, mhlo.num_replicas = 8 : i32 } {
-  // CHECK-LABEL: @flattened_ids
-  // CHECK-SAME: ([[ARG0:%.+]]: tensor<2304xf32>)
-  func.func @flattened_ids(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-    // CHECK: [[CHANNEL:%.+]] = flow.channel.default : !flow.channel
-    // CHECK: [[EMPTY:%.+]] = tensor.empty() : tensor<2304xf32>
-    // CHECK: [[ALLREDUCE:%.+]] = flow.collective.all_reduce sum, f32, [[EMPTY]], [[ARG0]], [[CHANNEL]] : (tensor<2304xf32>, tensor<2304xf32>, !flow.channel) -> [[EMPTY]] as tensor<2304xf32>
-    // CHECK: return [[ALLREDUCE]] : tensor<2304xf32>
-    %out = "mhlo.all_reduce"(%input) ({
-      ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-        %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-        mhlo.return %sum : tensor<f32>
-      }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-          replica_groups = dense<[[0, 1, 2, 3, 4, 5, 6, 7]]> : tensor<1x8xi64>,
-          use_global_device_ids} : (tensor<2304xf32>) -> tensor<2304xf32>
-    return %out : tensor<2304xf32>
-  }
-}
-
-// -----
-
-// cross-replica: channel_id <= 0 && use_global_device_ids = false
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @cross_replica
-  func.func @cross_replica(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-    // Cross replica should form groups (0,2,4,6),(1,3,5,7), where each number represents a cell below.
-    // +---+---+
-    // | 0 | 1 |
-    // | 2 | 3 |
-    // | 4 | 5 |
-    // | 6 | 7 |
-    // +---+---+
-    //                          rank:   0    1    2    3    4    5    6    7
-    // CHECK: util.switch index from [%c0, %c1, %c0, %c1, %c0, %c1, %c0, %c1] at %channel_rank else %c-1 : index
-    // CHECK: util.switch index from [%c0, %c0, %c1, %c1, %c2, %c2, %c3, %c3] at %channel_rank else %c-1 : index
-    %out = "mhlo.all_reduce"(%input) ({
-      ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-        %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-        mhlo.return %sum : tensor<f32>
-      }) {channel_handle = #mhlo.channel_handle<handle = 0, type = 1>,
-          replica_groups = dense<[[0, 1, 2, 3]]> : tensor<1x4xi64>
-         } : (tensor<2304xf32>) -> tensor<2304xf32>
-    return %out : tensor<2304xf32>
-  }
-}
-
-// -----
-
-// cross_replica_and_partition: channel_id > 0 && use_global_device_ids = false
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @cross_replica_and_partition
-  func.func @cross_replica_and_partition(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-    // Cross replica_and_partition should form groups (0,2,1,3),(4,6,5,7), where each number represents a cell below.
-    // Note that the rank is assigned in a partiton first, e.g., rank 0 and 1 are assigned to cell 0 and 2, respectively.
-    // +---+---+
-    // | 0   1 |
-    // | 2   3 |
-    // |---+---|
-    // | 4   5 |
-    // | 6   7 |
-    // +---+---+
-    //                          rank:   0    1    2    3    4    5    6    7
-    // CHECK: util.switch index from [%c0, %c0, %c0, %c0, %c1, %c1, %c1, %c1] at %channel_rank else %c-1 : index
-    // CHECK: util.switch index from [%c0, %c2, %c1, %c3, %c0, %c2, %c1, %c3] at %channel_rank else %c-1 : index
-    %out = "mhlo.all_reduce"(%input) ({
-      ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-        %sum = mhlo.add %arg0, %arg1 : tensor<f32>
-        mhlo.return %sum : tensor<f32>
-      }) {channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-          replica_groups = dense<[[0, 1], [2, 3]]> : tensor<2x2xi64>
-         } : (tensor<2304xf32>) -> tensor<2304xf32>
-    return %out : tensor<2304xf32>
-  }
-}
-
-// -----
-
-// cross_partition: channel_id > 0
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @cross_partition
-  func.func @cross_partition(%input : tensor<2304xf32>) -> tensor<2304xf32> {
-    // Cross partition should form groups (0,1),(2,3),(4,5),(6,7) where each number represents a cell below.
-    // +---+---+
-    // | 0   1 |
-    // +---+---+
-    // | 2   3 |
-    // +---+---+
-    // | 4   5 |
-    // +---+---+
-    // | 6   7 |
-    // +---+---+
-    //                          rank:   0    1    2    3    4    5    6    7
-    // CHECK: util.switch index from [%c0, %c0, %c1, %c1, %c2, %c2, %c3, %c3] at %channel_rank else %c-1 : index
-    // CHECK: util.switch index from [%c0, %c1, %c0, %c1, %c0, %c1, %c0, %c1] at %channel_rank else %c-1 : index
-    %out = "mhlo.all_to_all"(%input) {
-      split_dimension = 0 : i64,
-      concat_dimension = 0 : i64,
-      split_count = 2 : i64,
-      channel_handle = #mhlo.channel_handle<handle = 1, type = 1>,
-      replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>} : (tensor<2304xf32>) -> tensor<2304xf32>
-    return %out : tensor<2304xf32>
-  }
-}
-
-// -----
-
-// CHECK-LABEL: @collective_permute
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<8xf32>) -> tensor<8xf32>
-func.func @collective_permute(%input : tensor<8xf32>) -> tensor<8xf32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[RANK:.+]] = flow.channel.rank %[[CHANNEL]] : index
-  // CHECK: %[[SEND:.+]] = util.switch index from [%c1, %c2, %c3, %c0] at %[[RANK]] else %c-1
-  // CHECK: %[[RECV:.+]] = util.switch index from [%c3, %c0, %c1, %c2] at %[[RANK]] else %c-1
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<8xf32>
-  // CHECK: %[[OP:.+]] = flow.collective.send_recv f32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]], %[[SEND]], %[[RECV]] : (tensor<8xf32>, tensor<8xf32>, !flow.channel, index, index) -> %[[EMPTY]] as tensor<8xf32>
-  // CHECK: return %[[OP]] : tensor<8xf32>
-  %out = "mhlo.collective_permute"(%input) {
-        source_target_pairs = dense<[[0, 1], [1, 2], [2, 3], [3, 0]]> : tensor<4x2xi64>,
-        channel_handle = #mhlo.channel_handle<handle = 1, type = 1>} : (tensor<8xf32>) -> tensor<8xf32>
-  return %out : tensor<8xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @collective_permute_uint
-// CHECK-SAME: (%[[ARG0:.+]]: tensor<8xi32>
-func.func @collective_permute_uint(%input : tensor<8xui32>) -> tensor<8xui32> {
-  // CHECK: %[[CHANNEL:.+]] = flow.channel.default : !flow.channel
-  // CHECK: %[[RANK:.+]] = flow.channel.rank %[[CHANNEL]] : index
-  // CHECK: %[[SEND:.+]] = util.switch index from [%c1, %c2, %c3, %c0] at %[[RANK]] else %c-1
-  // CHECK: %[[RECV:.+]] = util.switch index from [%c3, %c0, %c1, %c2] at %[[RANK]] else %c-1
-  // CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<8xi32>
-  // CHECK: %[[OP:.+]] = flow.collective.send_recv ui32, %[[EMPTY]], %[[ARG0]], %[[CHANNEL]], %[[SEND]], %[[RECV]] : (tensor<8xi32>, tensor<8xi32>, !flow.channel, index, index) -> %[[EMPTY]] as tensor<8xi32>
-  // CHECK: return %[[OP]] : tensor<8xi32>
-  %out = "mhlo.collective_permute"(%input) {
-        source_target_pairs = dense<[[0, 1], [1, 2], [2, 3], [3, 0]]> : tensor<4x2xi64>,
-        channel_handle = #mhlo.channel_handle<handle = 1, type = 1>} : (tensor<8xui32>) -> tensor<8xui32>
-  return %out : tensor<8xui32>
-}
-
-// -----
-
-// collective_permute cross_replica: channel_id <= 0
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @collective_permute_cross_replica
-  func.func @collective_permute_cross_replica(%input : tensor<8xf32>) -> tensor<8xf32> {
-    // Cross replica should form groups (0,2,4,6),(1,3,5,7) where each number represents a cell below.
-    // +---+---+
-    // | 0 | 1 |
-    // |   |   |
-    // | 2 | 3 |
-    // |   |   |
-    // | 4 | 5 |
-    // |   |   |
-    // | 6 | 7 |
-    // +---+---+
-    //                          rank:   0    1    2    3    4    5    6    7
-    // CHECK: util.switch index from [%c0, %c1, %c0, %c1, %c0, %c1, %c0, %c1] at %channel_rank else %c-1 : index
-    // CHECK: util.switch index from [%c0, %c0, %c1, %c1, %c2, %c2, %c3, %c3] at %channel_rank else %c-1 : index
-    %out = "mhlo.collective_permute"(%input) {
-          source_target_pairs = dense<[[0, 1], [1, 2], [2, 3], [3, 0]]> : tensor<4x2xi64>,
-          channel_handle = #mhlo.channel_handle<handle = 0, type = 1>} : (tensor<8xf32>) -> tensor<8xf32>
-    return %out : tensor<8xf32>
-  }
-}
-
-// -----
-
-// collective_permute cross_partition: channel_id > 0
-module @jit_fn attributes {mhlo.num_partitions = 2 : i32, mhlo.num_replicas = 4 : i32 } {
-  // CHECK-LABEL: @collective_permute_cross_partition
-  func.func @collective_permute_cross_partition(%input : tensor<8xf32>) -> tensor<8xf32> {
-    // Cross partition should form groups (0,1),(2,3),(4,5),(6,7) where each number represents a cell below.
-    // +---+---+
-    // | 0   1 |
-    // +---+---+
-    // | 2   3 |
-    // |---+---|
-    // | 4   5 |
-    // +---+---+
-    // | 6   7 |
-    // +---+---+
-    //                          rank:   0    1    2    3    4    5    6    7
-    // CHECK: util.switch index from [%c0, %c0, %c1, %c1, %c2, %c2, %c3, %c3] at %channel_rank else %c-1 : index
-    // CHECK: util.switch index from [%c0, %c1, %c0, %c1, %c0, %c1, %c0, %c1] at %channel_rank else %c-1 : index
-    %out = "mhlo.collective_permute"(%input) {
-          source_target_pairs = dense<[[0, 1]]> : tensor<1x2xi64>,
-          channel_handle = #mhlo.channel_handle<handle = 1, type = 1>} : (tensor<8xf32>) -> tensor<8xf32>
-    return %out : tensor<8xf32>
-  }
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_complex_to_real.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_complex_to_real.mlir
deleted file mode 100644
index 7c32f47..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_complex_to_real.mlir
+++ /dev/null
@@ -1,147 +0,0 @@
-// RUN: iree-opt --iree-test-mhlo-convert-complex-to-real %s | FileCheck %s
-
-// CHECK-LABEL: @add
-func.func @add(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>, %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xf32>, tensor<2xf32>) {
-  %2 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %3 = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: [[VAL0:%.+]] = mhlo.add %arg0, %arg2
-  // CHECK-DAG: [[VAL1:%.+]] = mhlo.add %arg1, %arg3
-  %4 = "mhlo.add"(%2, %3) : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> (tensor<2xcomplex<f32>>)
-  %5 = mhlo.real %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-  %6 = mhlo.imag %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: return [[VAL0]], [[VAL1]]
-  return %5, %6 : tensor<2xf32>, tensor<2xf32>
-}
-
-// CHECK-LABEL: @sub
-func.func @sub(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>, %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xf32>, tensor<2xf32>) {
-  %2 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %3 = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: [[VAL0:%.+]] = mhlo.subtract %arg0, %arg2
-  // CHECK-DAG: [[VAL1:%.+]] = mhlo.subtract %arg1, %arg3
-  %4 = "mhlo.subtract"(%2, %3) : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> (tensor<2xcomplex<f32>>)
-  %5 = mhlo.real %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-  %6 = mhlo.imag %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: return [[VAL0]], [[VAL1]]
-  return %5, %6 : tensor<2xf32>, tensor<2xf32>
-}
-
-// CHECK-LABEL: @mul
-func.func @mul(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>, %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xf32>, tensor<2xf32>) {
-  %2 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %3 = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: %[[VAL0:.+]] = chlo.broadcast_multiply %arg0, %arg2
-  // CHECK-DAG: %[[VAL1:.+]] = chlo.broadcast_multiply %arg1, %arg3
-  // CHECK-DAG: %[[VAL2:.+]] = mhlo.subtract %[[VAL0]], %[[VAL1]]
-  // CHECK-DAG: %[[VAL3:.+]] = chlo.broadcast_multiply %arg0, %arg3
-  // CHECK-DAG: %[[VAL4:.+]] = chlo.broadcast_multiply %arg1, %arg2
-  // CHECK-DAG: %[[VAL5:.+]] = mhlo.add %[[VAL3]], %[[VAL4]]
-  %4 = "mhlo.multiply"(%2, %3) : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> (tensor<2xcomplex<f32>>)
-  %5 = mhlo.real %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-  %6 = mhlo.imag %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: return %2, %5 : tensor<2xf32>, tensor<2xf32>
-  return %5, %6 : tensor<2xf32>, tensor<2xf32>
-}
-
-// CHECK-LABEL: @div
-func.func @div(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>, %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xf32>, tensor<2xf32>) {
-  %2 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %3 = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: %[[VAL0:.+]] = mhlo.negate %arg3
-
-  // Compute the numerator's real component:
-  //   numerator.real = lhs.real * rhs.real  lhs.imag * rhs.imag
-  // CHECK-DAG: %[[VAL1:.+]] = chlo.broadcast_multiply %arg0, %arg2
-  // CHECK-DAG: %[[VAL2:.+]] = chlo.broadcast_multiply %arg1, %[[VAL0]]
-  // CHECK-DAG: %[[VAL3:.+]] = mhlo.subtract %[[VAL1]], %[[VAL2]]
-
-  // Compute the real valued denominator as rhs * con(rhs):
-  //   denominator = rhs.real * rhs.real + rhs.imag * rhs.imag
-  // CHECK-DAG: %[[VAL4:.+]] = mhlo.multiply %arg2, %arg2
-  // CHECK-DAG: %[[VAL5:.+]] = mhlo.multiply %arg3, %arg3
-  // CHECK-DAG: %[[VAL6:.+]] = mhlo.add %[[VAL4]], %[[VAL5]]
-
-  // Compute the numerator's imaginary component:
-  //   numerator.imag = lhs.imag * rhs.real - lhs.real * rhs.imag
-  // CHECK-DAG: %[[VAL7:.+]] = chlo.broadcast_multiply %arg1, %arg2
-  // CHECK-DAG: %[[VAL8:.+]] = chlo.broadcast_multiply %arg0, %[[VAL0]]
-  // CHECK-DAG: %[[VAL9:.+]] = mhlo.add %[[VAL8]], %[[VAL7]]
-
-  // Divide the numerator by the real valued denominator.
-  // CHECK-DAG: %[[VAL10:.+]] = chlo.broadcast_divide %[[VAL3]], %[[VAL6]]
-  // CHECK-DAG: %[[VAL11:.+]] = chlo.broadcast_divide %[[VAL9]], %[[VAL6]]
-  %4 = "mhlo.divide"(%2, %3) : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> (tensor<2xcomplex<f32>>)
-
-  %5 = mhlo.real %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-  %6 = mhlo.imag %4 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: return %[[VAL10]], %[[VAL11]]
-  return %5, %6 : tensor<2xf32>, tensor<2xf32>
-}
-
-// CHECK-LABEL: @abs
-func.func @abs(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>) -> (tensor<2xf32>) {
-  %0 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: %[[VAL0:.+]] = mhlo.multiply %arg0, %arg0
-  // CHECK-DAG: %[[VAL1:.+]] = mhlo.multiply %arg1, %arg1
-  // CHECK-DAG: %[[VAL2:.+]] = mhlo.add %[[VAL0]], %[[VAL1]]
-  // CHECK-DAG: %[[VAL3:.+]] = mhlo.sqrt %[[VAL2]]
-  %1 = mhlo.abs %0 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: return %[[VAL3]]
-  return %1 : tensor<2xf32>
-}
-
-// CHECK-LABEL: @exp
-func.func @exp(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>) -> (tensor<2xf32>, tensor<2xf32>) {
-  %0 = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-
-  // CHECK-DAG: %[[EXP:.+]] = mhlo.exponential %arg0
-  // CHECK-DAG: %[[COS:.+]] = mhlo.cosine %arg1
-  // CHECK-DAG: %[[SIN:.+]] = mhlo.sine %arg1
-  // CHECK-DAG: %[[OUTR:.+]] = mhlo.multiply %[[COS]], %[[EXP]]
-  // CHECK-DAG: %[[OUTI:.+]] = mhlo.multiply %[[SIN]], %[[EXP]]
-  %1 = mhlo.exponential %0 : tensor<2xcomplex<f32>>
-
-  %2 = mhlo.real %1 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-  %3 = mhlo.imag %1 : (tensor<2xcomplex<f32>>) -> (tensor<2xf32>)
-
-  // CHECK: %[[OUTR]], %[[OUTI]]
-  return %2, %3 : tensor<2xf32>, tensor<2xf32>
-}
-
-// CHECK-LABEL: @compare_eq
-func.func @compare_eq(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>,
-                 %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xi1>) {
-  %lhs = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %rhs = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  // CHECK-DAG: %[[OUTR:.+]] = chlo.broadcast_compare %arg0, %arg2 {comparison_direction = #chlo<comparison_direction EQ>}
-  // CHECK-DAG: %[[OUTI:.+]] = chlo.broadcast_compare %arg1, %arg3 {comparison_direction = #chlo<comparison_direction EQ>}
-  // CHECK-DAG: %[[OUT:.+]] = mhlo.and %[[OUTR]], %[[OUTI]]
-  %0 = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> tensor<2xi1>
-
-  // CHECK: return %[[OUT]]
-  return %0 : tensor<2xi1>
-}
-
-// CHECK-LABEL: @compare_ne
-func.func @compare_ne(%arg0 : tensor<2xf32>, %arg1 : tensor<2xf32>,
-                 %arg2 : tensor<2xf32>, %arg3 : tensor<2xf32>) -> (tensor<2xi1>) {
-  %lhs = "mhlo.complex"(%arg0, %arg1) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  %rhs = "mhlo.complex"(%arg2, %arg3) : (tensor<2xf32>, tensor<2xf32>) -> (tensor<2xcomplex<f32>>)
-  // CHECK-DAG: %[[OUTR:.+]] = chlo.broadcast_compare %arg0, %arg2 {comparison_direction = #chlo<comparison_direction NE>}
-  // CHECK-DAG: %[[OUTI:.+]] = chlo.broadcast_compare %arg1, %arg3 {comparison_direction = #chlo<comparison_direction NE>}
-  // CHECK-DAG: %[[OUT:.+]] = mhlo.or %[[OUTR]], %[[OUTI]]
-  %0 = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction NE>} : (tensor<2xcomplex<f32>>, tensor<2xcomplex<f32>>) -> tensor<2xi1>
-
-  // CHECK: return %[[OUT]]
-  return %0 : tensor<2xi1>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_linalg_ext.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_linalg_ext.mlir
deleted file mode 100644
index 7d00f42..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_linalg_ext.mlir
+++ /dev/null
@@ -1,564 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-ext %s | FileCheck %s
-// Also ensure that full lowering to linalg doesn't error.
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-ext --iree-mhlo-to-linalg-on-tensors --reconcile-unrealized-casts %s
-
-func.func @sort_1d(%arg0: tensor<128xi32>) -> (tensor<128xi32>) {
-  %0 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>):
-    %1 = "mhlo.compare"(%arg2, %arg3) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%1) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<128xi32>) -> (tensor<128xi32>)
-  return %0 : tensor<128xi32>
-}
-// CHECK-LABEL: func.func @sort_1d(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(0)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<128xi32>)
-// CHECK:           ^bb0(%[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32)
-// CHECK:             %[[CMP:.+]] = arith.cmpi sgt, %[[ARG1]], %[[ARG2]]
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:         return %[[SORT]]
-
-// -----
-
-func.func @sort_1d_ui(%arg0: tensor<128xui32>) -> (tensor<128xui32>) {
-  %0 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg2: tensor<ui32>, %arg3: tensor<ui32>):  // no predecessors
-    %1 = "mhlo.compare"(%arg2, %arg3) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<ui32>, tensor<ui32>) -> tensor<i1>
-    "mhlo.return"(%1) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<128xui32>) -> (tensor<128xui32>)
-  return %0 : tensor<128xui32>
-}
-// CHECK-LABEL: func.func @sort_1d_ui(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[CAST:.+]] = tensor.bitcast %[[ARG0]] : tensor<128xui32> to tensor<128xi32>
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(0)
-// CHECK-SAME:      outs(%[[CAST]] : tensor<128xi32>)
-// CHECK:           ^bb0(%[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32)
-// CHECK:             %[[CMP:.+]] = arith.cmpi ugt, %[[ARG1]], %[[ARG2]]
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:         %[[RESULT:.+]] = tensor.bitcast %[[SORT]] : tensor<128xi32> to tensor<128xui32>
-// CHECK:         return %[[RESULT]]
-
-// -----
-
-func.func @sort_cst_capture(%arg0: tensor<1x10xi32>) -> tensor<1x10xi32> {
-  %0 = mhlo.constant dense<0> : tensor<i32>
-  %1 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg1: tensor<i32>, %arg3: tensor<i32>):
-    %2 = "mhlo.compare"(%arg1, %0) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%2) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = true} : (tensor<1x10xi32>) -> tensor<1x10xi32>
-  return %1 : tensor<1x10xi32>
-}
-
-// CHECK-LABEL: func.func @sort_cst_capture(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SCALAR:.+]] = arith.constant 0 : i32
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort dimension(1) outs(%[[ARG0]] : tensor<1x10xi32>)  {
-// CHECK:         ^bb0(%[[ARG1:.+]]: i32, %{{.*}}: i32)
-// CHECK:           %[[RES:.+]] = arith.cmpi slt, %[[ARG1]], %[[SCALAR]] : i32
-// CHECK:           iree_linalg_ext.yield %[[RES]] : i1
-// CHECK:         } -> tensor<1x10xi32>
-// CHECK:         return %[[SORT]]
-
-// -----
-
-func.func @sort_argument_capture(%arg0: tensor<1x10xi32>, %arg1 : tensor<i32>) -> tensor<1x10xi32> {
-  %1 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>):
-    %2 = "mhlo.compare"(%arg2, %arg1) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%2) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = true} : (tensor<1x10xi32>) -> tensor<1x10xi32>
-  return %1 : tensor<1x10xi32>
-}
-
-// CHECK-LABEL: func.func @sort_argument_capture(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:      %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SCALAR:.+]] = tensor.extract %[[ARG1]][] : tensor<i32>
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort dimension(1) outs(%[[ARG0]] : tensor<1x10xi32>)  {
-// CHECK:         ^bb0(%[[ARG2:.+]]: i32, %{{.*}}: i32)
-// CHECK:           %[[RES:.+]] = arith.cmpi slt, %[[ARG2]], %[[SCALAR]] : i32
-// CHECK:           iree_linalg_ext.yield %[[RES]] : i1
-// CHECK:         } -> tensor<1x10xi32>
-// CHECK:         return %[[SORT]]
-
-// -----
-
-func.func @sort_2d(%arg0: tensor<16x32xi32>) -> (tensor<16x32xi32>) {
-  %0 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>):
-    %1 = "mhlo.compare"(%arg2, %arg3) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%1) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<16x32xi32>) -> (tensor<16x32xi32>)
-  return %0 : tensor<16x32xi32>
-}
-// CHECK-LABEL: func.func @sort_2d(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(0)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<16x32xi32>)
-// CHECK:           ^bb0(%[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32)
-// CHECK:             %[[CMP:.+]] = arith.cmpi sgt, %[[ARG1]], %[[ARG2]]
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:         return %[[SORT]]
-
-// -----
-
-func.func @sort_unsigned(%arg0: tensor<1x5xf32>) -> tensor<1x5xf32> {
-  %1 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg1: tensor<f32>, %arg2: tensor<f32>):
-    %2 = "mhlo.bitcast_convert"(%arg1) : (tensor<f32>) -> tensor<ui32>
-    %3 = "mhlo.bitcast_convert"(%arg2) : (tensor<f32>) -> tensor<ui32>
-    %4 = "mhlo.compare"(%2, %3) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<ui32>, tensor<ui32>) -> tensor<i1>
-    "mhlo.return"(%4) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = true} : (tensor<1x5xf32>) -> tensor<1x5xf32>
-  return %1 : tensor<1x5xf32>
-}
-
-// CHECK-LABEL: func.func @sort_unsigned(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(1)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<1x5xf32>)
-// CHECK:           ^bb0(%[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
-// CHECK:             %[[CAST1:.+]] = arith.bitcast %[[ARG1]] : f32 to i32
-// CHECK:             %[[CAST2:.+]] = arith.bitcast %[[ARG2]] : f32 to i32
-// CHECK:             %[[CMP:.+]] = arith.cmpi ult, %[[CAST1]], %[[CAST2]] : i32
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:         return %[[SORT]]
-
-// -----
-
-func.func @sort_unsigned_cst_capture(%arg0: tensor<1x5xf32>) -> tensor<1x5xf32> {
-  %ui32 = mhlo.constant dense<2> : tensor<ui32>
-  %1 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg1: tensor<f32>, %arg2: tensor<f32>):
-    %2 = "mhlo.bitcast_convert"(%arg1) : (tensor<f32>) -> tensor<ui32>
-    %3 = "mhlo.compare"(%2, %ui32) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<ui32>, tensor<ui32>) -> tensor<i1>
-    "mhlo.return"(%3) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = true} : (tensor<1x5xf32>) -> tensor<1x5xf32>
-  return %1 : tensor<1x5xf32>
-}
-
-// CHECK-LABEL: func.func @sort_unsigned_cst_capture(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[UI32:.+]] = mhlo.constant dense<2> : tensor<ui32>
-// CHECK:         %[[CONVERSION_CAST_CST:.+]] = tensor.bitcast %[[UI32]] : tensor<ui32> to tensor<i32>
-// CHECK:         %[[EXTRACT_CST:.+]] = tensor.extract %[[CONVERSION_CAST_CST]][] : tensor<i32>
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(1)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<1x5xf32>)
-// CHECK:           ^bb0(%[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
-// CHECK:             %[[CAST1:.+]] = arith.bitcast %[[ARG1]] : f32 to i32
-// CHECK:             %[[CMP:.+]] = arith.cmpi ult, %[[CAST1]], %[[EXTRACT_CST]] : i32
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:         return %[[SORT]]
-
-// -----
-
-// For testing that complex within an iree_linalg_ext.op gets lowered
-func.func @sort_complex(%arg0: tensor<1x5xf32>, %arg1 : tensor<complex<f32>>) -> tensor<1x5xf32> {
-  %ui32 = mhlo.constant dense<2> : tensor<ui32>
-  %1 = "mhlo.sort"(%arg0) ( {
-  ^bb0(%arg2: tensor<f32>, %arg3: tensor<f32>):
-    %2 = "mhlo.complex"(%arg2, %arg3) : (tensor<f32>, tensor<f32>) -> tensor<complex<f32>>
-    %3 = mhlo.add %2, %arg1 : tensor<complex<f32>>
-    %4 = "mhlo.real"(%3) : (tensor<complex<f32>>) -> tensor<f32>
-    %5 = "mhlo.imag"(%3) : (tensor<complex<f32>>) -> tensor<f32>
-    %6 = "mhlo.compare"(%4, %5) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<f32>, tensor<f32>) -> tensor<i1>
-    "mhlo.return"(%6) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = true} : (tensor<1x5xf32>) -> tensor<1x5xf32>
-  return %1 : tensor<1x5xf32>
-}
-
-// CHECK-LABEL: func.func @sort_complex(
-// CHECK-SAME:      %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:      %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK-SAME:  )
-// CHECK:         %[[SORT:.+]] = iree_linalg_ext.sort
-// CHECK-SAME:    dimension(1)
-// CHECK-SAME:    outs(%[[ARG0]] : tensor<1x5xf32>)
-// CHECK:         ^bb0(%[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
-// CHECK-NOT:       mhlo.complex
-// CHECK:           %[[CMP:.+]] = arith.cmpf olt, %{{.+}}, %{{.+}} : f32
-// CHECK:           iree_linalg_ext.yield %[[CMP]]
-// CHECK:       return %[[SORT]]
-
-// -----
-
-func.func @topk(%arg0: tensor<128xi32>, %arg1: tensor<128xi32>) -> (tensor<128xi32>) {
-  %0:2 = "mhlo.sort"(%arg0, %arg1) ( {
-  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>):
-    %1 = "mhlo.compare"(%arg2, %arg3) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%1) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<128xi32>, tensor<128xi32>) -> (tensor<128xi32>, tensor<128xi32>)
-  return %0#0 : tensor<128xi32>
-}
-// CHECK-LABEL: func.func @topk
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK:         %[[SORT:.+]]:2 = iree_linalg_ext.sort
-// CHECK-SAME:      dimension(0)
-// CHECK-SAME:      outs(%[[ARG0]], %[[ARG1]] : tensor<128xi32>, tensor<128xi32>)
-// CHECK:           ^bb0(%[[ARG2:.+]]: i32, %[[ARG3:.+]]: i32, %{{.*}}: i32, %{{.*}}: i32)
-// CHECK:             %[[CMP:.+]] = arith.cmpi sgt, %[[ARG2]], %[[ARG3]]
-// CHECK:             iree_linalg_ext.yield %[[CMP]]
-// CHECK:        return %[[SORT]]#0
-
-// -----
-
-func.func @scatter_update_scalar_1D(%arg0: tensor<8xi32>, %arg1: tensor<4x1xi32>,
-    %arg2: tensor<4xi32>) -> tensor<8xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<8xi32>, tensor<4x1xi32>, tensor<4xi32>) -> tensor<8xi32>
-  return %0 : tensor<8xi32>
-}
-// CHECK-LABEL: func.func @scatter_update_scalar_1D
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG2:[a-zA-Z0-9]+]]
-// CHECK:         %[[SCATTER:.+]] = iree_linalg_ext.scatter
-// CHECK-SAME:      unique_indices(true)
-// CHECK-SAME:      ins(%[[ARG2]], %[[ARG1]] : tensor<4xi32>, tensor<4x1xi32>)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<8xi32>)
-// CHECK:           ^bb0(%[[V1:.+]]: i32, %[[V2:.+]]: i32):
-// CHECK:             iree_linalg_ext.yield %[[V1]]
-// CHECK:         return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_update_scalar_2D(%arg0: tensor<4x3xi32>, %arg1: tensor<3x2xi32>,
-    %arg2: tensor<3xi32>) -> tensor<4x3xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {indices_are_sorted = false,
-      scatter_dimension_numbers = #mhlo.scatter<
-        inserted_window_dims = [0, 1],
-        scatter_dims_to_operand_dims = [0, 1],
-        index_vector_dim = 1,
-      >,
-      unique_indices = true
-  } : (tensor<4x3xi32>, tensor<3x2xi32>, tensor<3xi32>) -> tensor<4x3xi32>
-  return %0 : tensor<4x3xi32>
-}
-// CHECK-LABEL: func.func @scatter_update_scalar_2D
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG2:[a-zA-Z0-9]+]]
-// CHECK:         %[[SCATTER:.+]] = iree_linalg_ext.scatter
-// CHECK-SAME:      unique_indices(true)
-// CHECK-SAME:      ins(%[[ARG2]], %[[ARG1]] : tensor<3xi32>, tensor<3x2xi32>)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<4x3xi32>)
-// CHECK:           ^bb0(%[[V1:.+]]: i32, %[[V2:.+]]: i32):
-// CHECK:             iree_linalg_ext.yield %[[V1]]
-// CHECK:         return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_update_slice_2D(%arg0: tensor<6x3xi32>, %arg1: tensor<2x1xi32>,
-    %arg2: tensor<2x3xi32>) -> tensor<6x3xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<6x3xi32>, tensor<2x1xi32>, tensor<2x3xi32>) -> tensor<6x3xi32>
-  return %0 : tensor<6x3xi32>
-}
-// CHECK-LABEL: func.func @scatter_update_slice_2D
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG2:[a-zA-Z0-9]+]]
-// CHECK:         %[[SCATTER:.+]] = iree_linalg_ext.scatter
-// CHECK-SAME:      unique_indices(true)
-// CHECK-SAME:      ins(%[[ARG2]], %[[ARG1]] : tensor<2x3xi32>, tensor<2x1xi32>)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<6x3xi32>)
-// CHECK:           ^bb0(%[[V1:.+]]: i32, %[[V2:.+]]: i32):
-// CHECK:             iree_linalg_ext.yield %[[V1]]
-// CHECK:         return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_add_slice_2D(%arg0: tensor<6x3xi32>, %arg1: tensor<2x1xi32>,
-    %arg2: tensor<2x3xi32>) -> tensor<6x3xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    %1 = mhlo.add %arg3, %arg4 : tensor<i32>
-    "mhlo.return"(%1) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = false
-  } : (tensor<6x3xi32>, tensor<2x1xi32>, tensor<2x3xi32>) -> tensor<6x3xi32>
-  return %0 : tensor<6x3xi32>
-}
-// CHECK-LABEL: func.func @scatter_add_slice_2D
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG2:[a-zA-Z0-9]+]]
-// CHECK:         %[[SCATTER:.+]] = iree_linalg_ext.scatter
-// CHECK-SAME:      unique_indices(false)
-// CHECK-SAME:      ins(%[[ARG2]], %[[ARG1]] : tensor<2x3xi32>, tensor<2x1xi32>)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<6x3xi32>)
-// CHECK:           ^bb0(%[[V1:.+]]: i32, %[[V2:.+]]: i32):
-//
-//                   The order is reverse.
-// CHECK:              %[[V3:.+]] = arith.addi %[[V2]], %[[V1]]
-// CHECK:              iree_linalg_ext.yield %[[V3]]
-// CHECK:         return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_partial(%arg0: tensor<10x5xf32>, %arg1: tensor<3x1xi32>, %arg2: tensor<3x3xf32>) -> tensor<10x5xf32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<f32>, %arg4: tensor<f32>):  // no predecessors
-    %1 = mhlo.add %arg3, %arg4 : tensor<f32>
-    "mhlo.return"(%1) : (tensor<f32>) -> ()
-  }) {indices_are_sorted = false, scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1], inserted_window_dims = [0], scatter_dims_to_operand_dims = [0], index_vector_dim = 1>, unique_indices = false} : (tensor<10x5xf32>, tensor<3x1xi32>, tensor<3x3xf32>) -> tensor<10x5xf32>
-  return %0 : tensor<10x5xf32>
-}
-
-// CHECK-LABEL: func.func @scatter_partial
-// CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK-SAME:    %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK-SAME:    %[[ARG2:[a-zA-Z0-9]+]]
-// CHECK:         %[[SCATTER:.+]] = iree_linalg_ext.scatter
-// CHECK-SAME:      unique_indices(false)
-// CHECK-SAME:      ins(%[[ARG2]], %[[ARG1]] : tensor<3x3xf32>, tensor<3x1xi32>)
-// CHECK-SAME:      outs(%[[ARG0]] : tensor<10x5xf32>)
-// CHECK:         return %[[SCATTER]]
-
-// -----
-
-func.func @rfft_1d(%input: tensor<8xf32>) -> (tensor<5xf32>, tensor<5xf32>) {
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<8> : tensor<1xi64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<8xf32>) -> tensor<5xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<5xcomplex<f32>>) -> tensor<5xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<5xcomplex<f32>>) -> tensor<5xf32>
-  return %1, %2 : tensor<5xf32>, tensor<5xf32>
-}
-// CHECK-DAG:  #[[MAP:.+]] = affine_map<(d0) -> (d0)>
-// CHECK:      func.func @rfft_1d
-// CHECK-SAME:   %[[REAL:[a-zA-Z0-9]+]]
-// CHECK-DAG:    %[[INDICES:.+]] = arith.constant dense<[0, 4, 2, 6, 1, 5, 3, 7]> : tensor<8xi32>
-// CHECK-DAG:    %[[EMPTY:.+]] = tensor.empty() : tensor<8xf32>
-// CHECK:        %[[REORDERED:.+]] = linalg.generic
-// CHECK-SAME:     {indexing_maps = [#[[MAP]], #[[MAP]]]
-// CHECK-SAME:     iterator_types = ["parallel"]
-// CHECK-SAME:     ins(%[[INDICES]]
-// CHECK-SAME:     outs(%[[EMPTY]]
-// CHECK:        ^bb0(%[[IDX:.+]]: i32, %{{.+}}: f32):
-// CHECK:          %[[IDXVAL:.+]] = arith.index_cast %[[IDX]] : i32 to index
-// CHECK:          %[[LOAD:.+]] = tensor.extract %[[REAL]][%[[IDXVAL]]] : tensor<8xf32>
-// CHECK:          linalg.yield %[[LOAD]] : f32
-// CHECK-DAG:    %[[IMAG:.+]] = arith.constant dense<0.000000e+00> : tensor<8xf32>
-// CHECK-DAG:    %[[C1:.+]] = arith.constant 1 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<1xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<1xf32>
-// CHECK:        %[[R1:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C1]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[REORDERED]], %[[IMAG]]
-// CHECK-DAG:    %[[C2:.+]] = arith.constant 2 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<2xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<2xf32>
-// CHECK:        %[[R2:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C2]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[R1]]#0, %[[R1]]#1
-// CHECK-DAG:    %[[C3:.+]] = arith.constant 3 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<4xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<4xf32>
-// CHECK:        %[[R3:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C3]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[R2]]#0, %[[R2]]#1
-// CHECK:        %[[RES_REAL:.+]] = tensor.extract_slice %[[R3]]#0[0] [5] [1] : tensor<8xf32> to tensor<5xf32>
-// CHECK:        %[[RES_IMAG:.+]] = tensor.extract_slice %[[R3]]#1[0] [5] [1] : tensor<8xf32> to tensor<5xf32>
-// CHECK:        %{{.+}} = mhlo.complex %[[RES_REAL]], %[[RES_IMAG]]
-
-// -----
-
-func.func @rfft_2d(%input: tensor<4x8xf32>) -> (tensor<4x5xf32>, tensor<4x5xf32>) {
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<8> : tensor<1xi64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<4x8xf32>) -> tensor<4x5xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<4x5xcomplex<f32>>) -> tensor<4x5xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<4x5xcomplex<f32>>) -> tensor<4x5xf32>
-  return %1, %2 : tensor<4x5xf32>, tensor<4x5xf32>
-}
-// CHECK-DAG:  #[[MAP0:.+]] = affine_map<(d0, d1) -> (d1)>
-// CHECK-DAG:  #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0, d1)>
-// CHECK:      func.func @rfft_2d
-// CHECK-SAME:   %[[REAL:[a-zA-Z0-9]+]]
-// CHECK-DAG:    %[[INDICES:.+]] = arith.constant dense<[0, 4, 2, 6, 1, 5, 3, 7]> : tensor<8xi32>
-// CHECK-DAG:    %[[EMPTY:.+]] = tensor.empty() : tensor<4x8xf32>
-// CHECK:        %[[REORDERED:.+]] = linalg.generic
-// CHECK-SAME:     {indexing_maps = [#[[MAP0]], #[[MAP1]]]
-// CHECK-SAME:     iterator_types = ["parallel", "parallel"]
-// CHECK-SAME:     ins(%[[INDICES]]
-// CHECK-SAME:     outs(%[[EMPTY]]
-// CHECK:        ^bb0(%[[IDX:.+]]: i32, %{{.+}}: f32):
-// CHECK:          %[[I:.+]] = linalg.index 0
-// CHECK:          %[[IDXVAL:.+]] = arith.index_cast %[[IDX]] : i32 to index
-// CHECK:          %[[LOAD:.+]] = tensor.extract %[[REAL]][%[[I]], %[[IDXVAL]]] : tensor<4x8xf32>
-// CHECK:          linalg.yield %[[LOAD]] : f32
-// CHECK-DAG:    %[[IMAG:.+]] = arith.constant dense<0.000000e+00> : tensor<4x8xf32>
-// CHECK-DAG:    %[[C1:.+]] = arith.constant 1 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<1xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<1xf32>
-// CHECK:        %[[R1:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C1]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[REORDERED]], %[[IMAG]]
-// CHECK-DAG:    %[[C2:.+]] = arith.constant 2 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<2xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<2xf32>
-// CHECK:        %[[R2:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C2]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[R1]]#0, %[[R1]]#1
-// CHECK-DAG:    %[[C3:.+]] = arith.constant 3 : index
-// CHECK-DAG:    %[[COEF_REAL:.+]] = arith.constant dense<{{.+}}> : tensor<4xf32>
-// CHECK-DAG:    %[[COEF_IMAG:.+]] = arith.constant dense<{{.+}}> : tensor<4xf32>
-// CHECK:        %[[R3:.+]]:2 = iree_linalg_ext.fft
-// CHECK-SAME:     ins(%[[C3]], %[[COEF_REAL]], %[[COEF_IMAG]]
-// CHECK-SAME:     outs(%[[R2]]#0, %[[R2]]#1
-// CHECK:        %[[RES_REAL:.+]] = tensor.extract_slice %[[R3]]#0[0, 0] [4, 5] [1, 1] : tensor<4x8xf32> to tensor<4x5xf32>
-// CHECK:        %[[RES_IMAG:.+]] = tensor.extract_slice %[[R3]]#1[0, 0] [4, 5] [1, 1] : tensor<4x8xf32> to tensor<4x5xf32>
-// CHECK:        %{{.+}} = mhlo.complex %[[RES_REAL]], %[[RES_IMAG]]
-
-// -----
-
-func.func @reverse_dim1(%arg0: tensor<3x5xi32>) -> tensor<3x5xi32> {
-  %0 = "mhlo.reverse"(%arg0) {
-    dimensions = dense<1> : tensor<1xi64>
-  } : (tensor<3x5xi32>) -> tensor<3x5xi32>
-  return %0 : tensor<3x5xi32>
-}
-// CHECK-LABEL: func.func @reverse_dim1
-// CHECK-SAME:   %[[IN:[a-zA-Z0-9]+]]
-// CHECK:        %[[INIT:.+]] = tensor.empty() : tensor<3x5xi32>
-// CHECK:        %[[REV:.+]] = iree_linalg_ext.reverse
-// CHECK-SAME:     dimensions(dense<1> : tensor<1xi64>)
-// CHECK-SAME:     ins(%[[IN]] : tensor<3x5xi32>)
-// CHECK-SAME:     outs(%[[INIT]] : tensor<3x5xi32>) : tensor<3x5xi32>
-// CHECK:        return %[[REV]]
-
-// -----
-
-func.func @reverse_unsigned(%arg0: tensor<3x5xui32>) -> tensor<3x5xui32> {
-  %0 = "mhlo.reverse"(%arg0) {
-    dimensions = dense<1> : tensor<1xi64>
-  } : (tensor<3x5xui32>) -> tensor<3x5xui32>
-  return %0 : tensor<3x5xui32>
-}
-// CHECK-LABEL: func.func @reverse_unsigned
-// CHECK-SAME:   %[[IN:[a-zA-Z0-9]+]]
-// CHECK:        %[[BITCAST:.+]] = tensor.bitcast %[[IN]] : tensor<3x5xui32> to tensor<3x5xi32>
-// CHECK:        %[[INIT:.+]] = tensor.empty() : tensor<3x5xi32>
-// CHECK:        %[[REV:.+]] = iree_linalg_ext.reverse
-// CHECK-SAME:     dimensions(dense<1> : tensor<1xi64>)
-// CHECK-SAME:     ins(%[[BITCAST]] : tensor<3x5xi32>)
-// CHECK-SAME:     outs(%[[INIT]] : tensor<3x5xi32>) : tensor<3x5xi32>
-// CHECK:        %[[BITCAST:.+]] = tensor.bitcast %[[REV]] : tensor<3x5xi32> to tensor<3x5xui32>
-// CHECK:        return %[[BITCAST]]
-
-// -----
-
-func.func @reverse_multi_dim(%arg0: tensor<?x?xi32>) -> tensor<?x?xi32> {
-  %0 = "mhlo.reverse"(%arg0) {
-    dimensions = dense<[0, 1]> : tensor<2xi64>
-  } : (tensor<?x?xi32>) -> tensor<?x?xi32>
-  return %0 : tensor<?x?xi32>
-}
-// CHECK-LABEL: func.func @reverse_multi_dim
-// CHECK-SAME:   %[[IN:[a-zA-Z0-9]+]]
-// CHECK-DAG:    %[[C0:.+]] = arith.constant 0 : index
-// CHECK-DAG:    %[[C1:.+]] = arith.constant 1 : index
-// CHECK-DAG:    %[[D0:.+]] = tensor.dim %[[IN]], %[[C0]]
-// CHECK-DAG:    %[[D1:.+]] = tensor.dim %[[IN]], %[[C1]]
-// CHECK:        %[[INIT:.+]] = tensor.empty(%[[D0]], %[[D1]]) : tensor<?x?xi32>
-// CHECK:        %[[REV:.+]] = iree_linalg_ext.reverse
-// CHECK-SAME:     dimensions(dense<[0, 1]> : tensor<2xi64>)
-// CHECK-SAME:     ins(%[[IN]] : tensor<?x?xi32>)
-// CHECK-SAME:     outs(%[[INIT]] : tensor<?x?xi32>) : tensor<?x?xi32>
-// CHECK:        return %[[REV]]
-
-// -----
-
-func.func @chlo_top_k_int(%arg : tensor<16x16xi32>) -> (tensor<16x8xi32>, tensor<16x8xi32>) {
-  %1:2 = chlo.top_k(%arg, k=8) : tensor<16x16xi32> -> (tensor<16x8xi32>, tensor<16x8xi32>)
-  return %1#0, %1#1 : tensor<16x8xi32>, tensor<16x8xi32>
-}
-
-// CHECK:       func.func @chlo_top_k_int
-// CHECK-SAME:   %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:        %[[D2:.+]] = tensor.empty() : tensor<16x8xi32>
-// CHECK:        %[[D3:.+]] = tensor.empty() : tensor<16x8xi32>
-// CHECK-DAG:    %[[CNEG:.+]] = arith.constant -2147483648 : i32
-// CHECK-DAG:    %[[CPOS:.+]] = arith.constant 2147483647 : i32
-// CHECK-DAG:    %[[D4:.+]] = linalg.fill ins(%[[CNEG]] : i32) outs(%[[D2]]
-// CHECK-DAG:    %[[D5:.+]] = linalg.fill ins(%[[CPOS]] : i32) outs(%[[D3]]
-// CHECK:        %[[D6:.+]]:2 = iree_linalg_ext.topk
-// CHECK-SAME:     dimension(1)
-// CHECK-SAME:     ins(%[[ARG0]]
-// CHECK-SAME:     outs(%[[D4]], %[[D5]]
-// CHECK:        ^bb0(%[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32)
-// CHECK:        %[[D7:.+]] = arith.cmpi sge, %[[ARG1]], %[[ARG2]] : i32
-// CHECK:        iree_linalg_ext.yield %[[D7]] : i1
-// CHECK:        return %[[D6]]#0, %[[D6]]#1
-
-// -----
-
-func.func @chlo_top_k_float(%arg : tensor<16x16xf32>) -> (tensor<16x8xf32>, tensor<16x8xi32>) {
-  %1:2 = chlo.top_k(%arg, k=8) : tensor<16x16xf32> -> (tensor<16x8xf32>, tensor<16x8xi32>)
-  return %1#0, %1#1 : tensor<16x8xf32>, tensor<16x8xi32>
-}
-
-// CHECK:       func.func @chlo_top_k_float
-// CHECK-SAME:   %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:        %[[D2:.+]] = tensor.empty() : tensor<16x8xf32>
-// CHECK:        %[[D3:.+]] = tensor.empty() : tensor<16x8xi32>
-// CHECK-DAG:    %[[CNEG:.+]] = arith.constant 0xFF800000 : f32
-// CHECK-DAG:    %[[CPOS:.+]] = arith.constant 2147483647 : i32
-// CHECK-DAG:    %[[D4:.+]] = linalg.fill ins(%[[CNEG]] : f32) outs(%[[D2]]
-// CHECK-DAG:    %[[D5:.+]] = linalg.fill ins(%[[CPOS]] : i32) outs(%[[D3]]
-// CHECK:        %[[D6:.+]]:2 = iree_linalg_ext.topk
-// CHECK-SAME:     dimension(1)
-// CHECK-SAME:     ins(%[[ARG0]]
-// CHECK-SAME:     outs(%[[D4]], %[[D5]]
-// CHECK:        ^bb0(%[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32)
-// CHECK:        %[[D7:.+]] = arith.cmpf ogt, %[[ARG1]], %[[ARG2]] : f32
-// CHECK:        iree_linalg_ext.yield %[[D7]] : i1
-// CHECK:        return %[[D6]]#0, %[[D6]]#1
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_stablehlo.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_stablehlo.mlir
deleted file mode 100644
index a40972c..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_mhlo_to_stablehlo.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: iree-opt --iree-convert-mhlo-to-stablehlo %s | FileCheck %s
-
-// CHECK-LABEL: func.func @add
-// CHECK-NEXT:    stablehlo.add
-// CHECK-NEXT:    chlo.broadcast_add
-// CHECK-NEXT:    stablehlo.add
-// CHECK-NEXT:    return
-func.func @add(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  %0 = mhlo.add %arg0, %arg1 : tensor<4xf32>
-  %1 = chlo.broadcast_add %0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  %2 = stablehlo.add %1, %arg1 : tensor<4xf32>
-  return %2 : tensor<4xf32>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_structural_types.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_structural_types.mlir
deleted file mode 100644
index 509c079..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/convert_structural_types.mlir
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors %s | FileCheck %s
-
-// CHECK-LABEL: @func_cfg_conversion
-module @func_cfg_conversion {
-  // CHECK: func.func @caller(%arg0: tensor<2xi32>, %arg1: i1) -> tensor<2xi32>
-  func.func @caller(%arg0: tensor<2xi32>, %arg1 : i1) -> tensor<2xi32> {
-    // CHECK: %[[RESULT:.*]] = call @callee(%arg0, %arg1) : (tensor<2xi32>, i1) -> tensor<2xi32>
-    %1 = call @callee(%arg0, %arg1) : (tensor<2xi32>, i1) -> tensor<2xi32>
-    // CHECK: return %[[RESULT]] : tensor<2xi32>
-    return %1 : tensor<2xi32>
-  }
-
-  // CHECK: func.func @callee(%arg0: tensor<2xi32>, %arg1: i1) -> tensor<2xi32>
-  func.func @callee(%arg0: tensor<2xi32>, %arg1: i1) -> tensor<2xi32> {
-    // CHECK: cf.cond_br %arg1, ^bb1(%arg0 : tensor<2xi32>), ^bb2(%arg0 : tensor<2xi32>)
-    cf.cond_br %arg1, ^bb1(%arg0 : tensor<2xi32>), ^bb2(%arg0 : tensor<2xi32>)
-  // CHECK: ^bb1(%[[BB1_PHI:.*]]: tensor<2xi32>)
-  ^bb1(%phi0 : tensor<2xi32>) :
-    // CHECK: %[[BB1_PHI_ADD:.*]] = linalg.generic
-    // CHECK: cf.br ^bb2(%[[BB1_PHI_ADD]] : tensor<2xi32>)
-    %0 = "mhlo.add"(%phi0, %phi0) : (tensor<2xi32>, tensor<2xi32>) -> tensor<2xi32>
-    cf.br ^bb2(%0 : tensor<2xi32>)
-  // CHECK: ^bb2(%[[BB2_PHI:.*]]: tensor<2xi32>)
-  ^bb2(%phi1 : tensor<2xi32>):
-    // CHECK: %[[BB2_PHI_ADD:.*]] = linalg.generic
-    // CHECK: return %[[BB2_PHI_ADD]] : tensor<2xi32>
-    %1 = "mhlo.add"(%phi1, %phi1) : (tensor<2xi32>, tensor<2xi32>) -> tensor<2xi32>
-    return %1 : tensor<2xi32>
-  }
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/dynamic_shape.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/dynamic_shape.mlir
deleted file mode 100644
index dcc27db..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/dynamic_shape.mlir
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors %s | FileCheck %s
-
-func.func @dynamic_shape(%operand: tensor<?x?xf32>) -> (tensor<?x?xf32>)
-attributes {iree.dispatch_fn_name = ""} {
-  %result = "mhlo.exponential"(%operand) : (tensor<?x?xf32>) -> tensor<?x?xf32>
-  return %result : tensor<?x?xf32>
-}
-
-//      CHECK: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
-//      CHECK: func.func @dynamic_shape
-// CHECK-SAME:   %[[ARG0:.+]]: tensor<?x?xf32>
-//  CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index
-//  CHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index
-//      CHECK:   %[[SHAPE:.+]] = shape.shape_of %[[ARG0]]
-//      CHECK:   %[[T0:.+]] = tensor.extract %[[SHAPE]][%[[C0]]]
-//      CHECK:   %[[T1:.+]] = tensor.extract %[[SHAPE]][%[[C1]]]
-//      CHECK:   %[[T2:.+]] = tensor.empty(%[[T0]], %[[T1]])
-//      CHECK:   %[[T3:.+]] = linalg.generic
-// CHECK-SAME:     indexing_maps = [#[[MAP0]], #[[MAP0]]]
-// CHECK-SAME:     iterator_types = ["parallel", "parallel"]}
-// CHECK-SAME:     ins(%[[ARG0]] : tensor<?x?xf32>)
-// CHECK-SAME:     outs(%[[T2]] : tensor<?x?xf32>)
-// CHECK-NEXT:     ^{{.+}}(%[[OPERAND_IN:[a-zA-Z0-9_]+]]: f32, %{{.+}}: f32):
-// CHECK-NEXT:       %[[RESULT:.+]] = math.exp %[[OPERAND_IN]] : f32
-// CHECK-NEXT:       linalg.yield %[[RESULT]] : f32
-//      CHECK:   return %[[T3]]
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/fft.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/fft.mlir
deleted file mode 100644
index 354ce7e..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/fft.mlir
+++ /dev/null
@@ -1,71 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors --canonicalize %s | FileCheck %s
-
-func.func @rfft_1d(%input: tensor<32xf32>) -> (tensor<17xf32>, tensor<17xf32>) {
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<32> : tensor<1xi64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<32xf32>) -> tensor<17xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<17xcomplex<f32>>) -> tensor<17xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<17xcomplex<f32>>) -> tensor<17xf32>
-  return %1, %2 : tensor<17xf32>, tensor<17xf32>
-}
-// CHECK:     func.func @rfft_1d
-// CHECK-SAME:  %[[Arg0:[a-zA-Z0-9_]*]]
-// CHECK-DAG:   %[[RealMatrix:.+]] = arith.constant dense<"0x0000803F{{.*}}"> : tensor<32x17xf32>
-// CHECK-DAG:   %[[ImagMatrix:.+]] = arith.constant dense<"0x00000080{{.*}}"> : tensor<32x17xf32>
-// CHECK-DAG:   %[[Zero:.+]] = arith.constant 0.000000e+00 : f32
-// CHECK:       %[[RealInit:.+]] = tensor.empty() : tensor<17xf32>
-// CHECK:       %[[RealFill:.+]] = linalg.fill
-// CHECK-SAME:    ins(%[[Zero]] :
-// CHECK-SAME:    outs(%[[RealInit]] :
-// CHECK:       %[[RealRes:.+]] = linalg.vecmat
-// CHECK-SAME:    ins(%[[Arg0]], %[[RealMatrix]] : tensor<32xf32>, tensor<32x17xf32>)
-// CHECK-SAME:    outs(%[[RealFill]] : tensor<17xf32>) -> tensor<17xf32>
-// CHECK:        %[[ImagInit:.+]] = tensor.empty() : tensor<17xf32>
-// CHECK:        %[[ImagFill:.+]] = linalg.fill
-// CHECK-SAME:     ins(%[[Zero]] :
-// CHECK-SAME:     outs(%[[ImagInit]] :
-// CHECK:        %[[ImagRes:.+]] = linalg.vecmat
-// CHECK-SAME:     ins(%[[Arg0]], %[[ImagMatrix]] : tensor<32xf32>, tensor<32x17xf32>)
-// CHECK-SAME:     outs(%[[ImagFill]] : tensor<17xf32>) -> tensor<17xf32>
-// CHECK:        %[[ComplexRes:.*]] = linalg.generic
-// CHECK:        %[[ReRes:.*]] = linalg.generic
-// CHECK-SAME:     ins(%[[ComplexRes]]
-// CHECK:        %[[ImRes:.*]] = linalg.generic
-// CHECK-SAME:     ins(%[[ComplexRes]]
-// CHECK:        return %[[ReRes]], %[[ImRes]] : tensor<17xf32>, tensor<17xf32>
-
-// -----
-
-func.func @rfft_2d(%input: tensor<1x32xf32>) -> (tensor<1x17xf32>, tensor<1x17xf32>) {
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<32> : tensor<1xi64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<1x32xf32>) -> tensor<1x17xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<1x17xcomplex<f32>>) -> tensor<1x17xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<1x17xcomplex<f32>>) -> tensor<1x17xf32>
-  return %1, %2 : tensor<1x17xf32>, tensor<1x17xf32>
-}
-// CHECK:     func.func @rfft_2d
-// CHECK-SAME:  %[[Arg0:[a-zA-Z0-9_]*]]
-// CHECK-DAG:   %[[RealMatrix:.+]] = arith.constant dense<"0x0000803F{{.*}}"> : tensor<32x17xf32>
-// CHECK-DAG:   %[[ImagMatrix:.+]] = arith.constant dense<"0x00000080{{.*}}"> : tensor<32x17xf32>
-// CHECK-DAG:   %[[Zero:.+]] = arith.constant 0.000000e+00 : f32
-// CHECK:        %[[RealInit:.+]] = tensor.empty() : tensor<1x17xf32>
-// CHECK:        %[[RealFill:.+]] = linalg.fill
-// CHECK-SAME:     ins(%[[Zero]] :
-// CHECK-SAME:     outs(%[[RealInit]] :
-// CHECK:        %[[RealRes:.+]] = linalg.matmul
-// CHECK-SAME:     ins(%[[Arg0]], %[[RealMatrix]] : tensor<1x32xf32>, tensor<32x17xf32>)
-// CHECK-SAME:     outs(%[[RealFill]] : tensor<1x17xf32>) -> tensor<1x17xf32>
-// CHECK:        %[[ImagInit:.+]] = tensor.empty() : tensor<1x17xf32>
-// CHECK:        %[[ImagFill:.+]] = linalg.fill
-// CHECK-SAME:     ins(%[[Zero]] :
-// CHECK-SAME:     outs(%[[ImagInit]] :
-// CHECK:        %[[ImagRes:.+]] = linalg.matmul
-// CHECK-SAME:     ins(%[[Arg0]], %[[ImagMatrix]] : tensor<1x32xf32>, tensor<32x17xf32>)
-// CHECK-SAME:     outs(%[[ImagFill]] : tensor<1x17xf32>) -> tensor<1x17xf32>
-// CHECK:        %[[ComplexRes:.*]] = linalg.generic
-// CHECK:        %[[ReRes:.*]] = linalg.generic
-// CHECK-SAME:     ins(%[[ComplexRes]]
-// CHECK:        %[[ImRes:.*]] = linalg.generic
-// CHECK-SAME:     ins(%[[ComplexRes]]
-// CHECK:        return %[[ReRes]], %[[ImRes]] : tensor<1x17xf32>, tensor<1x17xf32>
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/flatten_tuples_in_cfg.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/flatten_tuples_in_cfg.mlir
deleted file mode 100644
index 107ea14..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/flatten_tuples_in_cfg.mlir
+++ /dev/null
@@ -1,34 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-flatten-tuples-in-cfg --canonicalize %s | FileCheck %s
-// We rely on canonicalization to cancel out tuple/get_element operations, so
-// we test this followed by the canonicalizer rather than just the pass in
-// isolation.
-// TODO: It would be better if the pass was standalone.
-
-// CHECK-LABEL: @flatten_func
-module @flatten_func {
-  // CHECK: func.func @caller(%arg0: i1, %arg1: tensor<f32>) -> tensor<f32>
-  func.func @caller(%arg0 : i1, %arg1: tensor<f32>) -> tensor<f32> {
-    // CHECK: %[[RESULT:.*]]:2 = call @callee(%arg0, %arg1, %arg1, %arg1) : (i1, tensor<f32>, tensor<f32>, tensor<f32>) -> (tensor<f32>, tensor<f32>)
-    %0 = "mhlo.tuple"(%arg1, %arg1) : (tensor<f32>, tensor<f32>) -> tuple<tensor<f32>, tensor<f32>>
-    %1 = "mhlo.tuple"(%arg1, %0) : (tensor<f32>, tuple<tensor<f32>, tensor<f32>>) -> tuple<tensor<f32>, tuple<tensor<f32>, tensor<f32>>>
-    %2 = call @callee(%arg0, %1) : (i1, tuple<tensor<f32>, tuple<tensor<f32>, tensor<f32>>>) -> tuple<tensor<f32>, tensor<f32>>
-    %3 = "mhlo.get_tuple_element"(%2) {index = 0 : i32} : (tuple<tensor<f32>, tensor<f32>>) -> tensor<f32>
-    // CHECK: return %[[RESULT]]#0 : tensor<f32>
-    return %3 : tensor<f32>
-  }
-
-  // CHECK: func.func private @callee(%arg0: i1, %arg1: tensor<f32>, %arg2: tensor<f32>, %arg3: tensor<f32>) -> (tensor<f32>, tensor<f32>)
-  func.func private @callee(%arg0: i1, %arg1: tuple<tensor<f32>, tuple<tensor<f32>, tensor<f32>>>) -> tuple<tensor<f32>, tensor<f32>> {
-    // CHECK-DAG: %[[RESULT0:.*]] = arith.select %arg0, %arg2, %arg1 : tensor<f32>
-    // CHECK-DAG: %[[RESULT1:.*]] = arith.select %arg0, %arg3, %arg1 : tensor<f32>
-    // CHECK: return %[[RESULT0]], %[[RESULT1]] : tensor<f32>, tensor<f32>
-    %0 = "mhlo.get_tuple_element"(%arg1) {index = 0 : i32} : (tuple<tensor<f32>, tuple<tensor<f32>, tensor<f32>>>) -> tensor<f32>
-    %1 = "mhlo.get_tuple_element"(%arg1) {index = 1 : i32} : (tuple<tensor<f32>, tuple<tensor<f32>, tensor<f32>>>) -> tuple<tensor<f32>, tensor<f32>>
-    cf.cond_br %arg0, ^bb1(%1 : tuple<tensor<f32>, tensor<f32>>), ^bb2(%0 : tensor<f32>)
-  ^bb1(%phi0 : tuple<tensor<f32>, tensor<f32>>):
-    return %phi0 : tuple<tensor<f32>, tensor<f32>>
-  ^bb2(%phi1 : tensor<f32>):
-    %2 = "mhlo.tuple"(%phi1, %phi1) : (tensor<f32>, tensor<f32>) -> tuple<tensor<f32>, tensor<f32>>
-    cf.br ^bb1(%2 : tuple<tensor<f32>, tensor<f32>>)
-  }
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_linalg.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_linalg.mlir
deleted file mode 100644
index 0c4ae29..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_linalg.mlir
+++ /dev/null
@@ -1,64 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors --canonicalize -cse %s | FileCheck %s
-
-func.func @concatenate(%arg0: tensor<2x2xi32>, %arg1: tensor<2x4xi32>) -> tensor<2x9xi32> {
-  %cst = mhlo.constant dense<514> : tensor<2x3xi32>
-  %0 = "mhlo.concatenate"(%arg0, %cst, %arg1) {dimension = 1} : (tensor<2x2xi32>, tensor<2x3xi32>, tensor<2x4xi32>) -> tensor<2x9xi32>
-  return %0 : tensor<2x9xi32>
-}
-// CHECK:       func.func @concatenate
-// CHECK-SAME:    %[[ARG0:[a-zA-Z0-9$._-]+]]
-// CHECK-SAME:    %[[ARG1:[a-zA-Z0-9$._-]+]]
-// CHECK:         %[[CST:.+]] = arith.constant dense<514> : tensor<2x3xi32>
-// CHECK:         %[[INIT:.+]] = tensor.empty() : tensor<2x9xi32>
-// CHECK:         %[[T0:.+]] = tensor.insert_slice %[[ARG0]] into %[[INIT]][0, 0] [2, 2] [1, 1]
-// CHECK:         %[[T1:.+]] = tensor.insert_slice %[[CST]] into %[[T0]][0, 2] [2, 3] [1, 1]
-// CHECK:         %[[T2:.+]] = tensor.insert_slice %[[ARG1]] into %[[T1]][0, 5] [2, 4] [1, 1]
-// CHECK:         return %[[T2]]
-
-// -----
-
-// CHECK: ml_program.global private mutable @variable(dense<0> : tensor<2xi32>) : tensor<2xi32>
-ml_program.global private mutable @variable(dense<0> : tensor<2xui32>) : tensor<2xui32>
-// CHECK: func.func @global_types() -> (tensor<2xi32> {iree.abi.encoding = tensor<2xui32>})
-func.func @global_types() -> tensor<2xui32> {
-  // CHECK-NEXT: %[[VALUE:.+]] = ml_program.global_load @variable : tensor<2xi32>
-  %0 = ml_program.global_load @variable : tensor<2xui32>
-  // CHECK: return %[[VALUE]] : tensor<2xi32>
-  return %0 : tensor<2xui32>
-}
-
-// -----
-
-// CHECK: func.func @optimization_barrier
-// CHECK: %[[RESULT1:.+]] = util.optimization_barrier %arg0 : tensor<3x4xf32
-// CHECK: %[[RESULT2:.+]] = util.optimization_barrier %arg1 : tensor<4xi32>
-// CHECK: return %[[RESULT1]], %[[RESULT2]]
-func.func @optimization_barrier(%arg0: tensor<3x4xf32>, %arg1: tensor<4xi32>) -> (tensor<3x4xf32>, tensor<4xi32>) {
-  %0, %1 = "mhlo.optimization_barrier"(%arg0, %arg1) : (tensor<3x4xf32>, tensor<4xi32>) -> (tensor<3x4xf32>, tensor<4xi32>)
-  return %0, %1 : tensor<3x4xf32>, tensor<4xi32>
-}
-
-// -----
-
-// CHECK: @unsigned_integer_input_output(%[[ARG0:.*]]: tensor<2x2xi32> {iree.abi.encoding = tensor<2x2xui32>}, %[[ARG1:.*]]: tensor<2x2xi32> {iree.abi.encoding = tensor<2x2xui32>}) -> (tensor<2x2xi32> {iree.abi.encoding = tensor<2x2xui32>})
-func.func @unsigned_integer_input_output(%arg0: tensor<2x2xui32>, %arg1: tensor<2x2xui32>) -> tensor<2x2xui32> {
-  // CHECK: %[[INIT:.*]] = tensor.empty() : tensor<2x2xi32>
-  // CHECK: %[[RESULT:.*]] = linalg.generic
-  //  CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]] : tensor<2x2xi32>, tensor<2x2xi32>
-  //  CHECK-SAME:       outs(%[[INIT]] : tensor<2x2xi32>)
-  // CHECK: ^bb0(%[[IN0:.*]]: i32, %[[IN1:.*]]: i32, %out: i32):
-  // CHECK: %[[ADD:.*]] = arith.addi %[[IN0]], %[[IN1]] : i32
-  // CHECK: linalg.yield %[[ADD:.*]] : i32
-  %0 = "mhlo.add"(%arg0, %arg1) : (tensor<2x2xui32>, tensor<2x2xui32>) -> tensor<2x2xui32>
-  // CHECK: return %[[RESULT]] : tensor<2x2xi32>
-  return %0 : tensor<2x2xui32>
-}
-
-// -----
-
-// CHECK: func.func @aliasing_output
-// CHECK-SAME:    %[[ARG0:[^:]+]]: tensor<3x4xf32> {iree.abi.output = 1 : index}
-// CHECK-SAME:    %[[ARG1:[^:]+]]: tensor<4xi32> {iree.abi.encoding = tensor<4xui32>}
-func.func @aliasing_output(%arg0: tensor<3x4xf32> {tf.aliasing_output = 1 : i32}, %arg1: tensor<4xui32>) -> (tensor<4xui32>, tensor<3x4xf32>) {
-  return %arg1, %arg0 : tensor<4xui32>, tensor<3x4xf32>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing.mlir
deleted file mode 100644
index 5a0ec47..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing.mlir
+++ /dev/null
@@ -1,354 +0,0 @@
-// RUN: iree-opt --split-input-file --verify-diagnostics --iree-mhlo-to-mhlo-preprocessing %s | FileCheck %s
-
-// CHECK-LABEL: @batch_norm_inference
-// CHECK-SAME: %[[X:[^:[:space:]]+]]
-// CHECK-SAME: %[[SCALE:[^:[:space:]]+]]
-// CHECK-SAME: %[[OFFSET:[^:[:space:]]+]]
-// CHECK-SAME: %[[MEAN:[^:[:space:]]+]]
-// CHECK-SAME: %[[VARIANCE:[^:[:space:]]+]]
-func.func @batch_norm_inference(
-    %x: tensor<4x256xf32>, %scale: tensor<256xf32>, %offset: tensor<256xf32>,
-    %mean: tensor<256xf32>, %variance: tensor<256xf32>)
-    -> (tensor<4x256xf32>) {
-  // CHECK-DAG: %[[EPS_BCAST:.+]] = mhlo.constant dense<1.001000e-05> : tensor<256xf32>
-  // CHECK-DAG: %[[VARIANCE_EPS:.+]] = mhlo.add %[[VARIANCE]], %[[EPS_BCAST]] : tensor<256xf32>
-  // CHECK-DAG: %[[STDDEV:.+]] = mhlo.sqrt %[[VARIANCE_EPS]] : tensor<256xf32>
-  // CHECK-DAG: %[[STDDEV_BCAST:.+]] = "mhlo.broadcast_in_dim"(%[[STDDEV]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<256xf32>) -> tensor<4x256xf32>
-  // CHECK-DAG: %[[SCALE_BCAST:.+]] = "mhlo.broadcast_in_dim"(%[[SCALE]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<256xf32>) -> tensor<4x256xf32>
-  // CHECK-DAG: %[[OFFSET_BCAST:.+]] = "mhlo.broadcast_in_dim"(%[[OFFSET]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<256xf32>) -> tensor<4x256xf32>
-  // CHECK-DAG: %[[MEAN_BCAST:.+]] = "mhlo.broadcast_in_dim"(%[[MEAN]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<256xf32>) -> tensor<4x256xf32>
-  // CHECK-DAG: %[[X_CENTER:.+]] = mhlo.subtract %[[X]], %[[MEAN_BCAST]] : tensor<4x256xf32>
-  // CHECK-DAG: %[[X_SCALED:.+]] = mhlo.multiply %[[X_CENTER]], %[[SCALE_BCAST]] : tensor<4x256xf32>
-  // CHECK-DAG: %[[X_NORMED:.+]] = mhlo.divide %[[X_SCALED]], %[[STDDEV_BCAST]] : tensor<4x256xf32>
-  // CHECK-DAG: %[[RESULT:.+]] = mhlo.add %[[X_NORMED]], %[[OFFSET_BCAST]] : tensor<4x256xf32>
-  %0 = "mhlo.batch_norm_inference"(%x, %scale, %offset, %mean, %variance)
-      {epsilon = 1.001000e-05 : f32, feature_index = 1 : i64} :
-      (tensor<4x256xf32>, tensor<256xf32>, tensor<256xf32>, tensor<256xf32>,
-        tensor<256xf32>) -> tensor<4x256xf32>
-  // CHECK-DAG: return %[[RESULT]]
-  return %0 : tensor<4x256xf32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_scalar_binary(%[[ARG0:.*]]: tensor<f32>, %[[ARG1:.*]]: tensor<f32>, %[[ARG2:.*]]: tensor<i32>, %[[ARG3:.*]]: tensor<i32>)
-func.func @reorder_broadcast_in_dim_scalar_binary(%arg0: tensor<f32>, %arg1: tensor<f32>, %arg2: tensor<i32>, %arg3: tensor<i32>) -> (tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>) {
-  // CHECK: %[[ADD:.*]] = mhlo.add %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[ADD]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[ATAN2:.*]] = mhlo.atan2 %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[ATAN2]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[DIV:.*]] = mhlo.divide %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[DIV]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[MAX:.*]] = mhlo.maximum %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[MAX]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[MIN:.*]] = mhlo.minimum %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[MIN]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[MUL:.*]] = mhlo.multiply %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[MUL]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[POW:.*]] = mhlo.power %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[POW]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[REM:.*]] = mhlo.remainder %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[REM]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[SL:.*]] = mhlo.shift_left %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SL]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  // CHECK: %[[SRA:.*]] = mhlo.shift_right_arithmetic %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SRA]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  // CHECK: %[[SRL:.*]] = mhlo.shift_right_logical %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SRL]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  // CHECK: %[[SUB:.*]] = mhlo.subtract %[[ARG0]], %[[ARG1]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SUB]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[AND:.*]] = mhlo.and %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[AND]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  // CHECK: %[[OR:.*]] = mhlo.or %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[OR]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  // CHECK: %[[XOR:.*]] = mhlo.xor %[[ARG2]], %[[ARG3]] : tensor<i32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[XOR]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %1 = "mhlo.broadcast_in_dim"(%arg1) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %2 = "mhlo.broadcast_in_dim"(%arg2) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  %3 = "mhlo.broadcast_in_dim"(%arg3) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<i32>) -> tensor<1x8x8x64xi32>
-  %4 = mhlo.add %0, %1 : tensor<1x8x8x64xf32>
-  %5 = mhlo.atan2 %0, %1 : tensor<1x8x8x64xf32>
-  %6 = mhlo.divide %0, %1 : tensor<1x8x8x64xf32>
-  %7 = mhlo.maximum %0, %1 : tensor<1x8x8x64xf32>
-  %8 = mhlo.minimum %0, %1 : tensor<1x8x8x64xf32>
-  %9 = mhlo.multiply %0, %1 : tensor<1x8x8x64xf32>
-  %10 = mhlo.power %0, %1 : tensor<1x8x8x64xf32>
-  %11 = mhlo.remainder %0, %1 : tensor<1x8x8x64xf32>
-  %12 = mhlo.shift_left %2, %3 : tensor<1x8x8x64xi32>
-  %13 = mhlo.shift_right_arithmetic %2, %3 : tensor<1x8x8x64xi32>
-  %14 = mhlo.shift_right_logical %2, %3 : tensor<1x8x8x64xi32>
-  %15 = mhlo.subtract %0, %1 : tensor<1x8x8x64xf32>
-  %16 = mhlo.and %2, %3 : tensor<1x8x8x64xi32>
-  %17 = mhlo.or %2, %3 : tensor<1x8x8x64xi32>
-  %18 = mhlo.xor %2, %3 : tensor<1x8x8x64xi32>
-  return %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16, %17, %18 : tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>, tensor<1x8x8x64xi32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_scalar_binary_diff_type(%[[ARG0:.*]]: tensor<f32>, %[[ARG1:.*]]: tensor<f32>) -> tensor<1x8x8x64xcomplex<f32>>
-func.func @reorder_broadcast_in_dim_scalar_binary_diff_type(%arg0: tensor<f32>, %arg1: tensor<f32>) -> tensor<1x8x8x64xcomplex<f32>> {
-  // CHECK: %0 = mhlo.complex %[[ARG0]], %[[ARG1]] : tensor<complex<f32>>
-  // CHECK: "mhlo.broadcast_in_dim"(%0) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<complex<f32>>) -> tensor<1x8x8x64xcomplex<f32>>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %1 = "mhlo.broadcast_in_dim"(%arg1) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %2 = "mhlo.complex"(%0, %1) : (tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>) -> tensor<1x8x8x64xcomplex<f32>>
-  return %2 : tensor<1x8x8x64xcomplex<f32>>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_1d_binary(%[[ARG0:.*]]: tensor<3xf32>, %[[ARG1:.*]]: tensor<3xf32>) -> tensor<4x3xf32>
-func.func @reorder_broadcast_in_dim_1d_binary(%arg0: tensor<3xf32>, %arg1: tensor<3xf32>) -> tensor<4x3xf32> {
-  // CHECK: %[[ATAN2:.*]] = mhlo.atan2 %[[ARG0]], %[[ARG1]] : tensor<3xf32>
-  // CHECK: %[[BCAST:.*]] = "mhlo.broadcast_in_dim"(%[[ATAN2]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<3xf32>) -> tensor<4x3xf32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[1]> : tensor<1xi64>} : (tensor<3xf32>) -> tensor<4x3xf32>
-  %1 = "mhlo.broadcast_in_dim"(%arg1) {broadcast_dimensions = dense<[1]> : tensor<1xi64>} : (tensor<3xf32>) -> tensor<4x3xf32>
-  %2 = mhlo.atan2 %0, %1 : tensor<4x3xf32>
-  // CHECK: return %[[BCAST]]
-  return %2 : tensor<4x3xf32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_2d_binary(%[[ARG0:.*]]: tensor<2x4xi32>, %[[ARG1:.*]]: tensor<2x4xi32>) -> tensor<3x2x4xi32>
-func.func @reorder_broadcast_in_dim_2d_binary(%arg0: tensor<2x4xi32>, %arg1: tensor<2x4xi32>) -> tensor<3x2x4xi32> {
-  // CHECK: %[[POWER:.*]] = mhlo.power %[[ARG0]], %[[ARG1]] : tensor<2x4xi32>
-  // CHECK: %[[BCAST:.*]] = "mhlo.broadcast_in_dim"(%[[POWER]]) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xi32>) -> tensor<3x2x4xi32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xi32>) -> tensor<3x2x4xi32>
-  %1 = "mhlo.broadcast_in_dim"(%arg1) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xi32>) -> tensor<3x2x4xi32>
-  %2 = mhlo.power %0, %1 : tensor<3x2x4xi32>
-  // CHECK: return %[[BCAST]]
-  return %2 : tensor<3x2x4xi32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_scalar_unary(%[[ARG0:.*]]: tensor<f32>)
-func.func @reorder_broadcast_in_dim_scalar_unary(%arg0: tensor<f32>) -> (tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>) {
-  // CHECK: %[[ABS:.*]] = mhlo.abs %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[ABS]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[CEIL:.*]] = mhlo.ceil %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[CEIL]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[COSINE:.*]] = mhlo.cosine %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[COSINE]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[EXP:.*]] = mhlo.exponential %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[EXP]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[FLOOR:.*]] = mhlo.floor %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[FLOOR]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[LOG:.*]] = mhlo.log %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[LOG]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[NEG:.*]] = mhlo.negate %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[NEG]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[ROUND:.*]] = mhlo.round_nearest_afz %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[ROUND]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[RSQRT:.*]] = mhlo.rsqrt %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[RSQRT]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[SIGN:.*]] = mhlo.sign %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SIGN]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[SINE:.*]] = mhlo.sine %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SINE]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[SQRT:.*]] = mhlo.sqrt %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[SQRT]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[TANH:.*]] = mhlo.tanh %[[ARG0]] : tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[TANH]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %1 = mhlo.abs %0 : tensor<1x8x8x64xf32>
-  %2 = mhlo.ceil %0 : tensor<1x8x8x64xf32>
-  %3 = mhlo.cosine %0 : tensor<1x8x8x64xf32>
-  %4 = mhlo.exponential %0 : tensor<1x8x8x64xf32>
-  %5 = mhlo.floor %0 : tensor<1x8x8x64xf32>
-  %6 = mhlo.log %0 : tensor<1x8x8x64xf32>
-  %7 = mhlo.negate %0 : tensor<1x8x8x64xf32>
-  %8 = mhlo.round_nearest_afz %0 : tensor<1x8x8x64xf32>
-  %9 = mhlo.rsqrt %0 : tensor<1x8x8x64xf32>
-  %10 = mhlo.sign %0 : tensor<1x8x8x64xf32>
-  %11 = mhlo.sine %0 : tensor<1x8x8x64xf32>
-  %12 = mhlo.sqrt %0 : tensor<1x8x8x64xf32>
-  %13 = mhlo.tanh %0 : tensor<1x8x8x64xf32>
-  return %1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13: tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_1d_unary(%[[ARG0:.*]]: tensor<3xf32>) -> tensor<4x3xf32>
-func.func @reorder_broadcast_in_dim_1d_unary(%arg0: tensor<3xf32>) -> tensor<4x3xf32> {
-  // CHECK: %[[COS:.*]] = mhlo.cosine %[[ARG0]] : tensor<3xf32>
-  // CHECK: %[[BCAST:.*]] = "mhlo.broadcast_in_dim"(%[[COS]]) {broadcast_dimensions = dense<1> : tensor<1xi64>} : (tensor<3xf32>) -> tensor<4x3xf32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[1]> : tensor<1xi64>} : (tensor<3xf32>) -> tensor<4x3xf32>
-  %1 = mhlo.cosine %0 : tensor<4x3xf32>
-  // CHECK: return %[[BCAST]]
-  return %1 : tensor<4x3xf32>
-}
-
-// -----
-
-// CHECK: @reorder_in_dim_2d_unary(%[[ARG0:.*]]: tensor<2x4xf32>) -> tensor<3x2x4xf32>
-func.func @reorder_in_dim_2d_unary(%arg0: tensor<2x4xf32>) -> tensor<3x2x4xf32> {
-  // CHECK: %[[LOG:.*]] = mhlo.log %[[ARG0]] : tensor<2x4xf32>
-  // CHECK: %[[BCAST:.*]] = "mhlo.broadcast_in_dim"(%[[LOG]]) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xf32>) -> tensor<3x2x4xf32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xf32>) -> tensor<3x2x4xf32>
-  %1 = mhlo.log %0 : tensor<3x2x4xf32>
-  // CHECK: return %[[BCAST]]
-  return %1 : tensor<3x2x4xf32>
-}
-
-// -----
-
-// CHECK: @reorder_broadcast_in_dim_scalar_unary_diff_type(%[[ARG0:.*]]: tensor<complex<f32>>) -> (tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>)
-func.func @reorder_broadcast_in_dim_scalar_unary_diff_type(%arg0: tensor<complex<f32>>) -> (tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>) {
-  // CHECK: %[[REAL:.*]] = mhlo.real %[[ARG0]] : (tensor<complex<f32>>) -> tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[REAL]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  // CHECK: %[[IMAG:.*]] = mhlo.imag %[[ARG0]] : (tensor<complex<f32>>) -> tensor<f32>
-  // CHECK: "mhlo.broadcast_in_dim"(%[[IMAG]]) {broadcast_dimensions = dense<> : tensor<0xi64>} : (tensor<f32>) -> tensor<1x8x8x64xf32>
-  %0 = "mhlo.broadcast_in_dim"(%arg0) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<complex<f32>>) -> tensor<1x8x8x64xcomplex<f32>>
-  %1 = mhlo.real %0 : (tensor<1x8x8x64xcomplex<f32>>) -> tensor<1x8x8x64xf32>
-  %2 = mhlo.imag %0 : (tensor<1x8x8x64xcomplex<f32>>) -> tensor<1x8x8x64xf32>
-  return %1, %2: tensor<1x8x8x64xf32>, tensor<1x8x8x64xf32>
-}
-
-// -----
-
-func.func @rng_normal(%arg0: tensor<f32>, %arg1: tensor<f32>) -> tensor<3x5xf32> {
-  %shape = mhlo.constant dense<[3, 5]> : tensor<2xi64>
-  %0 = "mhlo.rng"(%arg0, %arg1, %shape) {rng_distribution = #mhlo.rng_distribution<NORMAL>} : (tensor<f32>, tensor<f32>, tensor<2xi64>) -> tensor<3x5xf32>
-  return %0 : tensor<3x5xf32>
-}
-// CHECK-LABEL: func.func @rng_normal
-// CHECK:         %[[ARG0:[a-zA-Z0-9]+]]
-// CHECK:         %[[ARG1:[a-zA-Z0-9]+]]
-// CHECK-DAG:     %{{.*}} = mhlo.constant dense<{{.*}}> : tensor<8xf32>
-// CHECK-DAG:     %{{.*}} = mhlo.constant dense<{{.*}}> : tensor<8xf32>
-// CHECK-DAG:     %{{.*}} = mhlo.constant dense<{{.*}}> : tensor<8xf32>
-// CHECK:         %[[SIGMA:.+]] = "mhlo.broadcast"(%[[ARG1]]) {broadcast_sizes = dense<8> : tensor<1xi64>} : (tensor<f32>) -> tensor<8xf32>
-//
-//                mag = sigma * sqrt(-2.0 * log(u1)) where sqrt values are
-//                constants.
-//
-// CHECK:         %[[MAG:.+]] = mhlo.multiply %[[SIGMA]], %{{.*}} : tensor<8xf32>
-//
-//                z0  = mag * cos(two_pi * u2) + mu;
-//                z1  = mag * sin(two_pi * u2) + mu;
-//
-// CHECK:         %[[MU:.+]] = "mhlo.broadcast"(%[[ARG0]]) {broadcast_sizes = dense<8> : tensor<1xi64>} : (tensor<f32>) -> tensor<8xf32>
-// CHECK:         %[[T1:.+]] = mhlo.multiply %[[MAG]], %{{.*}} : tensor<8xf32>
-// CHECK:         %[[Z0:.+]] = mhlo.add %[[T1:.+]], %[[MU]] : tensor<8xf32>
-// CHECK:         %[[T2:.+]] = mhlo.multiply %[[MAG]], %{{.*}} : tensor<8xf32>
-// CHECK:         %[[Z1:.+]] = mhlo.add %[[T2:.+]], %[[MU]] : tensor<8xf32>
-//
-//                Concate and reshape the output.
-// CHECK:         %[[CON:.+]] = "mhlo.concatenate"(%[[Z0]], %[[Z1]]) {dimension = 0 : i64} : (tensor<8xf32>, tensor<8xf32>) -> tensor<16xf32>
-// CHECK:         %[[SLICE:.+]] = tensor.extract_slice %[[CON]][0] [15] [1] : tensor<16xf32> to tensor<15xf32>
-// CHECK:         %[[RES:.+]] = mhlo.reshape %[[SLICE]] : (tensor<15xf32>) -> tensor<3x5xf32>
-// CHECK:         return %[[RES]]
-
-// -----
-
-func.func @mul_float_bool_cast(%arg0 : tensor<?xi1>, %arg1 : tensor<?xf32>) -> tensor<?xf32> {
-  %0 = mhlo.convert %arg0 : (tensor<?xi1>) -> tensor<?xf32>
-  %1 = "mhlo.multiply"(%0, %arg1) : (tensor<?xf32>, tensor<?xf32>) -> tensor<?xf32>
-  return %1 : tensor<?xf32>
-}
-
-// CHECK-LABEL: @mul_float_bool_cast
-// CHECK: %[[ZERO:.+]] = mhlo.constant dense<0.000000e+00> : tensor<f32>
-// CHECK: %[[BTOF:.+]] = mhlo.convert %arg0 : (tensor<?xi1>) -> tensor<?xf32>
-// CHECK: %[[FTOB:.+]] = mhlo.convert %[[BTOF]] : (tensor<?xf32>) -> tensor<?xi1>
-// CHECK: %[[SHP:.+]] = shape.shape_of %[[BTOF]] : tensor<?xf32> -> tensor<1xindex>
-// CHECK: %[[BROADCAST:.+]] = "mhlo.dynamic_broadcast_in_dim"(%[[ZERO]], %[[SHP]]) {broadcast_dimensions = dense<> : tensor<0xi64>}
-// CHECK: %[[SELECT:.+]] = mhlo.select %[[FTOB]], %arg1, %[[BROADCAST]]
-
-// -----
-
-func.func @mul_float_bool_cast_broadcast(%arg0: tensor<5xi1>, %arg1: tensor<5x6xf32>) -> tensor<5x6xf32> {
-  %0 = mhlo.convert %arg0 : (tensor<5xi1>) -> tensor<5xf32>
-  %1 = "mhlo.broadcast_in_dim"(%0) {broadcast_dimensions = dense<0> : tensor<1xi64>} : (tensor<5xf32>) -> tensor<5x6xf32>
-  %2 = mhlo.multiply %1, %arg1 : tensor<5x6xf32>
-  return %2 : tensor<5x6xf32>
-}
-
-// CHECK-LABEL: @mul_float_bool_cast_broadcast
-// CHECK: mhlo.select
-
-// -----
-
-func.func @mul_float_bool_cast_dyn_broadcast(%arg0: tensor<?xi1>, %arg1: tensor<?x?xf32>) -> tensor<?x?xf32> {
-    %0 = mhlo.convert %arg0 : (tensor<?xi1>) -> tensor<?xf32>
-    %1 = shape.shape_of %arg1 : tensor<?x?xf32> -> tensor<2xindex>
-    %2 = "mhlo.dynamic_broadcast_in_dim"(%0, %1) {broadcast_dimensions = dense<0> : tensor<1xi64>} : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
-    %3 = mhlo.multiply %2, %arg1 : tensor<?x?xf32>
-    return %3 : tensor<?x?xf32>
-}
-
-// CHECK-LABEL: @mul_float_bool_cast_dyn_broadcast
-// CHECK: mhlo.select
-
-// -----
-
-// CHECK-LABEL: @dot_general_fuse_both_with_attrs
-func.func @dot_general_fuse_both_with_attrs(%arg0: tensor<16x64x128xf16>, %arg1: tensor<16x128x3072xf16>) -> tensor<16x64x3072xf32> {
-  %0 = mhlo.convert %arg0 : (tensor<16x64x128xf16>) -> tensor<16x64x128xf32>
-  %1 = mhlo.convert %arg1 : (tensor<16x128x3072xf16>) -> tensor<16x128x3072xf32>
-  // CHECK: "mhlo.dot_general"(%arg0, %arg1)
-    // CHECK-SAME: dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [0], rhs_batching_dimensions = [0], lhs_contracting_dimensions = [2], rhs_contracting_dimensions = [1]>,
-    // CHECK-SAME: precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-    // CHECK-SAME: -> tensor<16x64x3072xf32>
-  %2 = "mhlo.dot_general"(%0, %1) {dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [0], rhs_batching_dimensions = [0], lhs_contracting_dimensions = [2], rhs_contracting_dimensions = [1]>, precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]} : (tensor<16x64x128xf32>, tensor<16x128x3072xf32>) -> tensor<16x64x3072xf32>
-  return %2 : tensor<16x64x3072xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @dot_general_fuse_one
-func.func @dot_general_fuse_one(%arg0: tensor<16x64x128xf64>, %arg1: tensor<16x128x3072xf16>) -> tensor<16x64x3072xf32> {
-  %0 = mhlo.convert %arg0 : (tensor<16x64x128xf64>) -> tensor<16x64x128xf32>
-  %1 = mhlo.convert%arg1 : (tensor<16x128x3072xf16>) -> tensor<16x128x3072xf32>
-  // CHECK: %[[CONVERT:.+]] = mhlo.convert %arg0
-  // CHECK: "mhlo.dot_general"(%[[CONVERT]], %arg1)
-  %2 = "mhlo.dot_general"(%0, %1) {dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [0], rhs_batching_dimensions = [0], lhs_contracting_dimensions = [2], rhs_contracting_dimensions = [1]>, precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]} : (tensor<16x64x128xf32>, tensor<16x128x3072xf32>) -> tensor<16x64x3072xf32>
-  return %2 : tensor<16x64x3072xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @dot_basic
-func.func @dot_basic(%arg0: tensor<4x4xf16>, %arg1: tensor<4x4xf16>) -> tensor<4x4xf32> {
-  %0 = mhlo.convert %arg0 : (tensor<4x4xf16>) -> tensor<4x4xf32>
-  %1 = mhlo.convert %arg1 : (tensor<4x4xf16>) -> tensor<4x4xf32>
-  // CHECK: %[[DOT:.+]] = "mhlo.dot"(%arg0, %arg1)
-  %2 = "mhlo.dot"(%0, %1) {precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]} : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>
-  // CHECK: return %[[DOT]]
-  return %2 : tensor<4x4xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @convolution
-func.func @convolution(%arg0: tensor<16x32x256xbf16>, %arg1: tensor<1x256x256xbf16>) -> tensor<16x32x256xf32> {
-  %cast = mhlo.convert %arg0 : (tensor<16x32x256xbf16>) -> tensor<16x32x256xf32>
-  // CHECK: %[[CONV:.+]] = mhlo.convolution(%arg0, %arg1)
-  // CHECK-SAME: -> tensor<16x32x256xf32>
-  %0 = "mhlo.convolution"(%cast, %arg1) {
-     batch_group_count = 1 : i64,
-     dimension_numbers = #mhlo.conv<[b, 0, f]x[0, i, o]->[b, 0, f]>,
-     feature_group_count = 1 : i64,
-     lhs_dilation = dense<1> : tensor<1xi64>,
-     padding = dense<0> : tensor<1x2xi64>,
-     precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>],
-     rhs_dilation = dense<1> : tensor<1xi64>,
-     window_strides = dense<1> : tensor<1xi64>
-   } : (tensor<16x32x256xf32>, tensor<1x256x256xbf16>) -> tensor<16x32x256xf32>
-  // CHECK: return %[[CONV]]
-  func.return %0 : tensor<16x32x256xf32>
-}
-
-// -----
-
-// CHECK-LABEL: @dynamic_dot_general
-// This verifies non-crashing, the lowering to linalg happens elsewhere.
-func.func @dynamic_dot_general(%arg1: tensor<?x1024x16x64xf32>, %arg2: tensor<?x1024x16x64xf32>) -> tensor<?x16x1024x1024xf32> {
-  %2 = "mhlo.dot_general"(%arg2, %arg1) {dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [0, 2], rhs_batching_dimensions = [0, 2], lhs_contracting_dimensions = [3], rhs_contracting_dimensions = [3]>, precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]} : (tensor<?x1024x16x64xf32>, tensor<?x1024x16x64xf32>) -> tensor<?x16x1024x1024xf32>
-  return %2 : tensor<?x16x1024x1024xf32>
-}
-
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing_canonicalize_dot_general.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing_canonicalize_dot_general.mlir
deleted file mode 100644
index 248c784..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_preprocessing_canonicalize_dot_general.mlir
+++ /dev/null
@@ -1,35 +0,0 @@
-// RUN: iree-opt --split-input-file --verify-diagnostics --iree-mhlo-to-mhlo-preprocessing %s | FileCheck %s
-
-// CHECK-LABEL: @dot_general_2d
-func.func public @dot_general_2d(%arg0: tensor<4x3xf32> {mhlo.sharding = ""}, %arg1: tensor<4x3xf32> {mhlo.sharding = ""}) -> tensor<3xf32> {
-  %0 = "mhlo.dot_general"(%arg0, %arg1) {dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [1], rhs_batching_dimensions = [1], lhs_contracting_dimensions = [0], rhs_contracting_dimensions = [0]>, precision_config = [#mhlo<precision HIGHEST>, #mhlo<precision HIGHEST>]} : (tensor<4x3xf32>, tensor<4x3xf32>) -> tensor<3xf32>
-
-  // CHECK: %[[LHS:.+]] = "mhlo.transpose"(%arg0) {permutation = dense<[1, 0]> : tensor<2xi64>} : (tensor<4x3xf32>) -> tensor<3x4xf32>
-  // CHECK: %[[RHS:.+]] = "mhlo.transpose"(%arg1) {permutation = dense<[1, 0]> : tensor<2xi64>} : (tensor<4x3xf32>) -> tensor<3x4xf32>
-  // CHECK: "mhlo.dot_general"(%[[LHS]], %[[RHS]])
-  // CHECK-SAME: dot_dimension_numbers = #mhlo.dot<
-  // CHECK-SAME: lhs_batching_dimensions = [0]
-  // CHECK-SAME: rhs_batching_dimensions = [0]
-  // CHECK-SAME: lhs_contracting_dimensions = [1]
-  // CHECK-SAME: rhs_contracting_dimensions = [1]>
-  // CHECK-SAME: precision_config = [#mhlo<precision HIGHEST>, #mhlo<precision HIGHEST>]
-  return %0 : tensor<3xf32>
-}
-
-// CHECK-LABEL: @dot_general_4d
-func.func public @dot_general_4d(%arg0: tensor<1x2x3xf32> {mhlo.sharding = ""}, %arg1: tensor<1x4x2x3xf32> {mhlo.sharding = ""}) -> tensor<1x2x4xf32> {
-  %0 = "mhlo.dot_general"(%arg0, %arg1) {dot_dimension_numbers = #mhlo.dot<lhs_batching_dimensions = [0, 1], rhs_batching_dimensions = [0, 2], lhs_contracting_dimensions = [2], rhs_contracting_dimensions = [3]>, precision_config = [#mhlo<precision HIGHEST>, #mhlo<precision HIGHEST>]} : (tensor<1x2x3xf32>, tensor<1x4x2x3xf32>) -> tensor<1x2x4xf32>
-
-  // CHECK: %[[RHS_T:.+]] = "mhlo.transpose"(%arg1) {permutation = dense<[0, 2, 3, 1]> : tensor<4xi64>} : (tensor<1x4x2x3xf32>) -> tensor<1x2x3x4xf32>
-  // CHECK: %[[LHS_R:.+]] = mhlo.reshape %arg0 : (tensor<1x2x3xf32>) -> tensor<2x1x3xf32>
-  // CHECK: %[[RHS_R:.+]] = mhlo.reshape %[[RHS_T]] : (tensor<1x2x3x4xf32>) -> tensor<2x3x4xf32> 
-  // CHECK: %[[DOT:.+]] = "mhlo.dot_general"(%[[LHS_R]], %[[RHS_R]])
-  // CHECK-SAME: dot_dimension_numbers = #mhlo.dot<
-  // CHECK-SAME: lhs_batching_dimensions = [0]
-  // CHECK-SAME: rhs_batching_dimensions = [0]
-  // CHECK-SAME: lhs_contracting_dimensions = [2]
-  // CHECK-SAME: rhs_contracting_dimensions = [1]>
-  // CHECK-SAME: precision_config = [#mhlo<precision HIGHEST>, #mhlo<precision HIGHEST>]
-  // CHECK: mhlo.reshape %[[DOT]] : (tensor<2x1x4xf32>) -> tensor<1x2x4xf32>
-  return %0 : tensor<1x2x4xf32>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_scatter.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_scatter.mlir
deleted file mode 100644
index c7ffead..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/mhlo_to_mhlo_scatter.mlir
+++ /dev/null
@@ -1,295 +0,0 @@
-// RUN: iree-opt --split-input-file --verify-diagnostics --iree-mhlo-to-mhlo-preprocessing %s | FileCheck %s
-
-func.func @scatter_implicit_batch(%arg0: tensor<5x6x7xi32>, %arg1: tensor<2xi32>, %arg2: tensor<7xi32>) -> tensor<5x6x7xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [0], inserted_window_dims = [0, 1], scatter_dims_to_operand_dims = [0, 1]>, unique_indices = true} : (tensor<5x6x7xi32>, tensor<2xi32>, tensor<7xi32>) -> tensor<5x6x7xi32>
-  return %0 : tensor<5x6x7xi32>
-}
-
-// CHECK-LABEL: func.func @scatter_implicit_batch
-// CHECK-DAG: %[[RE_I:.+]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1]] : tensor<2xi32> into tensor<1x2xi32>
-// CHECK-DAG: %[[RE_U:.+]] = tensor.expand_shape %{{.*}} {{\[\[}}0, 1]] : tensor<7xi32> into tensor<1x7xi32>
-// CHECK:     %[[SCATTER:.+]] = "mhlo.scatter"(%{{.*}}, %[[RE_I]], %[[RE_U]])
-// CHECK:       mhlo.return %{{.*}}
-// CHECK:            update_window_dims = [1],
-// CHECK-SAME:       inserted_window_dims = [0, 1]
-// CHECK-SAME:       scatter_dims_to_operand_dims = [0, 1]
-
-// -----
-
-func.func @scatter_implicit_indices(%arg0: tensor<17x11xf32>,
-  %arg1: tensor<7xi32>, %arg2: tensor<7x11xf32>) -> tensor<17x11xf32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<f32>, %arg4: tensor<f32>):
-    %1 = mhlo.add %arg3, %arg4 : tensor<f32>
-    "mhlo.return"(%1) : (tensor<f32>) -> ()
-  }) {indices_are_sorted = false,
-      scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1>,
-      unique_indices = false
-      } : (tensor<17x11xf32>, tensor<7xi32>, tensor<7x11xf32>) -> tensor<17x11xf32>
-  return %0 : tensor<17x11xf32>
-}
-
-// CHECK-LABEL: func.func @scatter_implicit_indices
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg1 {{\[\[}}0, 1]] : tensor<7xi32> into tensor<7x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %[[EXPAND]], %arg2) ({
-// CHECK-NEXT: ^bb0(%[[A0:.+]]: tensor<f32>, %[[A1:.+]]: tensor<f32>):
-// CHECK-NEXT:   %[[ADD:.+]] = mhlo.add %[[A0]], %[[A1]] : tensor<f32>
-// CHECK-NEXT:   mhlo.return %[[ADD]]
-// CHECK-NEXT: })
-// CHECK-SAME: indices_are_sorted = false,
-// CHECK-SAME: scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:   update_window_dims = [1],
-// CHECK-SAME:   inserted_window_dims = [0],
-// CHECK-SAME:   scatter_dims_to_operand_dims = [0],
-// CHECK-SAME:   index_vector_dim = 1>,
-// CHECK-SAME:   unique_indices = false
-
-// -----
-
-func.func @scatter_collapse_batch(%arg0: tensor<1x24x512xi32>,
-    %arg1: tensor<2x3x2xi32>, %arg2: tensor<2x3x512xi32>) -> tensor<1x24x512xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {indices_are_sorted = false,
-      scatter_dimension_numbers = #mhlo.scatter<
-        update_window_dims = [2],
-        inserted_window_dims = [0, 1],
-        scatter_dims_to_operand_dims = [0, 1],
-        index_vector_dim = 2,
-      >,
-      unique_indices = true
-  } : (tensor<1x24x512xi32>, tensor<2x3x2xi32>, tensor<2x3x512xi32>) -> tensor<1x24x512xi32>
-  return %0 : tensor<1x24x512xi32>
-}
-
-// CHECK-LABEL: func.func @scatter_collapse_batch
-// CHECK: %[[COLLAPSE0:.+]] = tensor.collapse_shape %arg1 {{\[\[}}0, 1], [2]] : tensor<2x3x2xi32> into tensor<6x2xi32>
-// CHECK: %[[COLLAPSE1:.+]] = tensor.collapse_shape %arg2 {{\[\[}}0, 1], [2]] : tensor<2x3x512xi32> into tensor<6x512xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %[[COLLAPSE0]], %[[COLLAPSE1]])
-// CHECK: ^bb0(%[[ARG0:.+]]: tensor<i32>, %[[ARG1:.+]]: tensor<i32>):
-// CHECK:   mhlo.return %[[ARG1]]
-// CHECK: }) {
-// CHECK: indices_are_sorted = false,
-// CHECK-SAME: scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME: update_window_dims = [1]
-// CHECK-SAME: inserted_window_dims = [0, 1]
-// CHECK-SAME: scatter_dims_to_operand_dims = [0, 1]
-// CHECK-SAME: index_vector_dim = 1>
-// CHECK-SAME: unique_indices = true
-// CHECK: return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_materialize_index_update(%arg0: tensor<5x1x1xi32>, %arg1: tensor<1x2xi32>, %arg2: tensor<1x4xi32>) -> tensor<5x1x1xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = true,
-    scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1],
-                                              inserted_window_dims = [1, 2],
-                                              scatter_dims_to_operand_dims = [0, 1],
-                                              index_vector_dim = 1>,
-    unique_indices = true} : (tensor<5x1x1xi32>, tensor<1x2xi32>, tensor<1x4xi32>) -> tensor<5x1x1xi32>
-  return %0 : tensor<5x1x1xi32>
-}
-
-// CHECK-LABEL: @scatter_materialize_index_update
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg2 {{\[\[}}0], [1, 2, 3]] : tensor<1x4xi32> into tensor<1x4x1x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %arg1, %[[EXPAND]])
-// CHECK:                   indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:                update_window_dims = [1, 2, 3]
-// CHECK-SAME:                scatter_dims_to_operand_dims = [0, 1]
-// CHECK-SAME:                index_vector_dim = 1>, unique_indices = true
-
-// -----
-
-func.func @scatter_materialize_one_dim(%arg0: tensor<5x1x1xi32>, %arg1: tensor<1x2xi32>, %arg2: tensor<1xi32>) -> tensor<5x1x1xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = true,
-    scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [],
-                                              inserted_window_dims = [0, 1, 2],
-                                              scatter_dims_to_operand_dims = [0, 1],
-                                              index_vector_dim = 1>,
-    unique_indices = true} : (tensor<5x1x1xi32>, tensor<1x2xi32>, tensor<1xi32>) -> tensor<5x1x1xi32>
-  return %0 : tensor<5x1x1xi32>
-}
-
-// CHECK-LABEL: @scatter_materialize_one_dim
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg2 {{\[\[}}0, 1]] : tensor<1xi32> into tensor<1x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %arg1, %[[EXPAND]])
-// CHECK:                   indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:                 update_window_dims = [1]
-// CHECK-SAME:                 inserted_window_dims = [0, 1]
-// CHECK-SAME:                 scatter_dims_to_operand_dims = [0, 1]
-// CHECK-SAME:                 index_vector_dim = 1>, unique_indices = true
-
-// -----
-
-func.func @scatter_materialize_two_dims(%arg0: tensor<5x1x1xi32>, %arg1: tensor<1x1xi32>, %arg2: tensor<1xi32>) -> tensor<5x1x1xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = true,
-    scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [],
-                                              inserted_window_dims = [0, 1, 2],
-                                              scatter_dims_to_operand_dims = [0],
-                                              index_vector_dim = 1>,
-    unique_indices = true} : (tensor<5x1x1xi32>, tensor<1x1xi32>, tensor<1xi32>) -> tensor<5x1x1xi32>
-  return %0 : tensor<5x1x1xi32>
-}
-
-// CHECK-LABEL: @scatter_materialize_two_dims
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg2 {{\[\[}}0, 1, 2]] : tensor<1xi32> into tensor<1x1x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %arg1, %[[EXPAND]])
-// CHECK:                   indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:                 update_window_dims = [1, 2]
-// CHECK-SAME:                 inserted_window_dims = [0]
-// CHECK-SAME:                 scatter_dims_to_operand_dims = [0]
-// CHECK-SAME:                 index_vector_dim = 1>, unique_indices = true
-
-// -----
-
-func.func @scatter_materialize_comprehensive(%arg0: tensor<5x4x1xi32>, %arg1: tensor<1x1xi32>, %arg2: tensor<1x4xi32>) -> tensor<5x4x1xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = true,
-    scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1],
-                                              inserted_window_dims = [0, 2],
-                                              scatter_dims_to_operand_dims = [0],
-                                              index_vector_dim = 1>,
-    unique_indices = true} : (tensor<5x4x1xi32>, tensor<1x1xi32>, tensor<1x4xi32>) -> tensor<5x4x1xi32>
-  return %0 : tensor<5x4x1xi32>
-}
-
-// CHECK-LABEL: @scatter_materialize_comprehensive
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg2 {{\[\[}}0], [1, 2]] : tensor<1x4xi32> into tensor<1x4x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %arg1, %[[EXPAND]])
-// CHECK:                   indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:                 update_window_dims = [1, 2]
-// CHECK-SAME:                 inserted_window_dims = [0]
-// CHECK-SAME:                 scatter_dims_to_operand_dims = [0]
-// CHECK-SAME:                 index_vector_dim = 1>, unique_indices = true
-
-// -----
-
-func.func @scatter_operand_map(%arg0: tensor<5x4x1xi32>, %arg1: tensor<1x2xi32>, %arg2: tensor<1xi32>) -> tensor<5x4x1xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = true,
-    scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [],
-                                              inserted_window_dims = [0, 1, 2],
-                                              scatter_dims_to_operand_dims = [0, 2],
-                                              index_vector_dim = 1>,
-    unique_indices = true} : (tensor<5x4x1xi32>, tensor<1x2xi32>, tensor<1xi32>) -> tensor<5x4x1xi32>
-  return %0 : tensor<5x4x1xi32>
-}
-
-// CHECK-LABEL: @scatter_operand_map
-// CHECK: %[[EXPAND:.+]] = tensor.expand_shape %arg2 {{\[\[}}0, 1, 2]] : tensor<1xi32> into tensor<1x1x1xi32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%arg0, %arg1, %[[EXPAND]])
-// CHECK:                   indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<
-// CHECK-SAME:                 update_window_dims = [1, 2],
-// CHECK-SAME:                 inserted_window_dims = [0],
-// CHECK-SAME:                 scatter_dims_to_operand_dims = [0, 2],
-// CHECK-SAME:                 index_vector_dim = 1>, unique_indices = true
-
-// -----
-
-func.func @scatter_update_transpose(%a: tensor<16x17x8x384xf32>, %b: tensor<15x1xi32>, %c: tensor<16x17x15x384xf32>) -> tensor<16x17x8x384xf32>
-{
-  %out = "mhlo.scatter"(%a, %b, %c) ({
-    ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):
-      %add = mhlo.add %arg0, %arg1 : tensor<f32>
-      mhlo.return %add : tensor<f32>
-    }) {indices_are_sorted = false,
-        scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [0, 1, 3],
-        inserted_window_dims = [2],
-        scatter_dims_to_operand_dims = [2],
-        index_vector_dim = 1>,
-        unique_indices = false} : (tensor<16x17x8x384xf32>, tensor<15x1xi32>, tensor<16x17x15x384xf32>) -> tensor<16x17x8x384xf32>
-  return %out : tensor<16x17x8x384xf32>
-}
-
-// CHECK-LABEL: @scatter_update_transpose
-// CHECK-SAME: %[[ARG0:.+]]: tensor<16x17x8x384xf32>
-// CHECK-SAME: %[[ARG1:.+]]: tensor<15x1xi32>
-// CHECK-SAME: %[[ARG2:.+]]: tensor<16x17x15x384xf32>
-// CHECK:   %[[TRANSPOSE:.+]] = "mhlo.transpose"(%[[ARG2]]) {permutation = dense<[2, 0, 1, 3]> : tensor<4xi64>}
-// CHECK:   %[[EXPANDED:.+]] = tensor.expand_shape %[[TRANSPOSE]]
-// CHECK-NEXT{literal}: [[0], [1], [2, 3], [4]] : tensor<15x16x17x384xf32> into tensor<15x16x17x1x384xf32>
-// CHECK:   %[[SCATTER:.+]] = "mhlo.scatter"(%[[ARG0]], %[[ARG1]], %[[EXPANDED]]) ({
-// CHECK:   ^bb0(%[[ARG3:.+]]: tensor<f32>, %[[ARG4:.+]]: tensor<f32>):
-// CHECK:     %[[ADD:.+]] = mhlo.add %[[ARG3]], %[[ARG4]] : tensor<f32>
-// CHECK:     mhlo.return %[[ADD]] : tensor<f32>
-// CHECK:   }) 
-// CHECK-SAME: indices_are_sorted = false
-// CHECK-SAME: scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1, 2, 3, 4], scatter_dims_to_operand_dims = [2], index_vector_dim = 1>
-// CHECK-SAME: unique_indices = false
-// CHECK:   return %[[SCATTER]]
-
-// -----
-
-func.func @scatter_transpose_indices(%arg0: tensor<1x64x32x640xf32>, %arg1: tensor<1x44xi32>, %arg2: tensor<44x1x64x640xf32>) -> tensor<1x64x32x640xf32> {
-  %0 = "mhlo.transpose"(%arg1) {permutation = dense<[1, 0]> : tensor<2xi64>} : (tensor<1x44xi32>) -> tensor<44x1xi32>
-  %expanded = tensor.expand_shape %arg2 [[0], [1], [2, 3], [4]] : tensor<44x1x64x640xf32> into tensor<44x1x64x1x640xf32>
-  %1 = "mhlo.scatter"(%arg0, %0, %expanded) ({
-  ^bb0(%arg3: tensor<f32>, %arg4: tensor<f32>):
-    %2 = mhlo.add %arg3, %arg4 : tensor<f32>
-    mhlo.return %2 : tensor<f32>
-  }) {indices_are_sorted = false, scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1, 2, 3, 4], scatter_dims_to_operand_dims = [2], index_vector_dim = 1>, unique_indices = false} : (tensor<1x64x32x640xf32>, tensor<44x1xi32>, tensor<44x1x64x1x640xf32>) -> tensor<1x64x32x640xf32>
-  return %1 : tensor<1x64x32x640xf32>
-}
-
-// CHECK-LABEL: @scatter_transpose_indices
-// CHECK-SAME: %[[ARG0:.+]]: tensor<1x64x32x640xf32>
-// CHECK-SAME: %[[ARG1:.+]]: tensor<1x44xi32>
-// CHECK-SAME: %[[ARG2:.+]]: tensor<44x1x64x640xf32>
-// CHECK: %[[TRANSPOSE:.+]] = "mhlo.transpose"(%[[ARG1]]) {permutation = dense<[1, 0]> : tensor<2xi64>}
-// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG2]]
-// CHECK-SAME{literal}: [[0], [1], [2, 3], [4]] : tensor<44x1x64x640xf32> into tensor<44x1x64x1x640xf32>
-// CHECK: %[[SCATTER:.+]] = "mhlo.scatter"(%[[ARG0]], %[[TRANSPOSE]], %[[EXPANDED]])
-// CHECK: ^bb0(%arg3: tensor<f32>, %arg4: tensor<f32>):
-// CHECK:   %2 = mhlo.add %arg3, %arg4 : tensor<f32>
-// CHECK:   mhlo.return %2 : tensor<f32>
-// CHECK: indices_are_sorted = false
-// CHECK-SAME: scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1, 2, 3, 4], scatter_dims_to_operand_dims = [2], index_vector_dim = 1>
-// CHECK-SAME: unique_indices = false
-// CHECK: return %[[SCATTER]] : tensor<1x64x32x640xf32>
-
-// -----
-
-func.func @scatter_i64_indices(%arg0: tensor<5x6x7xi32>, %arg1: tensor<1x2xi64>, %arg2: tensor<1x7xi32>) -> tensor<5x6x7xi32> {
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ({
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):
-    mhlo.return %arg4 : tensor<i32>
-  }) {indices_are_sorted = true, scatter_dimension_numbers = #mhlo.scatter<update_window_dims = [1], inserted_window_dims = [0, 1], scatter_dims_to_operand_dims = [0, 1], index_vector_dim = 1>, unique_indices = true} : (tensor<5x6x7xi32>, tensor<1x2xi64>, tensor<1x7xi32>) -> tensor<5x6x7xi32>
-  return %0 : tensor<5x6x7xi32>
-}
-
-// CHECK-LABEL: func.func @scatter_i64_indices
-// CHECK-SAME: %[[ARG0:.+]]: tensor<5x6x7xi32>
-// CHECK-SAME: %[[ARG1:.+]]: tensor<1x2xi64>
-// CHECK-SAME: %[[ARG2:.+]]: tensor<1x7xi32>
-// CHECK-DAG: %[[CONVERT:.+]] = mhlo.convert %[[ARG1]] : (tensor<1x2xi64>) -> tensor<1x2xi32>
-// CHECK:     %[[SCATTER:.+]] = "mhlo.scatter"(%[[ARG0]], %[[CONVERT]], %[[ARG2]])
-// CHECK:       mhlo.return %{{.*}}
-// CHECK:            update_window_dims = [1],
-// CHECK-SAME:       inserted_window_dims = [0, 1]
-// CHECK-SAME:       scatter_dims_to_operand_dims = [0, 1]
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/missing_legalizations.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/missing_legalizations.mlir
deleted file mode 100644
index 349af8e..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/missing_legalizations.mlir
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-to-linalg-on-tensors --verify-diagnostics %s
-
-// Non-numpy compatible broadcast_dimensions are not supported.
-// Note: This is by design and support is not planned.
-func.func @dynamicNonScalarBroadcastDimensionsSizeMismatch(%arg0: tensor<1x4xf32>, %arg1: tensor<4xf32>) -> tensor<1x4xf32> {
-  // expected-error@+1 {{failed to legalize operation 'chlo.broadcast_add' that was explicitly marked illegal}}
-  %0 = chlo.broadcast_add %arg0, %arg1 {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<1x4xf32>, tensor<4xf32>) -> tensor<1x4xf32>
-  return %0 : tensor<1x4xf32>
-}
-
-// -----
-// Non-numpy compatible broadcast_dimensions are not supported.
-// Note: This is by design and support is not planned.
-func.func @dynamicNonScalarBroadcastDimensionsMismatch(%arg0: tensor<1x4xf32>, %arg1: tensor<4xf32>) -> tensor<1x4xf32> {
-  // expected-error@+1 {{failed to legalize operation 'chlo.broadcast_add' that was explicitly marked illegal}}
-  %0 = chlo.broadcast_add %arg0, %arg1 {broadcast_dimensions = dense<2> : tensor<1xi64>} : (tensor<1x4xf32>, tensor<4xf32>) -> tensor<1x4xf32>
-  return %0 : tensor<1x4xf32>
-}
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/transformation_pipeline.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/transformation_pipeline.mlir
deleted file mode 100644
index 2a6a871..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/transformation_pipeline.mlir
+++ /dev/null
@@ -1,102 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-input-transformation-pipeline %s | FileCheck %s
-
-// CHECK-LABEL: @empty
-func.func @empty() {
-  // CHECK-NEXT: return
-  return
-}
-
-// -----
-
-func.func @mhloElementwiseOps(%arg0 : tensor<4xf32>) -> tensor<4xf32> {
-  %0 = mhlo.add %arg0, %arg0 : tensor<4xf32>
-  %1 = mhlo.subtract %0, %arg0 : tensor<4xf32>
-  %2 = mhlo.multiply %1, %arg0 : tensor<4xf32>
-  return %2 : tensor<4xf32>
-}
-
-// CHECK:      #map = affine_map<(d0) -> (d0)>
-// CHECK-NEXT: module {
-// CHECK-NEXT:   func.func @mhloElementwiseOps(%arg0: tensor<4xf32>) -> tensor<4xf32> {
-// CHECK-NEXT:     %0 = tensor.empty() : tensor<4xf32>
-// CHECK-NEXT:     %1 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} ins(%arg0 : tensor<4xf32>) outs(%0 : tensor<4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %out: f32):
-// CHECK-NEXT:       %6 = arith.addf %[[ARG1]], %[[ARG1]] : f32
-// CHECK-NEXT:       linalg.yield %6 : f32
-// CHECK-NEXT:     } -> tensor<4xf32>
-// CHECK-NEXT:     %2 = tensor.empty() : tensor<4xf32>
-// CHECK-NEXT:     %3 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel"]} ins(%1, %arg0 : tensor<4xf32>, tensor<4xf32>) outs(%2 : tensor<4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %[[ARG2:.*]]: f32, %out: f32):
-// CHECK-NEXT:       %6 = arith.subf %[[ARG1]], %[[ARG2]] : f32
-// CHECK-NEXT:       linalg.yield %6 : f32
-// CHECK-NEXT:     } -> tensor<4xf32>
-// CHECK-NEXT:     %4 = tensor.empty() : tensor<4xf32>
-// CHECK-NEXT:     %5 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel"]} ins(%3, %arg0 : tensor<4xf32>, tensor<4xf32>) outs(%4 : tensor<4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %[[ARG2:.*]]: f32, %out: f32):
-// CHECK-NEXT:       %6 = arith.mulf %[[ARG1]], %[[ARG2]] : f32
-// CHECK-NEXT:       linalg.yield %6 : f32
-// CHECK-NEXT:     } -> tensor<4xf32>
-// CHECK-NEXT:     return %5 : tensor<4xf32>
-// CHECK-NEXT:   }
-// CHECK-NEXT: }
-
-// -----
-
-func.func @interleavedDot(%arg0 : tensor<4x4xf32>) -> tensor<4x4xf32> {
-  %0 = "stablehlo.add"(%arg0, %arg0) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>
-  %1 = "stablehlo.dot"(%0, %arg0) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>
-  %2 = "stablehlo.multiply"(%1, %arg0) : (tensor<4x4xf32>, tensor<4x4xf32>) -> tensor<4x4xf32>
-  return %2 : tensor<4x4xf32>
-}
-
-// CHECK:      #map = affine_map<(d0, d1) -> (d0, d1)>
-// CHECK-NEXT: module {
-// CHECK-NEXT:   func.func @interleavedDot(%arg0: tensor<4x4xf32>) -> tensor<4x4xf32> {
-// CHECK-NEXT:     %cst = arith.constant 0.000000e+00 : f32
-// CHECK-NEXT:     %0 = tensor.empty() : tensor<4x4xf32>
-// CHECK-NEXT:     %1 = linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0 : tensor<4x4xf32>) outs(%0 : tensor<4x4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %out: f32):
-// CHECK-NEXT:       %7 = arith.addf %[[ARG1]], %[[ARG1]] : f32
-// CHECK-NEXT:       linalg.yield %7 : f32
-// CHECK-NEXT:     } -> tensor<4x4xf32>
-// CHECK-NEXT:     %2 = tensor.empty() : tensor<4x4xf32>
-// CHECK-NEXT:     %3 = linalg.fill ins(%cst : f32) outs(%2 : tensor<4x4xf32>) -> tensor<4x4xf32>
-// CHECK-NEXT:     %4 = linalg.matmul ins(%1, %arg0 : tensor<4x4xf32>, tensor<4x4xf32>) outs(%3 : tensor<4x4xf32>) -> tensor<4x4xf32>
-// CHECK-NEXT:     %5 = tensor.empty() : tensor<4x4xf32>
-// CHECK-NEXT:     %6 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%4, %arg0 : tensor<4x4xf32>, tensor<4x4xf32>) outs(%5 : tensor<4x4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %[[ARG2:.*]]: f32, %out: f32):
-// CHECK-NEXT:       %7 = arith.mulf %[[ARG1]], %[[ARG2]] : f32
-// CHECK-NEXT:       linalg.yield %7 : f32
-// CHECK-NEXT:     } -> tensor<4x4xf32>
-// CHECK-NEXT:     return %6 : tensor<4x4xf32>
-// CHECK-NEXT:   }
-// CHECK-NEXT: }
-
-
-// -----
-
-func.func @reduction(%arg0 : tensor<4x8xf32>) -> tensor<4xf32> {
-  %0 = arith.constant dense<0.0> : tensor<f32>
-  %1 = "mhlo.reduce"(%arg0, %0) ( {
-  ^bb0(%arg1 : tensor<f32>, %arg2 : tensor<f32>):
-    %2 = mhlo.add %arg1, %arg2 : tensor<f32>
-    "mhlo.return"(%2) : (tensor<f32>) -> ()
-  }) {dimensions = dense<[1]> : tensor<1xi64>} : (tensor<4x8xf32>, tensor<f32>) -> tensor<4xf32>
-  return %1 : tensor<4xf32>
-}
-
-// CHECK:      #map = affine_map<(d0, d1) -> (d0, d1)>
-// CHECK-NEXT: #map1 = affine_map<(d0, d1) -> (d0)>
-// CHECK-NEXT: module {
-// CHECK-NEXT:   func.func @reduction(%arg0: tensor<4x8xf32>) -> tensor<4xf32> {
-// CHECK-NEXT:     %cst = arith.constant 0.000000e+00 : f32
-// CHECK-NEXT:     %0 = tensor.empty() : tensor<4xf32>
-// CHECK-NEXT:     %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<4xf32>) -> tensor<4xf32>
-// CHECK-NEXT:     %2 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "reduction"]} ins(%arg0 : tensor<4x8xf32>) outs(%1 : tensor<4xf32>) {
-// CHECK-NEXT:     ^bb0(%[[ARG1:.*]]: f32, %[[ARG2:.*]]: f32):
-// CHECK-NEXT:       %3 = arith.addf %[[ARG2]], %[[ARG1]] : f32
-// CHECK-NEXT:       linalg.yield %3 : f32
-// CHECK-NEXT:     } -> tensor<4xf32>
-// CHECK-NEXT:     return %2 : tensor<4xf32>
-// CHECK-NEXT:   }
-// CHECK-NEXT: }
diff --git a/compiler/src/iree/compiler/InputConversion/MHLO/test/verify_compiler_mhlo_input_legality.mlir b/compiler/src/iree/compiler/InputConversion/MHLO/test/verify_compiler_mhlo_input_legality.mlir
deleted file mode 100644
index ffb7998..0000000
--- a/compiler/src/iree/compiler/InputConversion/MHLO/test/verify_compiler_mhlo_input_legality.mlir
+++ /dev/null
@@ -1,31 +0,0 @@
-// RUN: iree-opt --split-input-file --iree-mhlo-verify-compiler-input-legality --verify-diagnostics %s
-
-// expected-error@+1 {{one or more illegal operations were found in the compiler input}}
-module {
-func.func @illegal_chlo(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // expected-note@+1 {{failed to legalize operation 'chlo.broadcast_add' that was explicitly marked illegal}}
-  %0 = chlo.broadcast_add %arg0, %arg1 : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-}
-
-// -----
-// expected-error@+1 {{one or more illegal operations were found in the compiler input}}
-module {
-func.func @illegal_mhlo(%arg0: tensor<4xf32>, %arg1: tensor<4xf32>) -> tensor<4xf32> {
-  // expected-note@+1 {{failed to legalize operation 'mhlo.add' that was explicitly marked illegal}}
-  %0 = mhlo.add %arg0, %arg1 : tensor<4xf32>
-  return %0 : tensor<4xf32>
-}
-}
-
-// -----
-// expected-error@+1 {{one or more illegal operations were found in the compiler input}}
-module {
-func.func @illegal_shape(%arg0: tensor<*xf32>) -> index {
-  // expected-note@+1 {{failed to legalize operation 'shape.shape_of' that was explicitly marked illegal}}
-  %arg_shape = shape.shape_of %arg0 : tensor<*xf32> -> tensor<?xindex>
-  %rank = shape.rank %arg_shape : tensor<?xindex> -> index
-  return %rank : index
-}
-}
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/BUILD.bazel b/compiler/src/iree/compiler/InputConversion/StableHLO/BUILD.bazel
index 7070947..ff0e92c 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/BUILD.bazel
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/BUILD.bazel
@@ -129,6 +129,9 @@
     hdrs = [
         "Passes.h",
     ],
+    defines = [
+        "IREE_HAVE_STABLEHLO_INPUT",
+    ],
     deps = [
         ":PassHeaders",
         ":StableHLOLegalization",
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/CMakeLists.txt b/compiler/src/iree/compiler/InputConversion/StableHLO/CMakeLists.txt
index 26c54f4..f23c246 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/CMakeLists.txt
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/CMakeLists.txt
@@ -134,6 +134,8 @@
     iree::compiler::Dialect::Util::Transforms
     iree::compiler::InputConversion::Common
     iree::compiler::InputConversion::StableHLO::Preprocessing
+  DEFINES
+    "IREE_HAVE_STABLEHLO_INPUT"
   PUBLIC
 )
 
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/LegalizeControlFlow.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/LegalizeControlFlow.cpp
index d414100..c9eaefc 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/LegalizeControlFlow.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/LegalizeControlFlow.cpp
@@ -119,7 +119,8 @@
           extractTensorValue(rewriter, bounds->step), adaptor.getOperands());
 
       rewriter.setInsertionPointToEnd(newForOp.getBody());
-      // Inline while body, and only replace the mhlo.return with an scf.yield.
+      // Inline while body, and only replace the stablehlo.return with an
+      // scf.yield.
       inlineStableHloRegionIntoSCFRegion(rewriter, op.getBody(),
                                          newForOp.getRegion());
       BlockArgument indexArg = newForOp.getRegion().insertArgument(
@@ -149,7 +150,8 @@
     rewriter.replaceOpWithNewOp<scf::ConditionOp>(
         conditionReturn, i1, newWhileOp.getBeforeArguments());
 
-    // Inline while body, and only replace the mhlo.return with an scf.yield.
+    // Inline while body, and only replace the stablehlo.return with an
+    // scf.yield.
     inlineStableHloRegionIntoSCFRegion(rewriter, op.getBody(),
                                        newWhileOp.getAfter());
 
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/MapStableHLOToScalarOp.h b/compiler/src/iree/compiler/InputConversion/StableHLO/MapStableHLOToScalarOp.h
index 2a78aa1..fb25d72 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/MapStableHLOToScalarOp.h
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/MapStableHLOToScalarOp.h
@@ -897,21 +897,6 @@
   }
 };
 
-inline Value mhloAlwaysPropagateNaN(Value v, ValueRange args, Location loc,
-                                    OpBuilder* b) {
-  Type elementType = getElementTypeOrSelf(args.front().getType());
-  if (auto floatType = elementType.dyn_cast<FloatType>()) {
-    Value isnan = b->create<mlir::arith::CmpFOp>(loc, arith::CmpFPredicate::UNO,
-                                                 args[0], args[1]);
-
-    auto nanApfloat = APFloat::getQNaN(floatType.getFloatSemantics());
-    Value nan = getConstantOrSplat(b, loc, args[0].getType(),
-                                   b->getFloatAttr(floatType, nanApfloat));
-    v = b->create<mlir::arith::SelectOp>(loc, isnan, nan, v);
-  }
-  return v;
-}
-
 template <>
 inline Value mapStableHloOpToStdScalarOp<stablehlo::ClampOp>(
     Location loc, ArrayRef<Type> resultTypes, ArrayRef<Type> argTypes,
@@ -1268,7 +1253,7 @@
 }  // namespace impl
 
 struct StableHloOpToStdScalarOp {
-  // Converts mhlo 'op' to linalg and arith ops.
+  // Converts stablehlo 'op' to linalg and arith ops.
   template <typename StableHloOpTy>
   static Value mapOp(StableHloOpTy op, ArrayRef<Type> resultTypes,
                      ValueRange args, OpBuilder* b) {
@@ -1276,8 +1261,8 @@
     return mapOpWithArgTypes(op, resultTypes, argTypes, args, b);
   }
 
-  // Converts mhlo 'op' to linalg and arith ops. The types of 'args' may already
-  // be converted, 'argTypes' are their original types.
+  // Converts stablehlo 'op' to linalg and arith ops. The types of 'args' may
+  // already be converted, 'argTypes' are their original types.
   template <typename StableHloOpTy>
   static Value mapOpWithArgTypes(StableHloOpTy op, ArrayRef<Type> resultTypes,
                                  ArrayRef<Type> argTypes, ValueRange args,
@@ -1296,7 +1281,7 @@
                                            resultTypes, argTypes, args, b);
   }
 
-  // Converts mhlo 'op' to linalg and arith ops.
+  // Converts stablehlo 'op' to linalg and arith ops.
   template <typename StableHloOpTy>
   static Value mapOpOfType(Location loc, ArrayRef<Type> resultTypes,
                            ArrayRef<Type> argTypes,
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/Preprocessing/StableHLOToStableHLO.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/Preprocessing/StableHLOToStableHLO.cpp
index 65864bd..bc61b2e 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/Preprocessing/StableHLOToStableHLO.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/Preprocessing/StableHLOToStableHLO.cpp
@@ -1105,14 +1105,14 @@
 //
 // Rewrites the following pattern (take binary elementwise op as example)
 //
-// %bcastx = "mhlo.broadcast_in_dim"(%x) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
-// %bcasty = "mhlo.broadcast_in_dim"(%y) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
+// %bcastx = "stablehlo.broadcast_in_dim"(%x) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
+// %bcasty = "stablehlo.broadcast_in_dim"(%y) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
 // %result = "BinaryElementwiseOpT"(%bcastx, %bcasty) : (%[[SHAPE_AFTER_BCAST]], %[[SHAPE_AFTER_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
 //
 // into
 //
 // %z = "BinaryElementwiseOpT"(%x, %y) : (%[[SHAPE_BEFORE_BCAST]], %[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_BEFORE_BCAST]]
-// %result = "mhlo.broadcast_in_dim"(%z) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
+// %result = "stablehlo.broadcast_in_dim"(%z) {broadcast_dimensions = %[[BCAST_DIMS]]} : (%[[SHAPE_BEFORE_BCAST]]) -> %[[SHAPE_AFTER_BCAST]]
 //
 // clang-format on
 template <typename ElementwiseOpT>
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalg.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalg.cpp
index 1f852a3..9a03d7a 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalg.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalg.cpp
@@ -243,7 +243,7 @@
   return exprs;
 }
 
-// Convert mhlo.einsum op into linalg.generic.
+// Convert stablehlo.einsum op into linalg.generic.
 // Algorithm in general 3 steps:
 
 // Step1) Dissect entire einsum_config to different operands
@@ -719,8 +719,8 @@
 // broadcast and go directly to `linalg.generic`.
 
 // This also covers the important case of broadcasting a scalar. Ideally the
-// pattern (`mhlo.constant` -> `mhlo.dynamic_broadcast_in_dim`) should be
-// converted to a tensor dialect op similar to TF's `ConstantLikeOp`.
+// pattern (`stablehlo.constant` -> `stablehlo.dynamic_broadcast_in_dim`) should
+// be converted to a tensor dialect op similar to TF's `ConstantLikeOp`.
 class HloDynamicBroadcastInDimConverter
     : public OpConversionPattern<mlir::stablehlo::DynamicBroadcastInDimOp> {
  public:
@@ -1069,7 +1069,7 @@
   }
 };
 
-// Lowers mhlo.RealDynamicSliceOp to tensor.extract_slice and other
+// Lowers stablehlo.RealDynamicSliceOp to tensor.extract_slice and other
 // arith/tensor dialect ops.
 class RealDynamicSliceConverter
     : public OpConversionPattern<mlir::stablehlo::RealDynamicSliceOp> {
@@ -1573,7 +1573,7 @@
       int64_t size = std::get<1>(en.value());
       sizes.push_back(rewriter.getI64IntegerAttr(size));
 
-      // By mhlo.DynamicSlice definition:
+      // By stablehlo.DynamicSlice definition:
       //   `start_indices[i] = clamp(start_indices[i],
       //       0, operand.dimension_size[i] - size_indices[i])`
       Value startIndex = extractIndexFromTensor(
@@ -1640,7 +1640,7 @@
     SmallVector<OpFoldResult, 3> startIndices;
     Value zero = rewriter.create<arith::ConstantIndexOp>(loc, 0);
     for (const auto& en : llvm::enumerate(adaptor.getStartIndices())) {
-      // By mhlo.DynamicUpdateSlice definition:
+      // By stablehlo.DynamicUpdateSlice definition:
       //   `start_indices[i] = clamp(start_indices[i],
       //       0, operand.dimension_size[i] - update.dimension_size[i])`
       Value startIndex = extractIndexFromTensor(
@@ -2036,7 +2036,7 @@
     }
 
     // The first linalg.generic operation computes the relevant index over
-    // window for the defined mhlo.select_and_scatter. This involves
+    // window for the defined stablehlo.select_and_scatter. This involves
     // iterating over the window of the operand a computing the index.
     // Rather than storing N indices we compute the row major identifier
     // in the window, to specify which location should be scattered to.
@@ -2116,7 +2116,8 @@
     rewriter.cloneRegionBefore(op.getSelect(), reduceRegion,
                                reduceRegion.end());
 
-    // This includes convert `mhlo` scalar-tensor regions to `linalg` scalars.
+    // This includes convert `stablehlo` scalar-tensor regions to `linalg`
+    // scalars.
     TypeConverter::SignatureConversion reduceSignConverter(4);
     reduceSignConverter.addInputs(0, srcETy);
     reduceSignConverter.addInputs(srcETy);
@@ -2166,7 +2167,7 @@
         b.create<arith::SelectOp>(selectPred, selectInVal, selectOutVal);
     b.create<linalg::YieldOp>(ValueRange{selectedValue, selectedIdx});
 
-    // Original terminator is an mhlo.return we no longer need.
+    // Original terminator is an stablehlo.return we no longer need.
     rewriter.eraseOp(reduceTerminator);
     b.setInsertionPoint(op);
 
@@ -2384,7 +2385,7 @@
   }
 };
 
-/// Converts mhlo.pad operation to tensor.pad or tensor.insert_slice.
+/// Converts stablehlo.pad operation to tensor.pad or tensor.insert_slice.
 struct PadOpConversion : public OpConversionPattern<mlir::stablehlo::PadOp> {
   using OpConversionPattern::OpConversionPattern;
 
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgPointwise.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgPointwise.cpp
index fde8bd5..d0326c5 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgPointwise.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgPointwise.cpp
@@ -60,7 +60,7 @@
   int64_t maxRank = getMaxRank(operands);
 
   // Apply only if all operands are scalar or have the same rank. Some ops,
-  // like `mhlo.select`, support implicit broadcasting of scalars.
+  // like `stablehlo.select`, support implicit broadcasting of scalars.
   if (!llvm::all_of(operands, [&](Value v) {
         int64_t r = getRank(v);
         return r == 0 || r == maxRank;
diff --git a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgReduce.cpp b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgReduce.cpp
index cc9d782..ebb366d 100644
--- a/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgReduce.cpp
+++ b/compiler/src/iree/compiler/InputConversion/StableHLO/StableHLOToLinalgReduce.cpp
@@ -279,10 +279,10 @@
     // apply function has a signature with tensor types, this is converted to a
     // function with element types. E.g. the signature "(tensor<f32>,
     // tensor<f32>) -> tensor<f32>" will be converted to "(f32, f32) -> f32".
-    // Also, we need to swap the operands of the function. The mhlo.reduce op
-    // expects the init values to be the first parameters of the apply function,
-    // while the linalg.reduction op expects the init values as the last
-    // parameters of the 'combiner' region apply function.
+    // Also, we need to swap the operands of the function. The stablehlo.reduce
+    // op expects the init values to be the first parameters of the apply
+    // function, while the linalg.reduction op expects the init values as the
+    // last parameters of the 'combiner' region apply function.
     TypeConverter::SignatureConversion signatureConverter(
         linalgOp.getNumDpsInputs() * 2);
     assert(linalgOp.getNumDpsInputs() == linalgOp.getNumDpsInits());
diff --git a/compiler/src/iree/compiler/Pipelines/BUILD.bazel b/compiler/src/iree/compiler/Pipelines/BUILD.bazel
index b003ce0..fb04b06 100644
--- a/compiler/src/iree/compiler/Pipelines/BUILD.bazel
+++ b/compiler/src/iree/compiler/Pipelines/BUILD.bazel
@@ -17,7 +17,6 @@
     srcs = ["Options.cpp"],
     hdrs = ["Options.h"],
     deps = [
-        "//compiler/src/iree/compiler/InputConversion/MHLO",
         "//compiler/src/iree/compiler/InputConversion/StableHLO",
         "//compiler/src/iree/compiler/InputConversion/TMTensor",
         "//compiler/src/iree/compiler/InputConversion/TOSA",
@@ -49,7 +48,6 @@
         "//compiler/src/iree/compiler/Dialect/VM/Transforms",
         "//compiler/src/iree/compiler/InputConversion/Common",
         "//compiler/src/iree/compiler/InputConversion/Common:AutoInputConversionPipeline",
-        "//compiler/src/iree/compiler/InputConversion/MHLO",
         "//compiler/src/iree/compiler/InputConversion/StableHLO",
         "//compiler/src/iree/compiler/InputConversion/TMTensor",
         "//compiler/src/iree/compiler/InputConversion/TOSA",
diff --git a/compiler/src/iree/compiler/Pipelines/CMakeLists.txt b/compiler/src/iree/compiler/Pipelines/CMakeLists.txt
index 525eaa1..76440ca 100644
--- a/compiler/src/iree/compiler/Pipelines/CMakeLists.txt
+++ b/compiler/src/iree/compiler/Pipelines/CMakeLists.txt
@@ -6,8 +6,7 @@
 
 # Enable input dialects based on options.
 set(IREE_INPUT_DEPS "")
-if(IREE_INPUT_MHLO)
-  list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::MHLO)
+if(IREE_INPUT_STABLEHLO)
   list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::StableHLO)
 endif()
 if(IREE_INPUT_TORCH)
diff --git a/compiler/src/iree/compiler/Pipelines/Options.cpp b/compiler/src/iree/compiler/Pipelines/Options.cpp
index 904dc31..2326e98 100644
--- a/compiler/src/iree/compiler/Pipelines/Options.cpp
+++ b/compiler/src/iree/compiler/Pipelines/Options.cpp
@@ -44,19 +44,14 @@
           clEnumValN(InputDialectOptions::Type::auto_detect, "auto",
                      "Analyze the input program to choose conversion.")
   // clang-format off
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
         , clEnumValN(InputDialectOptions::Type::stablehlo,
             "stablehlo",
             "Legalize from StableHLO ops.")
         , clEnumValN(InputDialectOptions::Type::stablehlo_xla,
             "stablehlo_xla",
             "Legalize from StableHLO ops (with XLA cleanup preprocessing). ")
-        , clEnumValN(InputDialectOptions::Type::mhlo_legacy, "mhlo_legacy",
-                     "Legalize from MHLO ops. (Deprecated.)")
-        , clEnumValN(InputDialectOptions::Type::xla_legacy, "xla_legacy",
-            "Legalize from MHLO ops (with XLA cleanup preprocessing). "
-            "(Deprecated.)")
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
         , clEnumValN(InputDialectOptions::Type::tm_tensor, "tm_tensor",
                      "Legalize from TMTensor ops.")
@@ -69,7 +64,7 @@
       // clang-format on
       llvm::cl::cat(category));
 
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
   binder.opt<bool>(
       "iree-input-demote-i64-to-i32", demoteI64ToI32,
       llvm::cl::desc("Converts all i64 ops and values into i32 counterparts."),
@@ -84,7 +79,7 @@
       "iree-input-promote-bf16-to-f32", promoteBF16ToF32,
       llvm::cl::desc("Converts all bf16 ops and values into f32 counterparts."),
       llvm::cl::cat(category));
-#endif
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 }
 
 void HighLevelOptimizationOptions::bindOptions(OptionsBinder &binder) {
diff --git a/compiler/src/iree/compiler/Pipelines/Options.h b/compiler/src/iree/compiler/Pipelines/Options.h
index 40b9504..82d5926 100644
--- a/compiler/src/iree/compiler/Pipelines/Options.h
+++ b/compiler/src/iree/compiler/Pipelines/Options.h
@@ -36,18 +36,13 @@
     none,
     // Analyses the input to determine what input dialect pipeline to use.
     auto_detect,
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
     // Legalizes input defined over StableHLO ops.
     stablehlo,
     // Special case of 'stablehlo' legalization which also performs some XLA
     // preprocessing, e.g., flattening of tuples.
     stablehlo_xla,
-    // Legalizes input defined over MHLO ops. (Deprecated.)
-    mhlo_legacy,
-    // Special case of 'mhlo' legalization which also performs some XLA
-    // cleanup activities. (Deprecated.)
-    xla_legacy,
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
     // Legalizes input defined over TMTensor ops.
     tm_tensor,
diff --git a/compiler/src/iree/compiler/Pipelines/Pipelines.cpp b/compiler/src/iree/compiler/Pipelines/Pipelines.cpp
index 2b78d77..39b2eb1 100644
--- a/compiler/src/iree/compiler/Pipelines/Pipelines.cpp
+++ b/compiler/src/iree/compiler/Pipelines/Pipelines.cpp
@@ -19,10 +19,9 @@
 #include "iree/compiler/Preprocessing/Passes.h"
 #include "iree/compiler/Utils/TracingUtils.h"
 
-#ifdef IREE_HAVE_MHLO_INPUT
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
+#ifdef IREE_HAVE_STABLEHLO_INPUT
 #include "iree/compiler/InputConversion/StableHLO/Passes.h"
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
 #include "iree/compiler/InputConversion/TMTensor/Passes.h"
 #endif  // IREE_HAVE_TORCH_INPUT
@@ -62,19 +61,20 @@
   }
   AutoInputConversionPipelineOptions autoOptions;
 
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
   stablehlo::StableHloOptions stablehloOptions;
   stablehloOptions.demoteI64ToI32 = inputOptions.demoteI64ToI32;
   stablehloOptions.demoteF64ToF32 = inputOptions.demoteF64ToF32;
   stablehloOptions.promoteBF16ToF32 = inputOptions.promoteBF16ToF32;
-#endif
+#endif  // IREE_HAVE_STABLEHLO_INPUT
+
   switch (inputOptions.type) {
     case InputDialectOptions::Type::none:
       break;
     case InputDialectOptions::Type::auto_detect:
       passManager.addPass(createAutoInputConversionPipelinePass(autoOptions));
       break;
-#ifdef IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
     case InputDialectOptions::Type::stablehlo:
       stablehlo::buildStableHLOInputConversionPassPipeline(passManager,
                                                            stablehloOptions);
@@ -83,13 +83,7 @@
       stablehlo::buildStableHLOXLAInputConversionPassPipeline(passManager,
                                                               stablehloOptions);
       break;
-    case InputDialectOptions::Type::mhlo_legacy:
-      MHLO::buildMHLOInputConversionPassPipeline(passManager);
-      break;
-    case InputDialectOptions::Type::xla_legacy:
-      MHLO::buildXLAInputConversionPassPipeline(passManager);
-      break;
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
     case InputDialectOptions::Type::tm_tensor:
       passManager.addNestedPass<func::FuncOp>(
diff --git a/compiler/src/iree/compiler/Preprocessing/Passes.h b/compiler/src/iree/compiler/Preprocessing/Passes.h
index 7768e82..22ed1b5 100644
--- a/compiler/src/iree/compiler/Preprocessing/Passes.h
+++ b/compiler/src/iree/compiler/Preprocessing/Passes.h
@@ -21,7 +21,7 @@
 /// passes specified in textual pass-pipeline format using
 /// `iree-preprocessing-pass-pipeline`. This allows some user control
 /// on the sequence of preprocessing passes to run after conversion from input
-/// dialects like `mhlo`/`tosa` before running the core IREE compilation
+/// dialects like `stablehlo`/`tosa` before running the core IREE compilation
 /// pipelines (starting with the flow pipeline).
 void buildPreprocessingPassPipeline(
     OpPassManager &passManager, const PreprocessingOptions &options,
diff --git a/compiler/src/iree/compiler/Tools/BUILD.bazel b/compiler/src/iree/compiler/Tools/BUILD.bazel
index ca74e5c..799372e 100644
--- a/compiler/src/iree/compiler/Tools/BUILD.bazel
+++ b/compiler/src/iree/compiler/Tools/BUILD.bazel
@@ -37,14 +37,12 @@
     ],
     deps = [
         "//compiler/src/iree/compiler/InputConversion/Common",
-        "//compiler/src/iree/compiler/InputConversion/MHLO",
         "//compiler/src/iree/compiler/InputConversion/StableHLO",
         "//compiler/src/iree/compiler/InputConversion/TMTensor",
         "//compiler/src/iree/compiler/InputConversion/TOSA",
         "@llvm-project//mlir:ConversionPasses",
         "@llvm-project//mlir:IR",
         "@llvm-project//mlir:TosaDialect",
-        "@mlir-hlo//:mlir_hlo",
         "@mlir-hlo//stablehlo:chlo_ops",
         "@mlir-hlo//stablehlo:stablehlo_ops",
         "@torch-mlir-dialects//:TorchMLIRTMTensorDialect",
diff --git a/compiler/src/iree/compiler/Tools/CMakeLists.txt b/compiler/src/iree/compiler/Tools/CMakeLists.txt
index 36aa391..fd1a433 100644
--- a/compiler/src/iree/compiler/Tools/CMakeLists.txt
+++ b/compiler/src/iree/compiler/Tools/CMakeLists.txt
@@ -42,12 +42,9 @@
 
 # Enable input dialects based on options.
 set(IREE_INPUT_DEPS "")
-if(IREE_INPUT_MHLO)
-  list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::MHLO)
+if(IREE_INPUT_STABLEHLO)
   list(APPEND IREE_INPUT_DEPS iree::compiler::InputConversion::StableHLO)
-  list(APPEND IREE_INPUT_DEPS tensorflow::external_mhlo_includes)
   list(APPEND IREE_INPUT_DEPS ChloOps)
-  list(APPEND IREE_INPUT_DEPS MhloDialect)
   list(APPEND IREE_INPUT_DEPS StablehloOps)
 endif()
 if(IREE_INPUT_TORCH)
diff --git a/compiler/src/iree/compiler/Tools/init_input_dialects.cc b/compiler/src/iree/compiler/Tools/init_input_dialects.cc
index 30aae19..d7a3296 100644
--- a/compiler/src/iree/compiler/Tools/init_input_dialects.cc
+++ b/compiler/src/iree/compiler/Tools/init_input_dialects.cc
@@ -6,11 +6,10 @@
 
 #include "iree/compiler/Tools/init_input_dialects.h"
 
-#ifdef IREE_HAVE_MHLO_INPUT
-#include "mhlo/IR/hlo_ops.h"
+#ifdef IREE_HAVE_STABLEHLO_INPUT
 #include "stablehlo/dialect/ChloOps.h"
 #include "stablehlo/dialect/StablehloOps.h"
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
 #include "torch-mlir-dialects/Dialect/TMTensor/IR/TMTensorDialect.h"
 #endif
@@ -22,10 +21,9 @@
 namespace iree_compiler {
 
 void registerInputDialects(DialectRegistry &registry) {
-#ifdef IREE_HAVE_MHLO_INPUT
-  registry.insert<mlir::chlo::ChloDialect, mlir::mhlo::MhloDialect,
-                  mlir::stablehlo::StablehloDialect>();
-#endif  // IREE_HAVE_MHLO_INPUT
+#ifdef IREE_HAVE_STABLEHLO_INPUT
+  registry.insert<mlir::chlo::ChloDialect, mlir::stablehlo::StablehloDialect>();
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
   registry.insert<mlir::torch::TMTensor::TMTensorDialect>();
 #endif  // IREE_HAVE_TORCH_INPUT
diff --git a/compiler/src/iree/compiler/Tools/init_input_passes.cc b/compiler/src/iree/compiler/Tools/init_input_passes.cc
index fe9f41f..ab2faec 100644
--- a/compiler/src/iree/compiler/Tools/init_input_passes.cc
+++ b/compiler/src/iree/compiler/Tools/init_input_passes.cc
@@ -8,10 +8,9 @@
 
 #include "iree/compiler/InputConversion/Common/Passes.h"
 
-#ifdef IREE_HAVE_MHLO_INPUT
-#include "iree/compiler/InputConversion/MHLO/Passes.h"
+#ifdef IREE_HAVE_STABLEHLO_INPUT
 #include "iree/compiler/InputConversion/StableHLO/Passes.h"
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
 #include "iree/compiler/InputConversion/TMTensor/Passes.h"
 #endif  // IREE_HAVE_TORCH_INPUT
@@ -27,10 +26,9 @@
 void registerInputPasses() {
   registerCommonInputConversionPasses();
 
-#ifdef IREE_HAVE_MHLO_INPUT
-  MHLO::registerMHLOConversionPasses();
+#ifdef IREE_HAVE_STABLEHLO_INPUT
   stablehlo::registerStableHLOConversionPasses();
-#endif  // IREE_HAVE_MHLO_INPUT
+#endif  // IREE_HAVE_STABLEHLO_INPUT
 #ifdef IREE_HAVE_TORCH_INPUT
   TMTensor::registerTMTensorConversionPasses();
 #endif
diff --git a/tests/e2e/models/mnist_train_test/mnist_train_test.py b/tests/e2e/models/mnist_train_test/mnist_train_test.py
index d84c406..578ad09 100644
--- a/tests/e2e/models/mnist_train_test/mnist_train_test.py
+++ b/tests/e2e/models/mnist_train_test/mnist_train_test.py
@@ -28,7 +28,7 @@
   compile_file(input_file=os.path.join(artifacts_dir, "mnist_train.mlirbc"),
                output_file=vmfb_file,
                target_backends=[args.target_backend],
-               input_type=InputType.MHLO_LEGACY)
+               input_type=InputType.STABLEHLO)
   return load_vm_flatbuffer_file(vmfb_file, driver=args.driver)
 
 
diff --git a/tests/e2e/xla_ops/BUILD.bazel b/tests/e2e/xla_ops/BUILD.bazel
deleted file mode 100644
index 14c3a9f..0000000
--- a/tests/e2e/xla_ops/BUILD.bazel
+++ /dev/null
@@ -1,496 +0,0 @@
-# Copyright 2019 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
-
-# Tests of end-to-end IREE support for individual ops in the XLA HLO dialect.
-# Each test file should have a name matching the corresponding XLA HLO op and test only the
-# functionality of that op (though may make use of other ops where necessary). Tests should be
-# written using the IREE Check framework and should always pass on the reference VMVX backend.
-# See https://github.com/openxla/iree/blob/main/docs/developers/developing_iree/testing_guide.md#iree-core-end-to-end-tests.
-
-load("//build_tools/bazel:enforce_glob.bzl", "enforce_glob")
-load("//build_tools/bazel:iree_check_test.bzl", "iree_check_single_backend_test_suite")
-
-package(
-    features = ["layering_check"],
-    licenses = ["notice"],  # Apache 2.0
-)
-
-iree_check_single_backend_test_suite(
-    name = "check_cuda_graph",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_bf16.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_fp16.mlir",
-            "exponential_minus_one.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "reverse.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-        exclude = [
-            "fft.mlir",  # TODO(#9583)
-        ],
-    ),
-    compiler_flags = [
-        "--iree-input-type=mhlo_legacy",
-        # TODO(#13984): memset emulation required for graphs.
-        "--iree-stream-emulate-memset",
-    ],
-    driver = "cuda",
-    runner_args = ["--cuda_use_streams=false"],
-    tags = [
-        # CUDA cuInit fails with sanitizer on.
-        "noasan",
-        "nomsan",
-        "notsan",
-        "noubsan",
-        "requires-gpu-nvidia",
-    ],
-    target_backend = "cuda",
-)
-
-# Run cuda tests using stream command buffer
-iree_check_single_backend_test_suite(
-    name = "check_cuda_streams",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_bf16.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_fp16.mlir",
-            "exponential_minus_one.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "reverse.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-        exclude = [
-            "fft.mlir",  # TODO(#9583)
-        ],
-    ),
-    compiler_flags = ["--iree-input-type=mhlo_legacy"],
-    driver = "cuda",
-    runner_args = ["--cuda_use_streams=true"],
-    tags = [
-        # CUDA cuInit fails with sanitizer on.
-        "noasan",
-        "nomsan",
-        "notsan",
-        "noubsan",
-        "requires-gpu-nvidia",
-    ],
-    target_backend = "cuda",
-)
-
-iree_check_single_backend_test_suite(
-    name = "check_llvm-cpu_local-task",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_bf16.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_fp16.mlir",
-            "exponential_minus_one.mlir",
-            "fft.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "reverse.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-    ),
-    compiler_flags = ["--iree-input-type=mhlo_legacy"],
-    driver = "local-task",
-    target_backend = "llvm-cpu",
-)
-
-iree_check_single_backend_test_suite(
-    name = "check_vmvx_local-task",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_minus_one.mlir",
-            "fft.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "reverse.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-        exclude = [
-            "dot_bf16.mlir",  # Missing BF16 support on VMVX buffer ops
-            "exponential_fp16.mlir",
-        ],
-    ),
-    compiler_flags = ["--iree-input-type=mhlo_legacy"],
-    driver = "local-task",
-    target_backend = "vmvx",
-)
-
-iree_check_single_backend_test_suite(
-    name = "check_vulkan-spirv_vulkan",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_bf16.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_minus_one.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-        exclude = [
-            "exponential_fp16.mlir",
-            "fft.mlir",  # TODO(#9583)
-            "reverse.mlir",  #TODO(#12415): disabled due to miscompilation on Pixel 6.
-        ],
-    ),
-    compiler_flags = ["--iree-input-type=mhlo_legacy"],
-    driver = "vulkan",
-    target_backend = "vulkan-spirv",
-)
-
-# Check host features compilation (LLVM backend with host cpu features).
-iree_check_single_backend_test_suite(
-    name = "check_llvm-cpu-host_local-task",
-    srcs = enforce_glob(
-        # keep sorted
-        [
-            "abs.mlir",
-            "add.mlir",
-            "batch_norm_inference.mlir",
-            "bitcast_convert.mlir",
-            "broadcast.mlir",
-            "broadcast_add.mlir",
-            "broadcast_in_dim.mlir",
-            "clamp.mlir",
-            "compare.mlir",
-            "complex.mlir",
-            "concatenate.mlir",
-            "constant.mlir",
-            "convert.mlir",
-            "convolution.mlir",
-            "cosine.mlir",
-            "divide.mlir",
-            "dot.mlir",
-            "dot_bf16.mlir",
-            "dot_general.mlir",
-            "dynamic_slice.mlir",
-            "dynamic_update_slice.mlir",
-            "exponential.mlir",
-            "exponential_fp16.mlir",
-            "exponential_minus_one.mlir",
-            "fft.mlir",
-            "finite.mlir",
-            "floor.mlir",
-            "gather.mlir",
-            "iota.mlir",
-            "log.mlir",
-            "log_plus_one.mlir",
-            "maximum.mlir",
-            "minimum.mlir",
-            "multiply.mlir",
-            "negate.mlir",
-            "pad.mlir",
-            "pow.mlir",
-            "reduce.mlir",
-            "reduce_window.mlir",
-            "remainder.mlir",
-            "reshape.mlir",
-            "reverse.mlir",
-            "rng_normal.mlir",
-            "rng_uniform.mlir",
-            "round.mlir",
-            "rsqrt.mlir",
-            "scatter.mlir",
-            "scatter_dynamic.mlir",
-            "select.mlir",
-            "sine.mlir",
-            "slice.mlir",
-            "sort.mlir",
-            "sqrt.mlir",
-            "subtract.mlir",
-            "tanh.mlir",
-            "torch_index_select.mlir",
-            "transpose.mlir",
-            "while.mlir",
-        ],
-        include = ["*.mlir"],
-    ),
-    compiler_flags = [
-        "--iree-input-type=mhlo_legacy",
-        "--iree-llvmcpu-target-cpu-features=host",
-    ],
-    driver = "local-task",
-    # Building and testing must be on the same architecture, which doesn't work
-    # with remote execution in general.
-    tags = [
-        "hostonly",
-        "local",
-    ],
-    target_backend = "llvm-cpu",
-)
-
-test_suite(
-    name = "check",
-    tests = [
-        ":check_llvm-cpu-host_local-task",
-        ":check_llvm-cpu_local-task",
-        ":check_vmvx_local-task",
-        ":check_vulkan-spirv_vulkan",
-    ],
-)
diff --git a/tests/e2e/xla_ops/CMakeLists.txt b/tests/e2e/xla_ops/CMakeLists.txt
deleted file mode 100644
index c23e05f..0000000
--- a/tests/e2e/xla_ops/CMakeLists.txt
+++ /dev/null
@@ -1,518 +0,0 @@
-################################################################################
-# Autogenerated by build_tools/bazel_to_cmake/bazel_to_cmake.py from           #
-# tests/e2e/xla_ops/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_check_single_backend_test_suite(
-  NAME
-    check_cuda_graph
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_bf16.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_fp16.mlir"
-    "exponential_minus_one.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "cuda"
-  DRIVER
-    "cuda"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-    "--iree-stream-emulate-memset"
-  RUNNER_ARGS
-    "--cuda_use_streams=false"
-  LABELS
-    "noasan"
-    "nomsan"
-    "notsan"
-    "noubsan"
-    "requires-gpu-nvidia"
-)
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_cuda_streams
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_bf16.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_fp16.mlir"
-    "exponential_minus_one.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "cuda"
-  DRIVER
-    "cuda"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-  RUNNER_ARGS
-    "--cuda_use_streams=true"
-  LABELS
-    "noasan"
-    "nomsan"
-    "notsan"
-    "noubsan"
-    "requires-gpu-nvidia"
-)
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_llvm-cpu_local-task
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_bf16.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_fp16.mlir"
-    "exponential_minus_one.mlir"
-    "fft.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "llvm-cpu"
-  DRIVER
-    "local-task"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-)
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_vmvx_local-task
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_minus_one.mlir"
-    "fft.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "vmvx"
-  DRIVER
-    "local-task"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-)
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_vulkan-spirv_vulkan
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_bf16.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_minus_one.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "vulkan-spirv"
-  DRIVER
-    "vulkan"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-)
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_llvm-cpu-host_local-task
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    "clamp.mlir"
-    "compare.mlir"
-    "complex.mlir"
-    "concatenate.mlir"
-    "constant.mlir"
-    "convert.mlir"
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_bf16.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_fp16.mlir"
-    "exponential_minus_one.mlir"
-    "fft.mlir"
-    "finite.mlir"
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    "maximum.mlir"
-    "minimum.mlir"
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    "while.mlir"
-  TARGET_BACKEND
-    "llvm-cpu"
-  DRIVER
-    "local-task"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-    "--iree-llvmcpu-target-cpu-features=host"
-  LABELS
-    "hostonly"
-    "local"
-)
-
-### BAZEL_TO_CMAKE_PRESERVES_ALL_CONTENT_BELOW_THIS_LINE ###
-
-iree_check_single_backend_test_suite(
-  NAME
-    check_webgpu
-  SRCS
-    "abs.mlir"
-    "add.mlir"
-    "batch_norm_inference.mlir"
-    "bitcast_convert.mlir"
-    "broadcast.mlir"
-    "broadcast_add.mlir"
-    "broadcast_in_dim.mlir"
-    # "clamp.mlir"  # TODO(#10906): fix (i8/i16?)
-    # "compare.mlir"  # TODO(#10906): fix (i8/i16?)
-    # "complex.mlir" # TODO(#11054)
-    "concatenate.mlir"
-    "constant.mlir"
-    # "convert.mlir"  # TODO(#10906): fix (i8/i16?)
-    "convolution.mlir"
-    "cosine.mlir"
-    "divide.mlir"
-    "dot.mlir"
-    "dot_general.mlir"
-    "dynamic_slice.mlir"
-    "dynamic_update_slice.mlir"
-    "exponential.mlir"
-    "exponential_fp16.mlir"
-    "exponential_minus_one.mlir"
-    # "fft.mlir"  # TODO(#9583): fix (fft codegen via spirv)
-    # "finite.mlir"  # TODO(#11321): error: value cannot be represented as 'f32': inf
-    "floor.mlir"
-    "gather.mlir"
-    "iota.mlir"
-    "log.mlir"
-    "log_plus_one.mlir"
-    # "maximum.mlir"  # TODO(#10906): fix (i8/i16?)
-    # "minimum.mlir"  # TODO(#10906): fix (i8/i16?)
-    "multiply.mlir"
-    "negate.mlir"
-    "pad.mlir"
-    "pow.mlir"
-    "reduce.mlir"
-    "reduce_window.mlir"
-    "remainder.mlir"
-    "reshape.mlir"
-    "reverse.mlir"
-    "rng_normal.mlir"
-    "rng_uniform.mlir"
-    "round.mlir"
-    "rsqrt.mlir"
-    "scatter.mlir"
-    "scatter_dynamic.mlir"
-    "select.mlir"
-    "sine.mlir"
-    "slice.mlir"
-    "sort.mlir"
-    "sqrt.mlir"
-    "subtract.mlir"
-    "tanh.mlir"
-    "torch_index_select.mlir"
-    "transpose.mlir"
-    # "while.mlir"  # TODO(#12509): WebGPU SPIR-V broken
-  TARGET_BACKEND
-    "webgpu"
-  # Only test compilation for now, the WebGPU driver is not stable/tested yet.
-  # DRIVER
-  #   "webgpu"
-  COMPILER_FLAGS
-    "--iree-input-type=mhlo_legacy"
-    "--iree-codegen-gpu-native-math-precision=true"  # TODO(#11321): Infer/flip default
-)
diff --git a/tests/e2e/xla_ops/abs.mlir b/tests/e2e/xla_ops/abs.mlir
deleted file mode 100644
index cb8c66c..0000000
--- a/tests/e2e/xla_ops/abs.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[-1.0, -2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.abs"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<-4.0> : tensor<f32>
-  %result = "mhlo.abs"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<4.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/add.mlir b/tests/e2e/xla_ops/add.mlir
deleted file mode 100644
index a69cc86..0000000
--- a/tests/e2e/xla_ops/add.mlir
+++ /dev/null
@@ -1,28 +0,0 @@
-func.func @tensor() {
-  %0 = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %1 = util.unfoldable_constant dense<[5.0, 6.0, 7.0, 8.0]> : tensor<4xf32>
-  %result = "mhlo.add"(%0, %1) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[6.0, 8.0, 10.0, 12.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @tensor_4d() {
-  %0 = util.unfoldable_constant dense<[[[[1.0, 2.0], [3.0, 4.0]],
-                                         [[5.0, 6.0], [7.0, 8.0]]],
-                                        [[[9.0, 10.0], [11.0, 12.0]],
-                                         [[13.0, 14.0], [15.0, 16.0]]]]> :
-    tensor<2x2x2x2xf32>
-  %1 = util.unfoldable_constant dense<[[[[1.0, 2.0], [3.0, 4.0]],
-                                         [[5.0, 6.0], [7.0, 8.0]]],
-                                        [[[9.0, 10.0], [11.0, 12.0]],
-                                         [[13.0, 14.0], [15.0, 16.0]]]]> :
-    tensor<2x2x2x2xf32>
-  %result = "mhlo.add"(%0, %1) : (tensor<2x2x2x2xf32>, tensor<2x2x2x2xf32>)
-    -> tensor<2x2x2x2xf32>
-  check.expect_almost_eq_const(%result, dense<[[[[2.0, 4.0], [6.0, 8.0]],
-                                               [[10.0, 12.0], [14.0, 16.0]]],
-                                              [[[18.0, 20.0], [22.0, 24.0]],
-                                               [[26.0, 28.0], [30.0, 32.0]]]]> :
-    tensor<2x2x2x2xf32>) : tensor<2x2x2x2xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/batch_norm_inference.mlir b/tests/e2e/xla_ops/batch_norm_inference.mlir
deleted file mode 100644
index fe569e0..0000000
--- a/tests/e2e/xla_ops/batch_norm_inference.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @batchnorm_inference_4x2() {
-  %x = util.unfoldable_constant dense<[[1.0, 2.0, 3.0, 4.0],[5.0, 6.0, 7.0, 8.0]]> : tensor<2x4xf32>
-  %mean = util.unfoldable_constant dense<[1.0, 1.0, 1.0, 1.0]> : tensor<4xf32>
-  %var = util.unfoldable_constant dense<[2.0, 2.0, 2.0, 2.0]> : tensor<4xf32>
-  %offset = util.unfoldable_constant dense<[1.0, 1.0, 1.0, 1.0]> : tensor<4xf32>
-  %scale = util.unfoldable_constant dense<[1.0, 1.0, 1.0, 1.0]> : tensor<4xf32>
-  %result = "mhlo.batch_norm_inference"(%x, %mean, %var, %offset, %scale) {epsilon = 1.000000e-03 : f32, feature_index = 1 : i64} : (tensor<2x4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>, tensor<4xf32>) -> tensor<2x4xf32>
-  // TODO(gcmn): This should probably be a fuzzier check with round values.
-  check.expect_almost_eq_const(%result, dense<[
-      [2.0, 2.9995, 3.999, 4.9985],
-      [5.998, 6.9975, 7.997, 8.9965]]> : tensor<2x4xf32>) : tensor<2x4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/bitcast_convert.mlir b/tests/e2e/xla_ops/bitcast_convert.mlir
deleted file mode 100644
index 58add39..0000000
--- a/tests/e2e/xla_ops/bitcast_convert.mlir
+++ /dev/null
@@ -1,6 +0,0 @@
-func.func @bitcast() {
-  %input = util.unfoldable_constant dense<0> : tensor<4xi32>
-  %result = "mhlo.bitcast_convert"(%input) : (tensor<4xi32>) -> tensor<4xf32>
-  check.expect_eq_const(%result, dense<0.0> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/broadcast.mlir b/tests/e2e/xla_ops/broadcast.mlir
deleted file mode 100644
index 1bfafe2..0000000
--- a/tests/e2e/xla_ops/broadcast.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-func.func @broadcast_2D_3D() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3, 4],
-                                           [5, 6, 7, 8]]> : tensor<2x4xi32>
-  %result = "mhlo.broadcast"(%input) {broadcast_sizes = dense<3> : tensor<1xi64>} : (tensor<2x4xi32>) -> tensor<3x2x4xi32>
-  check.expect_eq_const(%result, dense<[
-      [[1, 2, 3, 4], [5, 6, 7, 8]],
-      [[1, 2, 3, 4], [5, 6, 7, 8]],
-      [[1, 2, 3, 4], [5, 6, 7, 8]]]> : tensor<3x2x4xi32>) : tensor<3x2x4xi32>
-  return
-}
-
-func.func @broadcast_3D_scalar() {
-  %input = util.unfoldable_constant dense<42> : tensor<i32>
-  %result = "mhlo.broadcast"(%input) {broadcast_sizes = dense<[3, 2, 4]> : tensor<3xi64>} : (tensor<i32>) -> tensor<3x2x4xi32>
-  check.expect_eq_const(%result, dense<[
-      [[42, 42, 42, 42], [42, 42, 42, 42]],
-      [[42, 42, 42, 42], [42, 42, 42, 42]],
-      [[42, 42, 42, 42], [42, 42, 42, 42]]]> : tensor<3x2x4xi32>) : tensor<3x2x4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/broadcast_add.mlir b/tests/e2e/xla_ops/broadcast_add.mlir
deleted file mode 100644
index 3649a21..0000000
--- a/tests/e2e/xla_ops/broadcast_add.mlir
+++ /dev/null
@@ -1,10 +0,0 @@
-func.func @tensor() {
-  %0 = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %1 = util.unfoldable_constant dense<2.0> : tensor<3x4xf32>
-  %result = "chlo.broadcast_add"(%0, %1) : (tensor<4xf32>, tensor<3x4xf32>) -> tensor<3x4xf32>
-  check.expect_almost_eq_const(%result,
-    dense<[[3.0, 4.0, 5.0, 6.0],
-           [3.0, 4.0, 5.0, 6.0],
-           [3.0, 4.0, 5.0, 6.0]]> : tensor<3x4xf32>) : tensor<3x4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/broadcast_in_dim.mlir b/tests/e2e/xla_ops/broadcast_in_dim.mlir
deleted file mode 100644
index 7512007..0000000
--- a/tests/e2e/xla_ops/broadcast_in_dim.mlir
+++ /dev/null
@@ -1,17 +0,0 @@
-func.func @broadcast_in_dim_2D_3D() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3, 4],
-                                           [5, 6, 7, 8]]> : tensor<2x4xi32>
-  %res = "mhlo.broadcast_in_dim"(%input) {broadcast_dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<2x4xi32>) -> tensor<3x2x4xi32>
-  check.expect_eq_const(%res, dense<[
-      [[1, 2, 3, 4], [5, 6, 7, 8]],
-      [[1, 2, 3, 4], [5, 6, 7, 8]],
-      [[1, 2, 3, 4], [5, 6, 7, 8]]]> : tensor<3x2x4xi32>) : tensor<3x2x4xi32>
-  return
-}
-
-func.func @broadcast_in_dim_3D_scalar() {
-  %input = util.unfoldable_constant dense<42> : tensor<i32>
-  %res = "mhlo.broadcast_in_dim"(%input) {broadcast_dimensions = dense<[]> : tensor<0xi64>} : (tensor<i32>) -> tensor<3x2x4xi32>
-  check.expect_eq_const(%res, dense<42> : tensor<3x2x4xi32>) : tensor<3x2x4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/clamp.mlir b/tests/e2e/xla_ops/clamp.mlir
deleted file mode 100644
index b033b47..0000000
--- a/tests/e2e/xla_ops/clamp.mlir
+++ /dev/null
@@ -1,35 +0,0 @@
-func.func @i8() {
-  %min = util.unfoldable_constant dense<[0, 0, 0, 0]> : tensor<4xi8>
-  %val = util.unfoldable_constant dense<[-2, 4, 8, 12]> : tensor<4xi8>
-  %max = util.unfoldable_constant dense<[10, 10, 10, 10]> : tensor<4xi8>
-  %result = "mhlo.clamp"(%min, %val, %max) : (tensor<4xi8>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%result, dense<[0, 4, 8, 10]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @i16() {
-  %min = util.unfoldable_constant dense<[0, 0, 0, 0]> : tensor<4xi16>
-  %val = util.unfoldable_constant dense<[-2, 4, 8, 12]> : tensor<4xi16>
-  %max = util.unfoldable_constant dense<[10, 10, 10, 10]> : tensor<4xi16>
-  %result = "mhlo.clamp"(%min, %val, %max) : (tensor<4xi16>, tensor<4xi16>, tensor<4xi16>) -> tensor<4xi16>
-  check.expect_eq_const(%result, dense<[0, 4, 8, 10]> : tensor<4xi16>) : tensor<4xi16>
-  return
-}
-
-func.func @i32() {
-  %min = util.unfoldable_constant dense<[0, 0, 0, 0]> : tensor<4xi32>
-  %val = util.unfoldable_constant dense<[-2, 4, 8, 12]> : tensor<4xi32>
-  %max = util.unfoldable_constant dense<[10, 10, 10, 10]> : tensor<4xi32>
-  %result = "mhlo.clamp"(%min, %val, %max) : (tensor<4xi32>, tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[0, 4, 8, 10]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @f32() {
-  %min = util.unfoldable_constant dense<[0.0, 0.0, 0.0, 0.0]> : tensor<4xf32>
-  %val = util.unfoldable_constant dense<[-2.0, 4.0, 8.0, 12.0]> : tensor<4xf32>
-  %max = util.unfoldable_constant dense<[10.0, 10.0, 10.0, 10.0]> : tensor<4xf32>
-  %result = "mhlo.clamp"(%min, %val, %max) : (tensor<4xf32>, tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_eq_const(%result, dense<[0.0, 4.0, 8.0, 10.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/compare.mlir b/tests/e2e/xla_ops/compare.mlir
deleted file mode 100644
index b52ad8a..0000000
--- a/tests/e2e/xla_ops/compare.mlir
+++ /dev/null
@@ -1,164 +0,0 @@
-func.func @compare_tensor() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[0, 1, 0, 1]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_scalar() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<5> : tensor<i32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_i8() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i8>
-  %rhs = util.unfoldable_constant dense<5> : tensor<i8>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i8>, tensor<i8>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_i16() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i16>
-  %rhs = util.unfoldable_constant dense<5> : tensor<i16>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i16>, tensor<i16>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_i32() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<5> : tensor<i32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_i64() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i64>
-  %rhs = util.unfoldable_constant dense<5> : tensor<i64>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i64>, tensor<i64>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_f32() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %rhs = util.unfoldable_constant dense<5.0> : tensor<f32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<f32>, tensor<f32>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_f64() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f64>
-  %rhs = util.unfoldable_constant dense<5.0> : tensor<f64>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<f64>, tensor<f64>) -> tensor<i1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<i1>, tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%output, dense<0> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @compare_tensor_odd_length() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7]> : tensor<3xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3]> : tensor<3xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<3xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<3xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<3xi1>, tensor<3xi8>, tensor<3xi8>) -> tensor<3xi8>
-  check.expect_eq_const(%output, dense<[0, 1, 0]> : tensor<3xi8>) : tensor<3xi8>
-  return
-}
-
-func.func @compare_eq() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[0, 1, 0, 1]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_ne() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction NE>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[1, 0, 1, 0]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_lt() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[1, 0, 0, 0]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_le() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction LE>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[1, 1, 0, 1]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_gt() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[0, 0, 1, 0]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
-
-func.func @compare_ge() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.compare"(%lhs, %rhs) {comparison_direction = #mhlo<comparison_direction GE>} : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[0, 1, 1, 1]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
diff --git a/tests/e2e/xla_ops/complex.mlir b/tests/e2e/xla_ops/complex.mlir
deleted file mode 100644
index 63898c5..0000000
--- a/tests/e2e/xla_ops/complex.mlir
+++ /dev/null
@@ -1,23 +0,0 @@
-func.func @math_sin() {
-  %real = util.unfoldable_constant dense<[0., 1., 1., -1.]> : tensor<4xf32>
-  %imag = util.unfoldable_constant dense<[0., 1., -1., 1.]> : tensor<4xf32>
-  %complex = "mhlo.complex"(%real, %imag) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xcomplex<f32>>
-  %result = "mhlo.sine"(%complex) : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>
-  %result_real = "mhlo.real"(%result) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-  %result_imag = "mhlo.imag"(%result) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result_real, dense<[0., 1.29846, 1.29846, -1.29846]> : tensor<4xf32>) : tensor<4xf32>
-  check.expect_almost_eq_const(%result_imag, dense<[0., 0.634964, -0.634964, 0.634964]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @math_exp() {
-  %real = util.unfoldable_constant dense<[0., 1., 1., -1.]> : tensor<4xf32>
-  %imag = util.unfoldable_constant dense<[0., 1., -1., 1.]> : tensor<4xf32>
-  %complex = "mhlo.complex"(%real, %imag) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xcomplex<f32>>
-  %result = "mhlo.exponential"(%complex) : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>
-  %result_real = "mhlo.real"(%result) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-  %result_imag = "mhlo.imag"(%result) : (tensor<4xcomplex<f32>>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result_real, dense<[1., 1.46869, 1.46869, 0.19876]> : tensor<4xf32>) : tensor<4xf32>
-  check.expect_almost_eq_const(%result_imag, dense<[0., 2.28735, -2.28735, 0.30956]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/concatenate.mlir b/tests/e2e/xla_ops/concatenate.mlir
deleted file mode 100644
index 2c0b82e..0000000
--- a/tests/e2e/xla_ops/concatenate.mlir
+++ /dev/null
@@ -1,26 +0,0 @@
-func.func @xla_concatenate() {
-  %c0 = util.unfoldable_constant dense<[[1, 2], [3, 4]]> : tensor<2x2xi32>
-  %c1 = util.unfoldable_constant dense<[[5, 6, 7], [8, 9, 10]]> : tensor<2x3xi32>
-  %c2 = util.unfoldable_constant dense<[[11, 12], [13, 14]]> : tensor<2x2xi32>
-
-  %0 = "mhlo.concatenate"(%c0, %c1) {dimension = 1} : (tensor<2x2xi32>, tensor<2x3xi32>) -> tensor<2x5xi32>
-  check.expect_eq_const(%0, dense<[[1, 2, 5, 6, 7], [3, 4, 8, 9, 10]]> : tensor<2x5xi32>) : tensor<2x5xi32>
-
-  %1 = "mhlo.concatenate"(%c1, %c0) {dimension = 1} : (tensor<2x3xi32>, tensor<2x2xi32>) -> tensor<2x5xi32>
-  check.expect_eq_const(%1, dense<[[5, 6, 7, 1, 2], [8, 9, 10, 3, 4]]> : tensor<2x5xi32>) : tensor<2x5xi32>
-
-  %2 = "mhlo.concatenate"(%c0, %c1, %c2) {dimension = 1} : (tensor<2x2xi32>, tensor<2x3xi32>, tensor<2x2xi32>) -> tensor<2x7xi32>
-  check.expect_eq_const(%2, dense<[[1, 2, 5, 6, 7, 11, 12], [3, 4, 8, 9, 10, 13, 14]]> : tensor<2x7xi32>) : tensor<2x7xi32>
-
-  %3 = "mhlo.concatenate"(%c0, %c2) {dimension = 0} : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<4x2xi32>
-  check.expect_eq_const(%3, dense<[[1, 2], [3, 4], [11, 12], [13, 14]]> : tensor<4x2xi32>) : tensor<4x2xi32>
-  return
-}
-
-func.func @concatenate_cst() {
-  %c0 = util.unfoldable_constant dense<[[1, 2], [3, 4]]> : tensor<2x2xi32>
-  %c1 = mhlo.constant dense<0> : tensor<2x3xi32>
-  %0 = "mhlo.concatenate"(%c0, %c1) {dimension = 1} : (tensor<2x2xi32>, tensor<2x3xi32>) -> tensor<2x5xi32>
-  check.expect_eq_const(%0, dense<[[1, 2, 0, 0, 0], [3, 4, 0, 0, 0]]> : tensor<2x5xi32>) : tensor<2x5xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/constant.mlir b/tests/e2e/xla_ops/constant.mlir
deleted file mode 100644
index 2bea25c..0000000
--- a/tests/e2e/xla_ops/constant.mlir
+++ /dev/null
@@ -1,26 +0,0 @@
-func.func @high_rank () {
-  %dense = mhlo.constant dense<[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]> : tensor<2x2x3xi32>
-  check.expect_eq_const(%dense, dense<[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]> : tensor<2x2x3xi32>) : tensor<2x2x3xi32>
-
-  // %splat = mhlo.constant dense<1> : tensor<2x2x3xi32>
-  // check.expect_eq_const(%splat, dense<1> : tensor<2x2x3xi32>) : tensor<2x2x3xi32>
-  return
-}
-
-// func.func @i8() {
-//   %c = mhlo.constant dense<[1, 2]> : tensor<2xi8>
-//   check.expect_eq_const(%c, dense<[1, 2]> : tensor<2xi8>) : tensor<2xi8>
-//   return
-// }
-
-// func.func @i32 () {
-//   %c = mhlo.constant dense<[1, 2]> : tensor<2xi32>
-//   check.expect_eq_const(%c,  dense<[1, 2]> : tensor<2xi32>) : tensor<2xi32>
-//   return
-// }
-
-// func.func @f32 () {
-//   %c = mhlo.constant dense<[1.1, 2.1]> : tensor<2xf32>
-//   check.expect_almost_eq_const(%c, dense<[1.1, 2.1]> : tensor<2xf32>) : tensor<2xf32>
-//   return
-// }
diff --git a/tests/e2e/xla_ops/convert.mlir b/tests/e2e/xla_ops/convert.mlir
deleted file mode 100644
index c75fe28..0000000
--- a/tests/e2e/xla_ops/convert.mlir
+++ /dev/null
@@ -1,61 +0,0 @@
-func.func @narrow_int_i32_i8() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi32>
-  %res = "mhlo.convert"(%input) : (tensor<3xi32>) -> tensor<3xi8>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi8>) : tensor<3xi8>
-  return
-}
-
-func.func @widen_int_i8_i32() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi8>
-  %res = "mhlo.convert"(%input) : (tensor<3xi8>) -> tensor<3xi32>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @narrow_int_i32_i16() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi32>
-  %res = "mhlo.convert"(%input) : (tensor<3xi32>) -> tensor<3xi16>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi16>) : tensor<3xi16>
-  return
-}
-
-func.func @widen_int_i16_i32() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi16>
-  %res = "mhlo.convert"(%input) : (tensor<3xi16>) -> tensor<3xi32>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @narrow_int_i64_i32() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi64>
-  %res = "mhlo.convert"(%input) : (tensor<3xi64>) -> tensor<3xi32>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @widen_int_i32_i64() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi32>
-  %res = "mhlo.convert"(%input) : (tensor<3xi32>) -> tensor<3xi64>
-  check.expect_eq_const(%res, dense<[-42, 0, 42]> : tensor<3xi64>) : tensor<3xi64>
-  return
-}
-
-func.func @int_to_float() {
-  %input = util.unfoldable_constant dense<[-42, 0, 42]> : tensor<3xi32>
-  %res = "mhlo.convert"(%input) : (tensor<3xi32>) -> tensor<3xf32>
-  check.expect_almost_eq_const(%res, dense<[-42.0, 0.0, 42.0]> : tensor<3xf32>) : tensor<3xf32>
-  return
-}
-
-// TODO(#6160): XLA does not specify the rounding behavior, meaning that we
-// can't test something like -10.5 as that could be -11 (roundf) or -10 (rint
-// with round-to-even mode).
-//
-// For casting rules, see
-// https://www.tensorflow.org/xla/operation_semantics#convertelementtype
-// func.func @float_to_int() {
-//   %input = util.unfoldable_constant dense<[-10.5, -4.4, 4.4, 10.5]> : tensor<4xf32>
-//   %res = "mhlo.convert"(%input) : (tensor<4xf32>) -> tensor<4xi32>
-//   check.expect_eq_const(%res, dense<[-10, -4, 4, 10]> : tensor<4xi32>) : tensor<4xi32>
-//   return
-// }
diff --git a/tests/e2e/xla_ops/convolution.mlir b/tests/e2e/xla_ops/convolution.mlir
deleted file mode 100644
index 8b294dc..0000000
--- a/tests/e2e/xla_ops/convolution.mlir
+++ /dev/null
@@ -1,434 +0,0 @@
-func.func @conv2d_nopadding() {
-  %inputs = util.unfoldable_constant dense<[[
-      [[ 1.0,  2.0], [ 3.0,  4.0], [ 5.0,  6.0], [ 7.0,  8.0]],
-      [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0]],
-      [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0]],
-      [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0]]]]> : tensor<1x4x4x2xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]],
-      [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]],
-      [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-        batch_group_count = 1 : i64,
-        dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-        feature_group_count = 1 : i64,
-        rhs_dilation = dense<1> : tensor<2xi64>,
-        window_strides = dense<1> : tensor<2xi64>} : (tensor<1x4x4x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x2x3x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[
-      [[1310.0],[1466.0],[1622.0]],
-      [[2090.0],[2246.0],[2402.0]]
-  ]]> : tensor<1x2x3x1xf32>) : tensor<1x2x3x1xf32>
-  return
-}
-
-func.func @conv2d_nopadding_batch_feature() {
-  %inputs = util.unfoldable_constant dense<[
-    [[[ 1.0], [ 3.0], [ 5.0], [ 7.0]],
-     [[11.0], [13.0], [15.0], [17.0]],
-     [[21.0], [23.0], [25.0], [27.0]],
-     [[31.0], [33.0], [35.0], [37.0]]],
-    [[[ 2.0], [ 4.0], [ 6.0], [ 8.0]],
-     [[12.0], [14.0], [16.0], [18.0]],
-     [[22.0], [24.0], [26.0], [28.0]],
-     [[32.0], [34.0], [36.0], [38.0]]]
-      ]> : tensor<2x4x4x1xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]],
-      [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]],
-      [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-        batch_group_count = 1 : i64,
-        dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 3,
-          input_feature_dimension = 0,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-        feature_group_count = 1 : i64,
-        rhs_dilation = dense<1> : tensor<2xi64>,
-        window_strides = dense<1> : tensor<2xi64>} : (tensor<2x4x4x1xf32>, tensor<3x2x2x1xf32>) -> tensor<1x2x3x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[
-      [[1310.0],[1466.0],[1622.0]],
-      [[2090.0],[2246.0],[2402.0]]
-  ]]> : tensor<1x2x3x1xf32>) : tensor<1x2x3x1xf32>
-  return
-}
-
-func.func @conv2d_reorder_input_spatial() {
-  %inputs = util.unfoldable_constant dense<[[
-      [[ 1.0,  2.0], [11.0, 12.0], [21.0, 22.0], [31.0, 32.0]],
-      [[ 3.0,  4.0], [13.0, 14.0], [23.0, 24.0], [33.0, 34.0]],
-      [[ 5.0,  6.0], [15.0, 16.0], [25.0, 26.0], [35.0, 36.0]],
-      [[ 7.0,  8.0], [17.0, 18.0], [27.0, 28.0], [37.0, 38.0]]]]> : tensor<1x4x4x2xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]],
-      [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]],
-      [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-        batch_group_count = 1 : i64,
-        dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [2, 1],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-        feature_group_count = 1 : i64,
-        rhs_dilation = dense<1> : tensor<2xi64>,
-        window_strides = dense<1> : tensor<2xi64>} : (tensor<1x4x4x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x2x3x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[
-      [[1310.0],[1466.0],[1622.0]],
-      [[2090.0],[2246.0],[2402.0]]
-  ]]> : tensor<1x2x3x1xf32>) : tensor<1x2x3x1xf32>
-  return
-}
-
-func.func @conv2d_reorder_kernel() {
-  %inputs = util.unfoldable_constant dense<[[
-      [[ 1.0,  2.0], [ 3.0,  4.0], [ 5.0,  6.0], [ 7.0,  8.0]],
-      [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0]],
-      [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0]],
-      [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0]]]]> : tensor<1x4x4x2xf32>
-  %weights = util.unfoldable_constant dense<
-      [[[[ 1.0,  3.0], [ 2.0,  4.0]],
-        [[ 5.0,  7.0], [ 6.0,  8.0]],
-        [[ 9.0, 11.0], [10.0, 12.0]]]]> : tensor<1x3x2x2xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-        batch_group_count = 1 : i64,
-        dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 0,
-          kernel_spatial_dimensions = [1, 3],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-        feature_group_count = 1 : i64,
-        rhs_dilation = dense<1> : tensor<2xi64>,
-        window_strides = dense<1> : tensor<2xi64>} : (tensor<1x4x4x2xf32>, tensor<1x3x2x2xf32>) -> tensor<1x2x3x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[
-      [[1310.0],[1466.0],[1622.0]],
-      [[2090.0],[2246.0],[2402.0]]
-  ]]> : tensor<1x2x3x1xf32>) : tensor<1x2x3x1xf32>
-  return
-}
-
-func.func @conv2d_reorder_output() {
-  %inputs = util.unfoldable_constant dense<[[
-      [[ 1.0,  2.0], [ 3.0,  4.0], [ 5.0,  6.0], [ 7.0,  8.0]],
-      [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0]],
-      [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0]],
-      [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0]]]]> : tensor<1x4x4x2xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]],
-      [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]],
-      [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-        batch_group_count = 1 : i64,
-        dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 2,
-          output_feature_dimension = 0,
-          output_spatial_dimensions = [3, 1]
-        >,
-        feature_group_count = 1 : i64,
-        rhs_dilation = dense<1> : tensor<2xi64>,
-        window_strides = dense<1> : tensor<2xi64>} : (tensor<1x4x4x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x3x1x2xf32>
-  check.expect_almost_eq_const(%res, dense<[[
-      [[1310.0, 2090.0]],
-      [[1466.0, 2246.0]],
-      [[1622.0, 2402.0]]
-      ]]> : tensor<1x3x1x2xf32>) : tensor<1x3x1x2xf32>
-  return
-}
-
-func.func @conv2d_1452x3221_same() {
-  %inputs = util.unfoldable_constant dense<[[
-      [[ 1.0,  2.0], [ 3.0,  4.0], [ 5.0,  6.0], [ 7.0,  8.0], [ 9.0, 10.0]],
-      [[11.0, 12.0], [13.0, 14.0], [15.0, 16.0], [17.0, 18.0], [19.0, 20.0]],
-      [[21.0, 22.0], [23.0, 24.0], [25.0, 26.0], [27.0, 28.0], [29.0, 30.0]],
-      [[31.0, 32.0], [33.0, 34.0], [35.0, 36.0], [37.0, 38.0], [39.0, 40.0]]]]> : tensor<1x4x5x2xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0]], [[ 3.0], [ 4.0]]],
-      [[[ 5.0], [ 6.0]], [[ 7.0], [ 8.0]]],
-      [[[ 9.0], [10.0]], [[11.0], [12.0]]]]> : tensor<3x2x2x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-       batch_group_count = 1 : i64,
-       dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-       feature_group_count = 1 : i64,
-       padding = dense<[[1, 1], [0, 1]]> : tensor<2x2xi64>,
-       rhs_dilation = dense<1> : tensor<2xi64>,
-       window_strides = dense<1> : tensor<2xi64>} :
-       (tensor<1x4x5x2xf32>, tensor<3x2x2x1xf32>) -> tensor<1x4x5x1xf32>
-  check.expect_almost_eq_const(%res,  dense<[[
-    [[ 600.0], [ 736.0], [ 872.0], [1008.0], [ 476.0]],
-    [[1310.0], [1466.0], [1622.0], [1778.0], [ 805.0]],
-    [[2090.0], [2246.0], [2402.0], [2558.0], [1135.0]],
-    [[1080.0], [1152.0], [1224.0], [1296.0], [ 524.0]]]]> : tensor<1x4x5x1xf32>) : tensor<1x4x5x1xf32>
-  return
-}
-
-func.func @conv2d_2451x2311_same() {
-  %inputs = util.unfoldable_constant dense<[
-      [[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0]],
-       [[ 6.0], [ 7.0], [ 8.0], [ 9.0], [10.0]],
-       [[11.0], [12.0], [13.0], [14.0], [15.0]],
-       [[16.0], [17.0], [18.0], [19.0], [20.0]]],
-      [[[21.0], [22.0], [23.0], [24.0], [25.0]],
-       [[26.0], [27.0], [28.0], [29.0], [30.0]],
-       [[31.0], [32.0], [33.0], [34.0], [35.0]],
-       [[36.0], [37.0], [38.0], [39.0], [40.0]]]]> : tensor <2x4x5x1xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[1.0]], [[2.0]], [[3.0]]],
-      [[[4.0]], [[5.0]], [[6.0]]]]> : tensor <2x3x1x1xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-       batch_group_count = 1 : i64,
-       dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-       feature_group_count = 1 : i64,
-       padding = dense<[[0, 1], [1, 1]]> : tensor<2x2xi64>,
-       rhs_dilation = dense<1> : tensor<2xi64>,
-       window_strides = dense<1> : tensor<2xi64>} :
-       (tensor<2x4x5x1xf32>, tensor<2x3x1x1xf32>) -> tensor<2x4x5x1xf32>
-  check.expect_almost_eq_const(%res, dense<[
-    [[[ 80.0], [121.0], [142.0], [163.0], [100.0]],
-     [[160.0], [226.0], [247.0], [268.0], [160.0]],
-     [[240.0], [331.0], [352.0], [373.0], [220.0]],
-     [[ 83.0], [104.0], [110.0], [116.0], [ 59.0]]],
-    [[[400.0], [541.0], [562.0], [583.0], [340.0]],
-     [[480.0], [646.0], [667.0], [688.0], [400.0]],
-     [[560.0], [751.0], [772.0], [793.0], [460.0]],
-     [[183.0], [224.0], [230.0], [236.0], [119.0]]]]> : tensor<2x4x5x1xf32>) : tensor<2x4x5x1xf32>
-  return
-}
-
-func.func @conv2d_no_padding2() {
-  %inputs = util.unfoldable_constant dense<[
-       [[[  1.0,   2.0,   3.0],
-         [  4.0,   5.0,   6.0],
-         [  7.0,   8.0,   9.0],
-         [ 10.0,  11.0,  12.0],
-         [ 13.0,  14.0,  15.0]],
-        [[ 16.0,  17.0,  18.0],
-         [ 19.0,  20.0,  21.0],
-         [ 22.0,  23.0,  24.0],
-         [ 25.0,  26.0,  27.0],
-         [ 28.0,  29.0,  30.0]],
-        [[ 31.0,  32.0,  33.0],
-         [ 34.0,  35.0,  36.0],
-         [ 37.0,  38.0,  39.0],
-         [ 40.0,  41.0,  42.0],
-         [ 43.0,  44.0,  45.0]],
-        [[ 46.0,  47.0,  48.0],
-         [ 49.0,  50.0,  51.0],
-         [ 52.0,  53.0,  54.0],
-         [ 55.0,  56.0,  57.0],
-         [ 58.0,  59.0,  60.0]]],
-       [[[ 61.0,  62.0,  63.0],
-         [ 64.0,  65.0,  66.0],
-         [ 67.0,  68.0,  69.0],
-         [ 70.0,  71.0,  72.0],
-         [ 73.0,  74.0,  75.0]],
-        [[ 76.0,  77.0,  78.0],
-         [ 79.0,  80.0,  81.0],
-         [ 82.0,  83.0,  84.0],
-         [ 85.0,  86.0,  87.0],
-         [ 88.0,  89.0,  90.0]],
-        [[ 91.0,  92.0,  93.0],
-         [ 94.0,  95.0,  96.0],
-         [ 97.0,  98.0,  99.0],
-         [100.0, 101.0, 102.0],
-         [103.0, 104.0, 105.0]],
-        [[106.0, 107.0, 108.0],
-         [109.0, 110.0, 111.0],
-         [112.0, 113.0, 114.0],
-         [115.0, 116.0, 117.0],
-         [118.0, 119.0, 120.0]]]]> : tensor<2x4x5x3xf32>
-  %weights = util.unfoldable_constant dense<[
-      [[[  1.0,   2.0,   3.0,   4.0,   5.0,   6.0],
-        [  7.0,   8.0,   9.0,  10.0,  11.0,  12.0],
-        [ 13.0,  14.0,  15.0,  16.0,  17.0,  18.0]],
-       [[ 19.0,  20.0,  21.0,  22.0,  23.0,  24.0],
-        [ 25.0,  26.0,  27.0,  28.0,  29.0,  30.0],
-        [ 31.0,  32.0,  33.0,  34.0,  35.0,  36.0]],
-       [[ 37.0,  38.0,  39.0,  40.0,  41.0,  42.0],
-        [ 43.0,  44.0,  45.0,  46.0,  47.0,  48.0],
-        [ 49.0,  50.0,  51.0,  52.0,  53.0,  54.0]]],
-      [[[ 55.0,  56.0,  57.0,  58.0,  59.0,  60.0],
-        [ 61.0,  62.0,  63.0,  64.0,  65.0,  66.0],
-        [ 67.0,  68.0,  69.0,  70.0,  71.0,  72.0]],
-       [[ 73.0,  74.0,  75.0,  76.0,  77.0,  78.0],
-        [ 79.0,  80.0,  81.0,  82.0,  83.0,  84.0],
-        [ 85.0,  86.0,  87.0,  88.0,  89.0,  90.0]],
-       [[ 91.0,  92.0,  93.0,  94.0,  95.0,  96.0],
-        [ 97.0,  98.0,  99.0, 100.0, 101.0, 102.0],
-        [103.0, 104.0, 105.0, 106.0, 107.0, 108.0]]]]> : tensor<2x3x3x6xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-       batch_group_count = 1 : i64,
-       dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-       feature_group_count = 1 : i64,
-       rhs_dilation = dense<1> : tensor<2xi64>,
-       window_strides = dense<1> : tensor<2xi64>} :
-       (tensor<2x4x5x3xf32>, tensor<2x3x3x6xf32>) -> tensor<2x3x3x6xf32>
-  check.expect_almost_eq_const(%res, dense<[
-      [[[16065.0,  16290.0,  16515.0,  16740.0,  16965.0,  17190.0],
-        [18873.0,  19152.0,  19431.0,  19710.0,  19989.0,  20268.0],
-        [21681.0,  22014.0,  22347.0,  22680.0,  23013.0,  23346.0]],
-       [[30105.0,  30600.0,  31095.0,  31590.0,  32085.0,  32580.0],
-        [32913.0,  33462.0,  34011.0,  34560.0,  35109.0,  35658.0],
-        [35721.0,  36324.0,  36927.0,  37530.0,  38133.0,  38736.0]],
-       [[44145.0,  44910.0,  45675.0,  46440.0,  47205.0,  47970.0],
-        [46953.0,  47772.0,  48591.0,  49410.0,  50229.0,  51048.0],
-        [49761.0,  50634.0,  51507.0,  52380.0,  53253.0,  54126.0]]],
-      [[[72225.0,  73530.0,  74835.0,  76140.0,  77445.0,  78750.0],
-        [75033.0,  76392.0,  77751.0,  79110.0,  80469.0,  81828.0],
-        [77841.0,  79254.0,  80667.0,  82080.0,  83493.0,  84906.0]],
-       [[86265.0,  87840.0,  89415.0,  90990.0,  92565.0,  94140.0],
-        [89073.0,  90702.0,  92331.0,  93960.0,  95589.0,  97218.0],
-        [91881.0,  93564.0,  95247.0,  96930.0,  98613.0, 100296.0]],
-       [[100305.0, 102150.0, 103995.0, 105840.0, 107685.0, 109530.0],
-        [103113.0, 105012.0, 106911.0, 108810.0, 110709.0, 112608.0],
-        [105921.0, 107874.0, 109827.0, 111780.0, 113733.0, 115686.0]]]]> : tensor<2x3x3x6xf32>) : tensor<2x3x3x6xf32>
-  return
-}
-
-func.func @conv2d_1452x2223_dilated_valid() {
-  %inputs = util.unfoldable_constant dense<
-     [[[[0.09762701,  0.43037874],
-       [ 0.20552675,  0.08976637],
-       [-0.1526904,   0.29178822],
-       [-0.12482557,  0.78354603],
-       [ 0.92732555, -0.23311697]],
-      [[ 0.5834501,   0.05778984],
-       [ 0.13608912,  0.85119325],
-       [-0.85792786, -0.8257414 ],
-       [-0.9595632,   0.6652397 ],
-       [ 0.5563135,   0.74002427]],
-      [[ 0.9572367,   0.59831715],
-       [-0.07704128,  0.56105834],
-       [-0.76345116,  0.27984205],
-       [-0.71329343,  0.88933784],
-       [ 0.04369664, -0.17067613]],
-      [[-0.47088876,  0.5484674 ],
-       [-0.08769934,  0.1368679 ],
-       [-0.9624204,   0.23527099],
-       [ 0.22419144,  0.23386799],
-       [ 0.8874962,   0.3636406 ]]]]> : tensor<1x4x5x2xf32>
-  %weights = util.unfoldable_constant dense<
-    [[[[-0.2809842,  -0.12593609,  0.3952624 ],
-       [-0.8795491,   0.33353344,  0.34127575]],
-      [[-0.5792349,  -0.7421474,  -0.3691433 ],
-       [-0.27257845,  0.14039354, -0.12279698]]],
-     [[[ 0.9767477,  -0.79591036, -0.5822465 ],
-       [-0.677381,    0.30621666, -0.4934168 ]],
-      [[-0.06737845, -0.5111488,  -0.68206084],
-       [-0.7792497,   0.31265917, -0.7236341 ]]]]> : tensor<2x2x2x3xf32>
-  %res = "mhlo.convolution"(%inputs, %weights) {
-    batch_group_count = 1 : i64,
-    dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-    feature_group_count = 1 : i64,
-    padding = dense<0> : tensor<2x2xi64>,
-    rhs_dilation = dense<[2, 1]> : tensor<2xi64>,
-    window_strides = dense<1> : tensor<2xi64>
-  } : (tensor<1x4x5x2xf32>, tensor<2x2x2x3xf32>) -> tensor<1x2x4x3xf32>
-  check.expect_almost_eq_const(%res, dense<
-    [[[[-0.45181108, -0.37253797, -1.1074474 ],
-       [-0.74972206,  0.8691965,   0.21864426],
-       [-1.9352274,   1.6551838,   0.13848126],
-       [-2.296763,    0.32046723, -0.02542188]],
-      [[-1.4578199,   0.59465677,  0.0599021 ],
-       [-0.3617443,   1.4647548,   1.2320882 ],
-       [ 0.04506956,  1.4347346,  -0.22625303],
-       [-1.122044,   -0.41301775, -1.5628793 ]]]]> : tensor<1x2x4x3xf32>) : tensor<1x2x4x3xf32>
-  return
-}
-
-func.func @depthwise_conv_non_1_channel_multiplier() {
-  %arg0 = util.unfoldable_constant dense<1.0> : tensor<2x4x5x2xf32>
-  %arg1 = util.unfoldable_constant dense<1.0> : tensor<2x2x1x6xf32>
-  %res = "mhlo.convolution"(%arg0, %arg1) {
-    batch_group_count = 1 : i64,
-    dimension_numbers = #mhlo.conv<raw
-          input_batch_dimension = 0,
-          input_feature_dimension = 3,
-          input_spatial_dimensions = [1, 2],
-          kernel_input_feature_dimension = 2,
-          kernel_output_feature_dimension = 3,
-          kernel_spatial_dimensions = [0, 1],
-          output_batch_dimension = 0,
-          output_feature_dimension = 3,
-          output_spatial_dimensions = [1, 2]
-        >,
-    feature_group_count = 2 : i64,
-    padding = dense<0> : tensor<2x2xi64>,
-    rhs_dilation = dense<1> : tensor<2xi64>,
-    window_strides = dense<1> : tensor<2xi64>} : (tensor<2x4x5x2xf32>, tensor<2x2x1x6xf32>) -> tensor<2x3x4x6xf32>
-  check.expect_almost_eq_const(%res, dense<4.0> : tensor<2x3x4x6xf32>) : tensor<2x3x4x6xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/cosine.mlir b/tests/e2e/xla_ops/cosine.mlir
deleted file mode 100644
index 16684e1..0000000
--- a/tests/e2e/xla_ops/cosine.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[0.0, 1.0, 1.5, 2.0]> : tensor<4xf32>
-  %result = "mhlo.cosine"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 0.5403, 0.0707, -0.4161]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<3.0> : tensor<f32>
-  %result = "mhlo.cosine"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<-0.99> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/divide.mlir b/tests/e2e/xla_ops/divide.mlir
deleted file mode 100644
index 3a99d86..0000000
--- a/tests/e2e/xla_ops/divide.mlir
+++ /dev/null
@@ -1,15 +0,0 @@
-func.func @i32() {
-  %0 = util.unfoldable_constant dense<[5, 6, 7, 8]> : tensor<4xi32>
-  %1 = util.unfoldable_constant dense<[1, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.divide"(%0, %1) : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[5, 3, 2, 2]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @f32() {
-  %0 = util.unfoldable_constant dense<[5.0, 6.0, 7.0, 8.0]> : tensor<4xf32>
-  %1 = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.divide"(%0, %1) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[5.0, 3.0, 2.333333, 2.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/dot.mlir b/tests/e2e/xla_ops/dot.mlir
deleted file mode 100644
index 11bdd5c..0000000
--- a/tests/e2e/xla_ops/dot.mlir
+++ /dev/null
@@ -1,68 +0,0 @@
-func.func @f32() {
-  %lhs = util.unfoldable_constant dense<[
-    [15.0, 14.0, 13.0],
-    [12.0, 11.0, 10.0],
-    [09.0, 08.0, 07.0],
-    [06.0, 05.0, 04.0],
-    [03.0, 02.0, 01.0]]> : tensor<5x3xf32>
-  %rhs = util.unfoldable_constant dense<[
-    [15.0, 14.0, 13.0, 12.0, 11.0],
-    [10.0, 09.0, 08.0, 07.0, 06.0],
-    [05.0, 04.0, 03.0, 02.0, 01.0]]> : tensor<3x5xf32>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<5x3xf32>, tensor<3x5xf32>) -> tensor<5x5xf32>
-  check.expect_almost_eq_const(%res, dense<[
-    [430.0, 388.0, 346.0, 304.0, 262.0],
-    [340.0, 307.0, 274.0, 241.0, 208.0],
-    [250.0, 226.0, 202.0, 178.0, 154.0],
-    [160.0, 145.0, 130.0, 115.0, 100.0],
-    [70.0, 64.0, 58.0, 52.0, 46.0]]> : tensor<5x5xf32>) : tensor<5x5xf32>
-  return
-}
-
-func.func @i32i32.i32() {
-  %lhs = util.unfoldable_constant dense<3> : tensor<2x4xi32>
-  %rhs = util.unfoldable_constant dense<2> : tensor<4x2xi32>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<2x4xi32>, tensor<4x2xi32>) -> tensor<2x2xi32>
-  check.expect_eq_const(%res, dense<24> : tensor<2x2xi32>) : tensor<2x2xi32>
-  return
-}
-
-func.func @i8i8.i32() {
-  %lhs = util.unfoldable_constant dense<3> : tensor<2x4xi8>
-  %rhs = util.unfoldable_constant dense<2> : tensor<4x2xi8>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<2x4xi8>, tensor<4x2xi8>) -> tensor<2x2xi32>
-  check.expect_eq_const(%res, dense<24> : tensor<2x2xi32>) : tensor<2x2xi32>
-  return
-}
-
-func.func @i16i16.i32() {
-  %lhs = util.unfoldable_constant dense<3> : tensor<2x4xi16>
-  %rhs = util.unfoldable_constant dense<2> : tensor<4x2xi16>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<2x4xi16>, tensor<4x2xi16>) -> tensor<2x2xi32>
-  check.expect_eq_const(%res, dense<24> : tensor<2x2xi32>) : tensor<2x2xi32>
-  return
-}
-
-func.func @large() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<15x16xf32>
-  %rhs = util.unfoldable_constant dense<0.4> : tensor<16x17xf32>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<15x16xf32>, tensor<16x17xf32>) -> tensor<15x17xf32>
-  check.expect_almost_eq_const(%res, dense<6.4> : tensor<15x17xf32>) : tensor<15x17xf32>
-  return
-}
-
-func.func @matvec() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<15x32xf32>
-  %rhs = util.unfoldable_constant dense<0.5> : tensor<32xf32>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<15x32xf32>, tensor<32xf32>) -> tensor<15xf32>
-  check.expect_almost_eq_const(%res, dense<16.0> : tensor<15xf32>) : tensor<15xf32>
-  return
-}
-
-func.func @dot() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<1024xf32>
-  %rhs = util.unfoldable_constant dense<0.5> : tensor<1024xf32>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<1024xf32>, tensor<1024xf32>) -> tensor<f32>
-  check.expect_almost_eq_const(%res, dense<512.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/dot_bf16.mlir b/tests/e2e/xla_ops/dot_bf16.mlir
deleted file mode 100644
index aa5a512..0000000
--- a/tests/e2e/xla_ops/dot_bf16.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-func.func @bf16() {
-  %lhs = util.unfoldable_constant dense<[
-    [15.0, 14.0, 13.0],
-    [12.0, 11.0, 10.0],
-    [09.0, 08.0, 07.0],
-    [06.0, 05.0, 04.0],
-    [03.0, 02.0, 01.0]]> : tensor<5x3xbf16>
-  %rhs = util.unfoldable_constant dense<[
-    [15.0, 14.0, 13.0, 12.0, 11.0],
-    [10.0, 09.0, 08.0, 07.0, 06.0],
-    [05.0, 04.0, 03.0, 02.0, 01.0]]> : tensor<3x5xbf16>
-  %res = "mhlo.dot"(%lhs, %rhs) : (tensor<5x3xbf16>, tensor<3x5xbf16>) -> tensor<5x5xf32>
-  check.expect_almost_eq_const(%res, dense<[
-    [430.0, 388.0, 346.0, 304.0, 262.0],
-    [340.0, 307.0, 274.0, 241.0, 208.0],
-    [250.0, 226.0, 202.0, 178.0, 154.0],
-    [160.0, 145.0, 130.0, 115.0, 100.0],
-    [70.0, 64.0, 58.0, 52.0, 46.0]]> : tensor<5x5xf32>) : tensor<5x5xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/dot_general.mlir b/tests/e2e/xla_ops/dot_general.mlir
deleted file mode 100644
index ccfad7c..0000000
--- a/tests/e2e/xla_ops/dot_general.mlir
+++ /dev/null
@@ -1,157 +0,0 @@
-func.func @dot_general_lower() {
-  %lhs = util.unfoldable_constant dense<[[[0.3, 0.5]]]> : tensor<1x1x2xf32>
-  %rhs = util.unfoldable_constant  dense<[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]> : tensor<2x3xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [],
-      lhs_contracting_dimensions = [2],
-      rhs_batching_dimensions = [],
-      rhs_contracting_dimensions = [0],
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<1x1x2xf32>, tensor<2x3xf32>) -> tensor<1x1x3xf32>
-  check.expect_almost_eq_const(%res, dense<[[[0.23, 0.31, 0.39]]]> : tensor<1x1x3xf32>) : tensor<1x1x3xf32>
-  return
-}
-
-func.func @dot_general_lower_swapped() {
-  %lhs = util.unfoldable_constant  dense<[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]> : tensor<2x3xf32>
-  %rhs = util.unfoldable_constant dense<[[[0.3, 0.5]]]> : tensor<1x1x2xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [],
-      lhs_contracting_dimensions = [0],
-      rhs_batching_dimensions = [],
-      rhs_contracting_dimensions = [2],
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<2x3xf32>, tensor<1x1x2xf32>) -> tensor<3x1x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[[0.23]],[[0.31]],[[0.39]]]> : tensor<3x1x1xf32>) : tensor<3x1x1xf32>
-  return
-}
-
-func.func @dot_general_trivial_batching_dimension() {
-  %lhs = util.unfoldable_constant  dense<[[[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]]> : tensor<1x2x3xf32>
-  %rhs = util.unfoldable_constant dense<[[
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0]]]> : tensor<1x3x4xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [0],
-      lhs_contracting_dimensions = [2],
-      rhs_batching_dimensions = [0],
-      rhs_contracting_dimensions = [1],
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<1x2x3xf32>, tensor<1x3x4xf32>) -> tensor<1x2x4xf32>
-  check.expect_almost_eq_const(%res, dense<[[[0.6, 1.2, 1.8, 2.4],[1.5, 3.0, 4.5, 6.0]]]> : tensor<1x2x4xf32>) : tensor<1x2x4xf32>
-  return
-}
-
-func.func @dot_general_matmul() {
-  %lhs = util.unfoldable_constant dense<3.0> : tensor<2x4xf32>
-  %rhs = util.unfoldable_constant dense<2.0> : tensor<4x2xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [],
-      lhs_contracting_dimensions = [1],
-      rhs_batching_dimensions = [],
-      rhs_contracting_dimensions = [0],
-    >
-  }  : (tensor<2x4xf32>, tensor<4x2xf32>) -> tensor<2x2xf32>
-  check.expect_eq_const(%res, dense<24.0> : tensor<2x2xf32>) : tensor<2x2xf32>
-  return
-}
-
-func.func @dot_general_matmul_i32.i32.i32() {
-  %lhs = util.unfoldable_constant dense<3> : tensor<2x4xi32>
-  %rhs = util.unfoldable_constant dense<2> : tensor<4x2xi32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [],
-      lhs_contracting_dimensions = [1],
-      rhs_batching_dimensions = [],
-      rhs_contracting_dimensions = [0],
-    >
-  } : (tensor<2x4xi32>, tensor<4x2xi32>) -> tensor<2x2xi32>
-  check.expect_eq_const(%res, dense<24> : tensor<2x2xi32>) : tensor<2x2xi32>
-  return
-}
-
-func.func @dot_general_nontrivial_batching_dimension() {
-  %lhs = util.unfoldable_constant dense<[
-    [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]],
-    [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<2x2x3xf32>
-  %rhs = util.unfoldable_constant dense<[[
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0]
-  ], [
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0],
-    [1.0, 2.0, 3.0, 4.0]]]> : tensor<2x3x4xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [0],
-      lhs_contracting_dimensions = [2],
-      rhs_batching_dimensions = [0],
-      rhs_contracting_dimensions = [1],
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<2x2x3xf32>, tensor<2x3x4xf32>) -> tensor<2x2x4xf32>
-  check.expect_almost_eq_const(%res, dense<[
-      [
-          [0.6, 1.2, 1.8, 2.4],
-          [1.5, 3.0, 4.5, 6.0]
-      ], [
-          [6.0, 12.0, 18.0, 24.0],
-          [15.0, 30.0, 45.0, 60.0]]]> : tensor<2x2x4xf32>) : tensor<2x2x4xf32>
-  return
-}
-
-func.func @large_dot_general() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<4x8x128xf32>
-  %rhs = util.unfoldable_constant dense<0.4> : tensor<4x128x16xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [0],
-      lhs_contracting_dimensions = [2],
-      rhs_batching_dimensions = [0],
-      rhs_contracting_dimensions = [1],
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<4x8x128xf32>, tensor<4x128x16xf32>) -> tensor<4x8x16xf32>
-  check.expect_almost_eq_const(%res, dense<51.2> : tensor<4x8x16xf32>) : tensor<4x8x16xf32>
-  return
-}
-
-func.func @dot_general_nontrivial_batching_mutliple_parallel_dimension() {
-  %lhs = util.unfoldable_constant dense<[
-    [[[0.0], [1.0]], [[2.0], [3.0]], [[ 4.0], [ 5.0]]],
-    [[[6.0], [7.0]], [[8.0], [9.0]], [[10.0], [11.0]]]
-  ]> : tensor<2x3x2x1xf32>
-  %rhs = util.unfoldable_constant dense<[
-    [[0.0], [1.0]], [[2.0], [3.0]]
-  ]> : tensor<2x2x1xf32>
-  %res = "mhlo.dot_general"(%lhs, %rhs) {
-    dot_dimension_numbers = #mhlo.dot<
-      lhs_batching_dimensions = [2],
-      rhs_batching_dimensions = [1],
-      lhs_contracting_dimensions = [3],
-      rhs_contracting_dimensions = [2]
-    >,
-    precision_config = [#mhlo<precision DEFAULT>, #mhlo<precision DEFAULT>]
-  } : (tensor<2x3x2x1xf32>, tensor<2x2x1xf32>) -> tensor<2x2x3x2xf32>
-  check.expect_almost_eq_const(%res, dense<[
-    [
-      [[0.0,  0.0], [0.0,  4.0], [0.0,  8.0]],
-      [[0.0, 12.0], [0.0, 16.0], [0.0, 20.0]]
-    ],
-    [
-      [[1.0,  3.0], [3.0,  9.0], [ 5.0, 15.0]],
-      [[7.0, 21.0], [9.0, 27.0], [11.0, 33.0]]
-    ]
-  ]> : tensor<2x2x3x2xf32>) : tensor<2x2x3x2xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/dynamic_slice.mlir b/tests/e2e/xla_ops/dynamic_slice.mlir
deleted file mode 100644
index 86aaaa1..0000000
--- a/tests/e2e/xla_ops/dynamic_slice.mlir
+++ /dev/null
@@ -1,40 +0,0 @@
-func.func @dynamic_slice() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %start1 = util.unfoldable_constant dense<1> : tensor<i64>
-  %start2 = util.unfoldable_constant dense<2> : tensor<i64>
-  %result = "mhlo.dynamic_slice"(%input, %start1, %start2) {
-    slice_sizes = dense<[2, 2]> : tensor<2xi64>
-  } : (tensor<3x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>
-  check.expect_eq_const(%result, dense<[
-      [7, 8],
-      [11, 12]]> : tensor<2x2xi32>) : tensor<2x2xi32>
-  return
-}
-
-func.func @dynamic_unit_slice() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %start1 = util.unfoldable_constant dense<1> : tensor<i64>
-  %start2 = util.unfoldable_constant dense<2> : tensor<i64>
-  %result = "mhlo.dynamic_slice"(%input, %start1, %start2) {
-    slice_sizes = dense<[1, 2]> : tensor<2xi64>
-  } : (tensor<3x4xi32>, tensor<i64>, tensor<i64>) -> tensor<1x2xi32>
-  check.expect_eq_const(%result, dense<[
-      [7, 8]]> : tensor<1x2xi32>) : tensor<1x2xi32>
-  return
-}
-
-func.func @dynamic_1d_slice() {
-  %input = util.unfoldable_constant dense<[1, 2, 3, 4]> : tensor<4xi32>
-  %start1 = util.unfoldable_constant dense<1> : tensor<i64>
-  %result = "mhlo.dynamic_slice"(%input, %start1) {
-    slice_sizes = dense<[2]> : tensor<1xi64>
-  } : (tensor<4xi32>, tensor<i64>) -> tensor<2xi32>
-  check.expect_eq_const(%result, dense<[2, 3]> : tensor<2xi32>) : tensor<2xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/dynamic_update_slice.mlir b/tests/e2e/xla_ops/dynamic_update_slice.mlir
deleted file mode 100644
index 7031373..0000000
--- a/tests/e2e/xla_ops/dynamic_update_slice.mlir
+++ /dev/null
@@ -1,35 +0,0 @@
-func.func @dynamic_update_slice_2x2() {
-  %target = util.unfoldable_constant dense<2> : tensor<3x3xi32>
-  %update = util.unfoldable_constant dense<1> : tensor<2x2xi32>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i32>
-  %result = "mhlo.dynamic_update_slice"(%target, %update, %c0, %c0)
-    : (tensor<3x3xi32>, tensor<2x2xi32>, tensor<i32>, tensor<i32>) -> tensor<3x3xi32>
-  check.expect_eq_const(%result, dense<[
-    [1, 1, 2],
-    [1, 1, 2],
-    [2, 2, 2]]> : tensor<3x3xi32>) : tensor<3x3xi32>
-  return
-}
-
-func.func @dynamic_update_slice_1x3() {
-  %target = util.unfoldable_constant dense<2> : tensor<3x3xi32>
-  %update = util.unfoldable_constant dense<1> : tensor<1x3xi32>
-  %c0 = util.unfoldable_constant dense<0> : tensor<i32>
-  %c1 = util.unfoldable_constant dense<1> : tensor<i32>
-  %result = "mhlo.dynamic_update_slice"(%target, %update, %c1, %c0)
-    : (tensor<3x3xi32>, tensor<1x3xi32>, tensor<i32>, tensor<i32>) -> tensor<3x3xi32>
-  check.expect_eq_const(%result, dense<[
-    [2, 2, 2],
-    [1, 1, 1],
-    [2, 2, 2]]> : tensor<3x3xi32>) : tensor<3x3xi32>
-  return
-}
-
-func.func @into_constant() {
-  %update = util.unfoldable_constant dense<2> : tensor<1xi32>
-  %target = mhlo.constant dense<1> : tensor<4xi32>
-  %index = mhlo.constant dense<0> : tensor<i32>
-  %result = "mhlo.dynamic_update_slice"(%target, %update, %index) : (tensor<4xi32>, tensor<1xi32>, tensor<i32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[2, 1, 1, 1]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/exponential.mlir b/tests/e2e/xla_ops/exponential.mlir
deleted file mode 100644
index d18bbd6..0000000
--- a/tests/e2e/xla_ops/exponential.mlir
+++ /dev/null
@@ -1,27 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[0.0, 1.0, 2.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.exponential"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.7183, 7.3891, 54.5981]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %result = "mhlo.exponential"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<2.7183> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @double() {
-  %input = util.unfoldable_constant dense<1.0> : tensor<f64>
-  %result = "mhlo.exponential"(%input) : (tensor<f64>) -> tensor<f64>
-  check.expect_almost_eq_const(%result, dense<2.7183> : tensor<f64>) : tensor<f64>
-  return
-}
-
-func.func @negative() {
-  %input = util.unfoldable_constant dense<-1.0> : tensor<f32>
-  %result = "mhlo.exponential"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<0.367879> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/exponential_fp16.mlir b/tests/e2e/xla_ops/exponential_fp16.mlir
deleted file mode 100644
index 9a21293..0000000
--- a/tests/e2e/xla_ops/exponential_fp16.mlir
+++ /dev/null
@@ -1,6 +0,0 @@
-func.func @tensor_fp16() {
-  %input = util.unfoldable_constant dense<[0.0, 1.0, 2.0, 4.0]> : tensor<4xf16>
-  %result = "mhlo.exponential"(%input) : (tensor<4xf16>) -> tensor<4xf16>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.7183, 7.3891, 54.5981]> : tensor<4xf16>) : tensor<4xf16>
-  return
-}
diff --git a/tests/e2e/xla_ops/exponential_minus_one.mlir b/tests/e2e/xla_ops/exponential_minus_one.mlir
deleted file mode 100644
index 1c3cb38..0000000
--- a/tests/e2e/xla_ops/exponential_minus_one.mlir
+++ /dev/null
@@ -1,6 +0,0 @@
-func.func @exponential_minus_one() {
-  %input = util.unfoldable_constant dense<[0.0, 0.5, 1.0, -1.0]> : tensor<4xf32>
-  %result = "mhlo.exponential_minus_one"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[0.0, 0.6487213, 1.7182818, -0.6321205]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/fft.mlir b/tests/e2e/xla_ops/fft.mlir
deleted file mode 100644
index e347822..0000000
--- a/tests/e2e/xla_ops/fft.mlir
+++ /dev/null
@@ -1,31 +0,0 @@
-// TODO(hanchung): Add other types of fft tests, e.g. fft, ifft, irfft.
-
-func.func @rfft_1d() {
-  %input = util.unfoldable_constant dense<[
-    9.0, 1.0, 4.5, -0.3, 10.0, -1.0, 5.5, 0.3, 299.0, 3.5, -0.777, 2.0, 1.7,
-    3.5, -4.5, 0.0, 9.0, 1.0, 4.5, -0.3, 10.0, -1.0, 5.5, 0.3, 299.0, 3.5,
-    -0.777, 2.0, 1.7, 3.5, -4.5, 0.0]> : tensor<32xf32>
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<32> : tensor<i64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<32xf32>) -> tensor<17xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<17xcomplex<f32>>) -> tensor<17xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<17xcomplex<f32>>) -> tensor<17xf32>
-  check.expect_almost_eq_const(%1, dense<[666.8460, 0.0, -590.16925, 0.0, 593.4485, 0.0, -579.52875, 0.0, 629.95404, 0.0, -567.1126, 0.0, 591.75146, 0.0, -583.1894, 0.0, 630.846]> : tensor<17xf32>) : tensor<17xf32>
-  check.expect_almost_eq_const(%2, dense<[0.0, 0.0, -23.956373, 0.0, -10.254326, 0.0, -6.1443653, 0.0, -10.0, 0.0, 3.865515, 0.0, 0.63767385, 0.0, 52.453506, 0.0, 0.0]> : tensor<17xf32>) : tensor<17xf32>
-  return
-}
-
-func.func @rfft_2d() {
-  %input = util.unfoldable_constant dense<[[
-    9.0, 1.0, 4.5, -0.3, 10.0, -1.0, 5.5, 0.3, 299.0, 3.5, -0.777, 2.0, 1.7,
-    3.5, -4.5, 0.0, 9.0, 1.0, 4.5, -0.3, 10.0, -1.0, 5.5, 0.3, 299.0, 3.5,
-    -0.777, 2.0, 1.7, 3.5, -4.5, 0.0]]> : tensor<1x32xf32>
-  %0 = "mhlo.fft"(%input) {
-    fft_length = dense<32> : tensor<1xi64>, fft_type = #mhlo<fft_type RFFT>
-  } : (tensor<1x32xf32>) -> tensor<1x17xcomplex<f32>>
-  %1 = "mhlo.real"(%0) : (tensor<1x17xcomplex<f32>>) -> tensor<1x17xf32>
-  %2 = "mhlo.imag"(%0) : (tensor<1x17xcomplex<f32>>) -> tensor<1x17xf32>
-  check.expect_almost_eq_const(%1, dense<[[666.8460, 0.0, -590.16925, 0.0, 593.4485, 0.0, -579.52875, 0.0, 629.95404, 0.0, -567.1126, 0.0, 591.75146, 0.0, -583.1894, 0.0, 630.846]]> : tensor<1x17xf32>) : tensor<1x17xf32>
-  check.expect_almost_eq_const(%2, dense<[[0.0, 0.0, -23.956373, 0.0, -10.254326, 0.0, -6.1443653, 0.0, -10.0, 0.0, 3.865515, 0.0, 0.63767385, 0.0, 52.453506, 0.0, 0.0]]> : tensor<1x17xf32>) : tensor<1x17xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/finite.mlir b/tests/e2e/xla_ops/finite.mlir
deleted file mode 100644
index 3179b18..0000000
--- a/tests/e2e/xla_ops/finite.mlir
+++ /dev/null
@@ -1,11 +0,0 @@
-func.func @f32() {
-  %0 = util.unfoldable_constant dense<[1.0, 6.0, -6.0, 0.0]> : tensor<4xf32>
-  %1 = util.unfoldable_constant dense<[0.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %2 = "mhlo.divide"(%0, %1) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  %result = "mhlo.is_finite"(%2) : (tensor<4xf32>) -> tensor<4xi1>
-  %c0 = util.unfoldable_constant dense<0> : tensor<4xi8>
-  %c1 = util.unfoldable_constant dense<1> : tensor<4xi8>
-  %output = "mhlo.select"(%result, %c1, %c0) : (tensor<4xi1>, tensor<4xi8>, tensor<4xi8>) -> tensor<4xi8>
-  check.expect_eq_const(%output, dense<[0, 1, 1, 1]> : tensor<4xi8>) : tensor<4xi8>
-  return
-}
diff --git a/tests/e2e/xla_ops/floor.mlir b/tests/e2e/xla_ops/floor.mlir
deleted file mode 100644
index da10a87..0000000
--- a/tests/e2e/xla_ops/floor.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[0.0, 1.1, 2.5, 4.9]> : tensor<4xf32>
-  %result = "mhlo.floor"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[0.0, 1.0, 2.0, 4.0]> : tensor<4xf32>): tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<101.3> : tensor<f32>
-  %result = "mhlo.floor"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<101.0> : tensor<f32>): tensor<f32>
-  return
-}
-
-func.func @negative() {
-  %input = util.unfoldable_constant dense<-1.1> : tensor<f32>
-  %result = "mhlo.floor"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<-2.0> : tensor<f32>): tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/gather.mlir b/tests/e2e/xla_ops/gather.mlir
deleted file mode 100644
index d563af1..0000000
--- a/tests/e2e/xla_ops/gather.mlir
+++ /dev/null
@@ -1,169 +0,0 @@
-func.func @foo() {
-  %input = util.unfoldable_constant dense<[
-    [[01, 02, 03, 04, 05]],
-    [[06, 07, 08, 09, 10]],
-    [[11, 12, 13, 14, 15]],
-    [[16, 17, 18, 19, 20]],
-    [[21, 22, 23, 24, 25]]]> : tensor<5x1x5xi32>
-  %start_indices = util.unfoldable_constant dense<2> : tensor<i64>
-  %res = "mhlo.gather"(%input, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0],
-      index_vector_dim = 0,
-      offset_dims = [0, 1],
-      start_index_map = [0],
-    >,
-    slice_sizes = dense<[1, 1, 5]> : tensor<3xi64>
-  } : (tensor<5x1x5xi32>, tensor<i64>) -> tensor<1x5xi32>
-  check.expect_eq_const(%res, dense<[[11, 12, 13, 14, 15]]> : tensor<1x5xi32>) : tensor<1x5xi32>
-  return
-}
-
-func.func @via_torch_index_select() {
-  %input = util.unfoldable_constant dense<[
-    [[01, 02, 03, 04, 05]],
-    [[06, 07, 08, 09, 10]],
-    [[11, 12, 13, 14, 15]],
-    [[16, 17, 18, 19, 20]],
-    [[21, 22, 23, 24, 25]]]> : tensor<5x1x5xi32>
-  %start_indices = util.unfoldable_constant dense<2> : tensor<i64>
-  %res = "mhlo.gather"(%input, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0],
-      index_vector_dim = 0,
-      offset_dims = [0, 1],
-      start_index_map = [0],
-    >,
-    slice_sizes = dense<[1, 1, 5]> : tensor<3xi64>
-  } : (tensor<5x1x5xi32>, tensor<i64>) -> tensor<1x5xi32>
-  check.expect_eq_const(%res, dense<[[11, 12, 13, 14, 15]]> : tensor<1x5xi32>) : tensor<1x5xi32>
-  return
-}
-
-
-func.func @general_but_just_index_select() {
-  %operand = util.unfoldable_constant dense<[[
-    [ 0,  1,  2,  3,  4,  5,  6,  7],
-    [ 8,  9, 10, 11, 12, 13, 14, 15],
-    [16, 17, 18, 19, 20, 21, 22, 23],
-    [24, 25, 26, 27, 28, 29, 30, 31]]]> : tensor<1x4x8xi32>
-  %start_indices = util.unfoldable_constant dense<[[
-      [0, 1],
-      [0, 2],
-      [0, 3],
-      [0, 0],
-      [0, 0],
-      [0, 1],
-      [0, 2],
-      [0, 3]]]> : tensor<1x8x2xi32>
-  %result = "mhlo.gather"(%operand, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0, 1],
-      index_vector_dim = 2,
-      offset_dims = [2],
-      start_index_map = [0, 1]
-    >,
-    indices_are_sorted = false,
-    slice_sizes = dense<[1, 1, 8]> : tensor<3xi64>
-  } : (tensor<1x4x8xi32>, tensor<1x8x2xi32>) -> tensor<1x8x8xi32>
-  check.expect_eq_const(%result, dense<[[
-         [ 8,  9, 10, 11, 12, 13, 14, 15],
-         [16, 17, 18, 19, 20, 21, 22, 23],
-         [24, 25, 26, 27, 28, 29, 30, 31],
-         [ 0,  1,  2,  3,  4,  5,  6,  7],
-         [ 0,  1,  2,  3,  4,  5,  6,  7],
-         [ 8,  9, 10, 11, 12, 13, 14, 15],
-         [16, 17, 18, 19, 20, 21, 22, 23],
-         [24, 25, 26, 27, 28, 29, 30, 31]]]> : tensor<1x8x8xi32>) : tensor<1x8x8xi32>
-  return
-}
-
-func.func @small_slices() {
-  %operand = util.unfoldable_constant dense<[[
-    [ 0,  1,  2,  3,  4,  5,  6,  7],
-    [ 8,  9, 10, 11, 12, 13, 14, 15],
-    [16, 17, 18, 19, 20, 21, 22, 23],
-    [24, 25, 26, 27, 28, 29, 30, 31]]]> : tensor<1x4x8xi32>
-  %start_indices = util.unfoldable_constant dense<[[
-    [0, 1],
-    [0, 2],
-    [0, 3],
-    [0, 0]]]> : tensor<1x4x2xi32>
-  %result = "mhlo.gather"(%operand, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0, 1],
-      index_vector_dim = 2,
-      offset_dims = [2],
-      start_index_map = [0, 1]
-    >,
-    indices_are_sorted = false,
-    slice_sizes = dense<[1, 1, 3]> : tensor<3xi64>
-  } : (tensor<1x4x8xi32>, tensor<1x4x2xi32>) -> tensor<1x4x3xi32>
-  check.expect_eq_const(%result, dense<[[
-        [ 8,  9, 10],
-        [16, 17, 18],
-        [24, 25, 26],
-        [ 0,  1,  2]]]> : tensor<1x4x3xi32>) : tensor<1x4x3xi32>
-  return
-}
-
-func.func @nonstandard_offset_dims() {
-  %operand = util.unfoldable_constant dense<[[
-    [ 0,  1,  2,  3,  4,  5,  6,  7],
-    [ 8,  9, 10, 11, 12, 13, 14, 15],
-    [16, 17, 18, 19, 20, 21, 22, 23],
-    [24, 25, 26, 27, 28, 29, 30, 31]]]> : tensor<1x4x8xi32>
-  %start_indices = util.unfoldable_constant dense<[[
-    [0, 1],
-    [0, 2],
-    [0, 2],
-    [0, 0]]]> : tensor<1x4x2xi32>
-  %result = "mhlo.gather"(%operand, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0],
-      index_vector_dim = 2,
-      offset_dims = [1, 2],
-      start_index_map = [0, 1]
-    >,
-    indices_are_sorted = false,
-    slice_sizes = dense<[1, 2, 3]> : tensor<3xi64>
-  } : (tensor<1x4x8xi32>, tensor<1x4x2xi32>) -> tensor<1x2x3x4xi32>
-  check.expect_eq_const(%result, dense<[[
-      [[ 8, 16, 16,  0],
-       [ 9, 17, 17,  1],
-       [10, 18, 18,  2]],
-      [[16, 24, 24,  8],
-       [17, 25, 25,  9],
-       [18, 26, 26, 10]]]]> : tensor<1x2x3x4xi32>) : tensor<1x2x3x4xi32>
-  return
-}
-
-func.func @reordered_start_index() {
-  %operand = util.unfoldable_constant dense<[[
-    [[ 0,  1,  2,  3],
-     [ 4,  5,  6,  7]],
-    [[ 8,  9, 10, 11],
-     [12, 13, 14, 15]],
-    [[16, 17, 18, 19],
-     [20, 21, 22, 23]]]]> : tensor<1x3x2x4xi32>
-  %start_indices = util.unfoldable_constant dense<[
-    [0, 1, 0, 0],
-    [1, 0, 0, 0]]> : tensor<2x4xi32>
- %result = "mhlo.gather"(%operand, %start_indices) {
-    dimension_numbers = #mhlo.gather<
-      collapsed_slice_dims = [0, 2],
-      index_vector_dim = 1,
-      offset_dims = [1, 2],
-      start_index_map = [3, 2, 0, 1]
-    >,
-    indices_are_sorted = false,
-    slice_sizes = dense<[1, 2, 1, 3]> : tensor<4xi64>
-  } : (tensor<1x3x2x4xi32>, tensor<2x4xi32>) -> tensor<2x2x3xi32>
-
-  check.expect_eq_const(%result, dense<[
-    [[ 4,  5,  6],
-     [12, 13, 14]],
-    [[ 1,  2,  3],
-     [ 9, 10, 11]]]> : tensor<2x2x3xi32>) : tensor<2x2x3xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/iota.mlir b/tests/e2e/xla_ops/iota.mlir
deleted file mode 100644
index fba0f93..0000000
--- a/tests/e2e/xla_ops/iota.mlir
+++ /dev/null
@@ -1,16 +0,0 @@
-func.func @iota_dim0() {
-  %result = "mhlo.iota"() {iota_dimension = 0 : i64} : () -> tensor<2x3xf32>
-  check.expect_almost_eq_const(%result, dense<[
-    [0.0, 0.0, 0.0],
-    [1.0, 1.0, 1.0]]> : tensor<2x3xf32>) : tensor<2x3xf32>
-  return
-}
-
-
-func.func @iota_dim1() {
-  %result = "mhlo.iota"() {iota_dimension = 1 : i64} : () -> tensor<2x3xf32>
-  check.expect_almost_eq_const(%result, dense<[
-    [0.0, 1.0, 2.0],
-    [0.0, 1.0, 2.0]]> : tensor<2x3xf32>) : tensor<2x3xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/log.mlir b/tests/e2e/xla_ops/log.mlir
deleted file mode 100644
index d0cf00f..0000000
--- a/tests/e2e/xla_ops/log.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.log"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[0.0, 0.693147, 1.09861, 1.38629]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<4.0> : tensor<f32>
-  %result = "mhlo.log"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<1.3863> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @double() {
-  %input = util.unfoldable_constant dense<4.0> : tensor<f64>
-  %result = "mhlo.log"(%input) : (tensor<f64>) -> tensor<f64>
-  check.expect_almost_eq_const(%result, dense<1.3863> : tensor<f64>) : tensor<f64>
-  return
-}
diff --git a/tests/e2e/xla_ops/log_plus_one.mlir b/tests/e2e/xla_ops/log_plus_one.mlir
deleted file mode 100644
index acdd626..0000000
--- a/tests/e2e/xla_ops/log_plus_one.mlir
+++ /dev/null
@@ -1,6 +0,0 @@
-func.func @log_plus_one() {
-  %input = util.unfoldable_constant dense<[0.0, 0.5, 1.0, 5.0]> : tensor<4xf32>
-  %result = "mhlo.log_plus_one"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[0.0, 0.4054651, 0.6931472, 1.7917595]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/maximum.mlir b/tests/e2e/xla_ops/maximum.mlir
deleted file mode 100644
index 906ab98..0000000
--- a/tests/e2e/xla_ops/maximum.mlir
+++ /dev/null
@@ -1,87 +0,0 @@
-func.func @tensor_i32() {
-  %lhs = util.unfoldable_constant dense<[1, 6, 7, 8]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 6, 3, 8]> : tensor<4xi32>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[5, 6, 7, 8]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @tensor_odd_dim() {
-  %lhs = util.unfoldable_constant dense<[1, 6, 7]> : tensor<3xi32>
-  %rhs = util.unfoldable_constant dense<[5, 6, 3]> : tensor<3xi32>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>
-  check.expect_eq_const(%result, dense<[5, 6,7]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @scalar_i32() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i32>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<2> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @negative_i32() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<-2> : tensor<i32>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<1> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @i8() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i8>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i8>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%result, dense<2> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @i16() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i16>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i16>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<i16>, tensor<i16>) -> tensor<i16>
-  check.expect_eq_const(%result, dense<2> : tensor<i16>) : tensor<i16>
-  return
-}
-
-func.func @i64() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i64>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i64>
-  %result = "mhlo.maximum"(%lhs, %rhs) : (tensor<i64>, tensor<i64>) -> tensor<i64>
-  check.expect_eq_const(%result, dense<2> : tensor<i64>) : tensor<i64>
-  return
-}
-
-func.func @tensor_f32() {
-  %lhs = util.unfoldable_constant dense<[1.0, 2.0, 7.0, 4.0]> : tensor<4xf32>
-  %rhs = util.unfoldable_constant dense<[5.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar_f32() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %rhs = util.unfoldable_constant dense<2.0> : tensor<f32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<1.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @double() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f64>
-  %rhs = util.unfoldable_constant dense<2.0> : tensor<f64>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f64>, tensor<f64>) -> tensor<f64>
-  check.expect_almost_eq_const(%result, dense<1.0> : tensor<f64>) : tensor<f64>
-  return
-}
-
-func.func @negative_f32() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %rhs = util.unfoldable_constant dense<-2.0> : tensor<f32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<-2.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/minimum.mlir b/tests/e2e/xla_ops/minimum.mlir
deleted file mode 100644
index ceb9159..0000000
--- a/tests/e2e/xla_ops/minimum.mlir
+++ /dev/null
@@ -1,87 +0,0 @@
-func.func @tensor_i32() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3, 4]> : tensor<4xi32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[1, 2, 3, 4]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @tensor_odd_dim() {
-  %lhs = util.unfoldable_constant dense<[1, 2, 7]> : tensor<3xi32>
-  %rhs = util.unfoldable_constant dense<[5, 2, 3]> : tensor<3xi32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>
-  check.expect_eq_const(%result, dense<[1, 2, 3]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @scalar_i32() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<1> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @negative_i32() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i32>
-  %rhs = util.unfoldable_constant dense<-2> : tensor<i32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<-2> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @i8() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i8>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i8>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<i8>, tensor<i8>) -> tensor<i8>
-  check.expect_eq_const(%result, dense<1> : tensor<i8>) : tensor<i8>
-  return
-}
-
-func.func @i16() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i16>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i16>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<i16>, tensor<i16>) -> tensor<i16>
-  check.expect_eq_const(%result, dense<1> : tensor<i16>) : tensor<i16>
-  return
-}
-
-func.func @i64() {
-  %lhs = util.unfoldable_constant dense<1> : tensor<i64>
-  %rhs = util.unfoldable_constant dense<2> : tensor<i64>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<i64>, tensor<i64>) -> tensor<i64>
-  check.expect_eq_const(%result, dense<1> : tensor<i64>) : tensor<i64>
-  return
-}
-
-func.func @tensor_f32() {
-  %lhs = util.unfoldable_constant dense<[1.0, 2.0, 7.0, 4.0]> : tensor<4xf32>
-  %rhs = util.unfoldable_constant dense<[5.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar_f32() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %rhs = util.unfoldable_constant dense<2.0> : tensor<f32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<1.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @double() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f64>
-  %rhs = util.unfoldable_constant dense<2.0> : tensor<f64>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f64>, tensor<f64>) -> tensor<f64>
-  check.expect_almost_eq_const(%result, dense<1.0> : tensor<f64>) : tensor<f64>
-  return
-}
-
-func.func @negative_f32() {
-  %lhs = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %rhs = util.unfoldable_constant dense<-2.0> : tensor<f32>
-  %result = "mhlo.minimum"(%lhs, %rhs) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<-2.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/multiply.mlir b/tests/e2e/xla_ops/multiply.mlir
deleted file mode 100644
index bb31176..0000000
--- a/tests/e2e/xla_ops/multiply.mlir
+++ /dev/null
@@ -1,6 +0,0 @@
-func.func @multiply () {
-  %c2 = util.unfoldable_constant dense<2.0> : tensor<f32>
-  %res = "mhlo.multiply"(%c2, %c2) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%res, dense<4.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/negate.mlir b/tests/e2e/xla_ops/negate.mlir
deleted file mode 100644
index 9a6ebd3..0000000
--- a/tests/e2e/xla_ops/negate.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[-1.0, -2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.negate"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 2.0, -3.0, -4.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<-4.0> : tensor<f32>
-  %result = "mhlo.negate"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<4.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/pad.mlir b/tests/e2e/xla_ops/pad.mlir
deleted file mode 100644
index a47c636..0000000
--- a/tests/e2e/xla_ops/pad.mlir
+++ /dev/null
@@ -1,22 +0,0 @@
-func.func @pad_test() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
-  %c0 = arith.constant dense<0> : tensor<i32>
-  %res = "mhlo.pad"(%input, %c0) {
-    edge_padding_low = dense<[0, 1]> : tensor<2xi64>,
-    edge_padding_high = dense<[1, 5]> : tensor<2xi64>,
-    interior_padding = dense<0> : tensor<2xi64>
-  } : (tensor<2x3xi32>, tensor<i32>) -> tensor<3x9xi32>
-  check.expect_eq_const(%res, dense<[
-      [0, 1, 2, 3, 0, 0, 0, 0, 0],
-      [0, 4, 5, 6, 0, 0, 0, 0, 0],
-      [0, 0, 0, 0, 0, 0, 0, 0, 0]]> : tensor<3x9xi32>) : tensor<3x9xi32>
-  return
-}
-
-func.func @pad_no_op() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
-  %c0 = arith.constant dense<0> : tensor<i32>
-  %res = "mhlo.pad"(%input, %c0) {edge_padding_high = dense<[0, 0]> : tensor<2xi64>, edge_padding_low = dense<[0, 0]> : tensor<2xi64>, interior_padding = dense<0> : tensor<2xi64>} : (tensor<2x3xi32>, tensor<i32>) -> tensor<2x3xi32>
-  check.expect_eq(%res, %input) : tensor<2x3xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/pow.mlir b/tests/e2e/xla_ops/pow.mlir
deleted file mode 100644
index 376ba1c..0000000
--- a/tests/e2e/xla_ops/pow.mlir
+++ /dev/null
@@ -1,15 +0,0 @@
-func.func @tensor() {
-  %cst = mhlo.constant dense<3.0e+00> : tensor<4xf32>
-  %input = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.power"(%input, %cst) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 8.0, 27.0, 64.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %cst = mhlo.constant dense<2.0e+00> : tensor<f32>
-  %input = util.unfoldable_constant dense<16.0> : tensor<f32>
-  %result = "mhlo.power"(%input, %cst) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<256.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/reduce.mlir b/tests/e2e/xla_ops/reduce.mlir
deleted file mode 100644
index a78b595..0000000
--- a/tests/e2e/xla_ops/reduce.mlir
+++ /dev/null
@@ -1,360 +0,0 @@
-// Int sum values from [1, 10]
-func.func @reduce_sum_1x10xi32() {
-  %0 = util.unfoldable_constant dense<[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]> : tensor<1x10xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xi32>, tensor<i32>) -> tensor<1xi32>
-  check.expect_eq_const(%res, dense<55> : tensor<1xi32>) : tensor<1xi32>
-  return
-}
-
-// Int max values from [1, 10]
-func.func @reduce_max_1x10xi32() {
-  %0 = util.unfoldable_constant dense<[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]> : tensor<1x10xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.maximum"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xi32>, tensor<i32>) -> tensor<1xi32>
-  check.expect_eq_const(%res, dense<10> : tensor<1xi32>) : tensor<1xi32>
-  return
-}
-
-// Int min values, along multiple dimensions. Expected to just be a reshape in this case.
-func.func @reduce_min_5x1x1xi32() {
-  %0 = util.unfoldable_constant dense<[[[1]],[[2]],[[3]],[[4]],[[5]]]> : tensor<5x1x1xi32>
-  %1 = util.unfoldable_constant dense<999> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.minimum"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<5x1x1xi32>, tensor<i32>) -> tensor<5xi32>
-  check.expect_eq_const(%res, dense<[1, 2, 3, 4, 5]> : tensor<5xi32>) : tensor<5xi32>
-  return
-}
-
-
-// The following cases match the examples presented at
-// https://www.tensorflow.org/xla/operation_semantics#reduce
-
-func.func @reduce_sum_2x3xi32_dim0() {
-  %0 = util.unfoldable_constant dense<[
-      [1, 2, 3],
-      [4, 5, 6]]> : tensor<2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<2x3xi32>, tensor<i32>) -> tensor<3xi32>
-  check.expect_eq_const(%res, dense<[5, 7, 9]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @reduce_sum_2x3xi32_dim1() {
-  %0 = util.unfoldable_constant dense<[
-      [1, 2, 3],
-      [4, 5, 6]]> : tensor<2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<2x3xi32>, tensor<i32>) -> tensor<2xi32>
-  check.expect_eq_const(%res, dense<[6, 15]> : tensor<2xi32>) : tensor<2xi32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xi32_dim0() {
-  %0 = util.unfoldable_constant dense<[
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]]]> : tensor<4x2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<4x2x3xi32>, tensor<i32>) -> tensor<2x3xi32>
-  check.expect_eq_const(%res, dense<[[4, 8, 12],[16, 20, 24]]> : tensor<2x3xi32>) : tensor<2x3xi32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xi32_dim2() {
-  %0 = util.unfoldable_constant dense<[
-    [[1, 2, 3], [4, 5, 6]],
-    [[1, 2, 3], [4, 5, 6]],
-    [[1, 2, 3], [4, 5, 6]],
-    [[1, 2, 3], [4, 5, 6]]]> : tensor<4x2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<2> : tensor<1xi64>} : (tensor<4x2x3xi32>, tensor<i32>) -> tensor<4x2xi32>
-  check.expect_eq_const(%res, dense<[[6, 15],[6, 15],[6, 15],[6, 15]]> : tensor<4x2xi32>) : tensor<4x2xi32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xi32_dims_0_1() {
-  %0 = util.unfoldable_constant dense<[
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]]]> : tensor<4x2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<[0, 1]> : tensor<2xi64>} : (tensor<4x2x3xi32>, tensor<i32>) -> tensor<3xi32>
-  check.expect_eq_const(%res, dense<[20, 28, 36]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xi32_dims_0_1_2() {
-  %0 = util.unfoldable_constant dense<[
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]],
-      [[1, 2, 3], [4, 5, 6]]]> : tensor<4x2x3xi32>
-  %1 = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<[0, 1, 2]> : tensor<3xi64>} : (tensor<4x2x3xi32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%res, dense<84> : tensor<i32>) : tensor<i32>
-  return
-}
-
-// Float sum values from [1.0, 10.0]
-func.func @reduce_sum_1x10xf32() {
-  %0 = util.unfoldable_constant dense<[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]]> : tensor<1x10xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32>
-  check.expect_almost_eq_const(%res, dense<55.0> : tensor<1xf32>) : tensor<1xf32>
-  return
-}
-
-// Float max values from [1.0, 10.0]
-func.func @reduce_max_1x10xf32() {
-  %0 = util.unfoldable_constant dense<[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]]> : tensor<1x10xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1)
-  ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-      %3 = "mhlo.maximum"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-      "mhlo.return"(%3) : (tensor<f32>) -> ()
-  })
-  {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xf32>, tensor<f32>) -> tensor<1xf32>
-  check.expect_almost_eq_const(%res, dense<10.0> : tensor<1xf32>) : tensor<1xf32>
-  return
-}
-
-// Float min values, along multiple dimensions. Expected to just be a reshape in this case.
-func.func @reduce_min_5x1x1xf32() {
-  %0 = util.unfoldable_constant dense<[[[1.0]],[[2.0]],[[3.0]],[[4.0]],[[5.0]]]> : tensor<5x1x1xf32>
-  %1 = util.unfoldable_constant dense<999.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-      %3 = "mhlo.minimum"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-      "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<[1, 2]> : tensor<2xi64>} : (tensor<5x1x1xf32>, tensor<f32>) -> tensor<5xf32>
-  check.expect_almost_eq_const(%res, dense<[1.0, 2.0, 3.0, 4.0, 5.0]> : tensor<5xf32>) : tensor<5xf32>
-  return
-}
-
-// The following cases match the examples presented at
-// https://www.tensorflow.org/xla/operation_semantics#reduce
-
-func.func @reduce_sum_2x3xf32_dim0() {
-  %0 = util.unfoldable_constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<2x3xf32>, tensor<f32>) -> tensor<3xf32>
-  check.expect_almost_eq_const(%res, dense<[5.0, 7.0, 9.0]> : tensor<3xf32>) : tensor<3xf32>
-  return
-}
-
-func.func @reduce_sum_2x3xf32_dim1() {
-  %0 = util.unfoldable_constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<2x3xf32>, tensor<f32>) -> tensor<2xf32>
-  check.expect_almost_eq_const(%res, dense<[6.0, 15.0]> : tensor<2xf32>) : tensor<2xf32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xf32_dim0() {
-  %0 = util.unfoldable_constant dense<[
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<4x2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<4x2x3xf32>, tensor<f32>) -> tensor<2x3xf32>
-  check.expect_almost_eq_const(%res, dense<[[4.0, 8.0, 12.0],[16.0, 20.0, 24.0]]> : tensor<2x3xf32>) : tensor<2x3xf32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xf32_dim1() {
-  %0 = util.unfoldable_constant dense<[
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<4x2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<4x2x3xf32>, tensor<f32>) -> tensor<4x3xf32>
-  check.expect_almost_eq_const(%res, dense<[
-      [5.0, 7.0, 9.0],
-      [5.0, 7.0, 9.0],
-      [5.0, 7.0, 9.0],
-      [5.0, 7.0, 9.0]]> : tensor<4x3xf32>) : tensor<4x3xf32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xf32_dim2() {
-  %0 = util.unfoldable_constant dense<[
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<4x2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<2> : tensor<1xi64>} : (tensor<4x2x3xf32>, tensor<f32>) -> tensor<4x2xf32>
-  check.expect_almost_eq_const(%res, dense<[
-      [6.0, 15.0],
-      [6.0, 15.0],
-      [6.0, 15.0],
-      [6.0, 15.0]]> : tensor<4x2xf32>) : tensor<4x2xf32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xf32_dims_0_1() {
-  %0 = util.unfoldable_constant dense<[
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<4x2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<[0, 1]> : tensor<2xi64>} : (tensor<4x2x3xf32>, tensor<f32>) -> tensor<3xf32>
-  check.expect_almost_eq_const(%res, dense<[20.0, 28.0, 36.0]> : tensor<3xf32>) : tensor<3xf32>
-  return
-}
-
-func.func @reduce_sum_4x2x3xf32_dims_0_1_2() {
-  %0 = util.unfoldable_constant dense<[
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]],
-      [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]> : tensor<4x2x3xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {dimensions = dense<[0, 1, 2]> : tensor<3xi64>} : (tensor<4x2x3xf32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%res, dense<84.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @reducemulti_result() {
-  %cst0 = mhlo.constant dense<-2147483648> : tensor<i32>
-  %cst1 = mhlo.constant dense<0> : tensor<i32>
-  %arg0 = util.unfoldable_constant dense<[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16], [17, 18]]> : tensor<9x2xi32>
-  %arg1 = util.unfoldable_constant dense<[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17]]> : tensor<9x2xi32>
-  %res0, %res1 = "mhlo.reduce"(%arg0, %arg1, %cst0, %cst1) ( {
-  ^bb0(%arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>):  // no predecessors
-    %0 = "mhlo.compare"(%arg2, %arg4) {comparison_direction = #mhlo<comparison_direction GE>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    %1 = "mhlo.select"(%0, %arg2, %arg4) : (tensor<i1>, tensor<i32>, tensor<i32>) -> tensor<i32>
-    %2 = "mhlo.compare"(%arg2, %arg4) {comparison_direction = #mhlo<comparison_direction EQ>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    %3 = mhlo.minimum %arg3, %arg5 : tensor<i32>
-    %4 = "mhlo.select"(%0, %arg3, %arg5) : (tensor<i1>, tensor<i32>, tensor<i32>) -> tensor<i32>
-    %5 = "mhlo.select"(%2, %3, %4) : (tensor<i1>, tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%1, %5) : (tensor<i32>, tensor<i32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<9x2xi32>, tensor<9x2xi32>, tensor<i32>, tensor<i32>) -> (tensor<2xi32>, tensor<2xi32>)
-  check.expect_eq_const(%res0, dense<[17, 18]> : tensor<2xi32>) : tensor<2xi32>
-  check.expect_eq_const(%res1, dense<[16, 17]> : tensor<2xi32>) : tensor<2xi32>
-  return
-}
-
-func.func @reduce_dim_1() {
-  %0 = util.unfoldable_constant dense<[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]> : tensor<2x5xi32>
-  %1 = util.unfoldable_constant dense<10> : tensor<i32>
-  %2 = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0 : tensor<i32>, %arg1 : tensor<i32>):
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<2x5xi32>, tensor<i32>) -> tensor<2xi32>
-  check.expect_eq_const(%2, dense<[25, 50]> : tensor<2xi32>) : tensor<2xi32>
-  return
-}
-
-// Constants get folded in which linalg.indexed_generic ops. Check to
-// make sure this works as expected.
-func.func @reduce_dim_1_const() {
-  %0 = util.unfoldable_constant dense<[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]> : tensor<2x5xi32>
-  %1 = arith.constant dense<10> : tensor<i32>
-  %2 = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0 : tensor<i32>, %arg1 : tensor<i32>):
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<2x5xi32>, tensor<i32>) -> tensor<2xi32>
-  check.expect_eq_const(%2, dense<[25, 50]> : tensor<2xi32>) : tensor<2xi32>
-  return
-}
-
-func.func @reduce_dim_0() {
-  %0 = util.unfoldable_constant dense<[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]> : tensor<1x10xi32>
-  %1 = util.unfoldable_constant dense<10> : tensor<i32>
-  %2 = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0 : tensor<i32>, %arg1 : tensor<i32>):
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<1> : tensor<1xi64>} : (tensor<1x10xi32>, tensor<i32>) -> tensor<1xi32>
-  check.expect_eq_const(%2, dense<[65]> : tensor<1xi32>) : tensor<1xi32>
-  return
-}
-
-func.func @reduce_to_scalar() {
-  %0 = util.unfoldable_constant dense<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]> : tensor<10xi32>
-  %1 = util.unfoldable_constant dense<10> : tensor<i32>
-  %2 = "mhlo.reduce"(%0, %1) ( {
-  ^bb0(%arg0 : tensor<i32>, %arg1 : tensor<i32>):
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-    "mhlo.return"(%3) : (tensor<i32>) -> ()
-  }) {dimensions = dense<0> : tensor<1xi64>} : (tensor<10xi32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%2, dense<65> : tensor<i32>) : tensor<i32>
-  return
-}
diff --git a/tests/e2e/xla_ops/reduce_window.mlir b/tests/e2e/xla_ops/reduce_window.mlir
deleted file mode 100644
index 09dd5b5..0000000
--- a/tests/e2e/xla_ops/reduce_window.mlir
+++ /dev/null
@@ -1,98 +0,0 @@
-func.func @reduce_window_nonoverlapping_1x4x6x1xf32() {
-  %0 = util.unfoldable_constant dense<[[[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0], [ 6.0]],
-                                        [[ 7.0], [ 8.0], [ 9.0], [10.0], [11.0], [12.0]],
-                                        [[13.0], [14.0], [15.0], [16.0], [17.0], [18.0]],
-                                        [[19.0], [20.0], [21.0], [22.0], [23.0], [24.0]]]]> : tensor<1x4x6x1xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce_window"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {window_dimensions = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      window_strides = dense<[1, 2, 3, 1]> : tensor<4xi64>} : (tensor<1x4x6x1xf32>, tensor<f32>) -> tensor<1x2x2x1xf32>
-  check.expect_eq_const(%res, dense<[[[[30.0], [48.0]],[[102.0], [120.0]]]]> : tensor<1x2x2x1xf32>) : tensor<1x2x2x1xf32>
-  return
-}
-
-func.func @reduce_window_overlapping_4x6xf32() {
-  %0 = util.unfoldable_constant dense<[[[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0], [ 6.0]],
-                                        [[ 7.0], [ 8.0], [ 9.0], [10.0], [11.0], [12.0]],
-                                        [[13.0], [14.0], [15.0], [16.0], [17.0], [18.0]],
-                                        [[19.0], [20.0], [21.0], [22.0], [23.0], [24.0]]]]> : tensor<1x4x6x1xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce_window"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.add"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {window_dimensions = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      window_strides = dense<[1, 1, 1, 1]> : tensor<4xi64>} : (tensor<1x4x6x1xf32>, tensor<f32>) -> tensor<1x3x4x1xf32>
-  check.expect_eq_const(%res, dense<[[
-      [[ 30.0], [ 36.0], [ 42.0], [ 48.0]],
-      [[ 66.0], [ 72.0], [ 78.0], [ 84.0]],
-      [[102.0], [108.0], [114.0], [120.0]]]]> : tensor<1x3x4x1xf32>) : tensor<1x3x4x1xf32>
-  return
-}
-
-func.func @reduce_window_max_4x6xf32() {
-  %0 = util.unfoldable_constant dense<[[[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0], [ 6.0]],
-                                        [[ 7.0], [ 8.0], [ 9.0], [10.0], [11.0], [12.0]],
-                                        [[13.0], [14.0], [15.0], [16.0], [17.0], [18.0]],
-                                        [[19.0], [20.0], [21.0], [22.0], [23.0], [24.0]]]]> : tensor<1x4x6x1xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce_window"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.maximum"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {window_dimensions = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      window_strides = dense<[1, 2, 3, 1]> : tensor<4xi64>} : (tensor<1x4x6x1xf32>, tensor<f32>) -> tensor<1x2x2x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[[[9.0], [12.0]], [[21.0], [24.0]]]]> : tensor<1x2x2x1xf32>) : tensor<1x2x2x1xf32>
-  return
-}
-
-func.func @reduce_window_min_4x6xf32() {
-  %0 = util.unfoldable_constant dense<[[[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0], [ 6.0]],
-                                        [[ 7.0], [ 8.0], [ 9.0], [10.0], [11.0], [12.0]],
-                                        [[13.0], [14.0], [15.0], [16.0], [17.0], [18.0]],
-                                        [[19.0], [20.0], [21.0], [22.0], [23.0], [24.0]]]]> : tensor<1x4x6x1xf32>
-  %1 = util.unfoldable_constant dense<14.0> : tensor<f32>
-  %res = "mhlo.reduce_window"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.minimum"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {window_dimensions = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      window_strides = dense<[1, 2, 3, 1]> : tensor<4xi64>} : (tensor<1x4x6x1xf32>, tensor<f32>) -> tensor<1x2x2x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[[[1.0], [4.0]], [[13.0], [14.0]]]]> : tensor<1x2x2x1xf32>) : tensor<1x2x2x1xf32>
-  return
-}
-
-func.func @reduce_window_max_with_padding_4x6xf32() {
-  %0 = util.unfoldable_constant dense<[[[[ 1.0], [ 2.0], [ 3.0], [ 4.0], [ 5.0], [ 6.0]],
-                                        [[ 7.0], [ 8.0], [ 9.0], [10.0], [11.0], [12.0]],
-                                        [[13.0], [14.0], [15.0], [16.0], [17.0], [18.0]],
-                                        [[19.0], [20.0], [21.0], [22.0], [23.0], [24.0]]]]> : tensor<1x4x6x1xf32>
-  %1 = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %res = "mhlo.reduce_window"(%0, %1) ( {
-  ^bb0(%arg0: tensor<f32>, %arg1: tensor<f32>):   // no predecessors
-    %3 = "mhlo.maximum"(%arg0, %arg1) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-    "mhlo.return"(%3) : (tensor<f32>) -> ()
-  }) {window_dimensions = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      window_strides = dense<[1, 2, 3, 1]> : tensor<4xi64>,
-      padding = dense<[[0, 0], [1, 1], [0, 0], [0, 0]]> : tensor<4x2xi64>} : (tensor<1x4x6x1xf32>, tensor<f32>) -> tensor<1x3x2x1xf32>
-  check.expect_almost_eq_const(%res, dense<[[[[3.0], [6.0]], [[15.0], [18.0]], [[21.0], [24.0]]]]> : tensor<1x3x2x1xf32>) : tensor<1x3x2x1xf32>
-  return
-}
-
-func.func @cumsum_f32() {
-  %0 = mhlo.constant dense<0.000000e+00> : tensor<f32>
-  %1 = util.unfoldable_constant dense<1.0> : tensor<2x2x2xf32>
-  %res = "mhlo.reduce_window"(%1, %0) ({
-  ^bb0(%arg1: tensor<f32>, %arg2: tensor<f32>):
-    %4 = mhlo.add %arg1, %arg2 : tensor<f32>
-    "mhlo.return"(%4) : (tensor<f32>) -> ()
-  }) {padding = dense<[[1, 0], [0, 0], [0, 0]]> : tensor<3x2xi64>,
-      window_dimensions = dense<[2, 1, 1]> : tensor<3xi64>,
-      window_strides = dense<1> : tensor<3xi64>
-  } : (tensor<2x2x2xf32>, tensor<f32>) -> tensor<2x2x2xf32>
-  check.expect_almost_eq_const(%res, dense<[[[1.0, 1.0], [1.0, 1.0]], [[2.0, 2.0], [2.0, 2.0]]]> : tensor<2x2x2xf32>) : tensor<2x2x2xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/remainder.mlir b/tests/e2e/xla_ops/remainder.mlir
deleted file mode 100644
index b225bc1..0000000
--- a/tests/e2e/xla_ops/remainder.mlir
+++ /dev/null
@@ -1,63 +0,0 @@
-func.func @scalar() {
-  %input1 = util.unfoldable_constant dense<16.0> : tensor<f32>
-  %input2 = util.unfoldable_constant dense<7.0> : tensor<f32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<2.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @tensor() {
-  %input1 = util.unfoldable_constant dense<[16.0, 17.0, 18.0]> : tensor<3xf32>
-  %input2 = util.unfoldable_constant dense<[7.0, 8.0, 9.0]> : tensor<3xf32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<3xf32>, tensor<3xf32>) -> tensor<3xf32>
-  check.expect_almost_eq_const(%result, dense<[2.0, 1.0, 0.0]> : tensor<3xf32>) : tensor<3xf32>
-  return
-}
-
-func.func @negative_den() {
-  %input1 = util.unfoldable_constant dense<16.0> : tensor<f32>
-  %input2 = util.unfoldable_constant dense<-7.0> : tensor<f32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<2.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @negative_num() {
-  %input1 = util.unfoldable_constant dense<-16.0> : tensor<f32>
-  %input2 = util.unfoldable_constant dense<7.0> : tensor<f32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<f32>, tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<-2.0> : tensor<f32>) : tensor<f32>
-  return
-}
-
-func.func @scalar_int() {
-  %input1 = util.unfoldable_constant dense<16> : tensor<i32>
-  %input2 = util.unfoldable_constant dense<7> : tensor<i32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<2> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @tensor_int() {
-  %input1 = util.unfoldable_constant dense<[16, 17, 18]> : tensor<3xi32>
-  %input2 = util.unfoldable_constant dense<[7, 8, 9]> : tensor<3xi32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>
-  check.expect_eq_const(%result, dense<[2, 1, 0]> : tensor<3xi32>) : tensor<3xi32>
-  return
-}
-
-func.func @negative_den_int() {
-  %input1 = util.unfoldable_constant dense<16> : tensor<i32>
-  %input2 = util.unfoldable_constant dense<-7> : tensor<i32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<2> : tensor<i32>) : tensor<i32>
-  return
-}
-
-func.func @negative_num_int() {
-  %input1 = util.unfoldable_constant dense<-16> : tensor<i32>
-  %input2 = util.unfoldable_constant dense<7> : tensor<i32>
-  %result = "mhlo.remainder"(%input1, %input2) : (tensor<i32>, tensor<i32>) -> tensor<i32>
-  check.expect_eq_const(%result, dense<-2> : tensor<i32>) : tensor<i32>
-  return
-}
diff --git a/tests/e2e/xla_ops/reshape.mlir b/tests/e2e/xla_ops/reshape.mlir
deleted file mode 100644
index cf0a451..0000000
--- a/tests/e2e/xla_ops/reshape.mlir
+++ /dev/null
@@ -1,32 +0,0 @@
-func.func @reshape_1D_2D() {
-  %input = util.unfoldable_constant dense<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]> : tensor<12xi32>
-  %result = "mhlo.reshape"(%input) : (tensor<12xi32>) -> tensor<3x4xi32>
-  check.expect_eq_const(%result, dense<[
-      [1, 2, 3, 4],
-      [5, 6, 7, 8],
-      [9, 10, 11, 12]]> : tensor<3x4xi32>) : tensor<3x4xi32>
-  return
-}
-
-// func.func @reshape_1D_3D() {
-//   %input = util.unfoldable_constant dense<[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]> : tensor<12xi32>
-//   %result = "mhlo.reshape"(%input) : (tensor<12xi32>) -> tensor<2x2x3xi32>
-//   check.expect_eq_const(%result, dense<[
-//       [[1, 2, 3], [4, 5, 6]],
-//       [[7, 8, 9], [10, 11, 12]]]> : tensor<2x2x3xi32>) : tensor<2x2x3xi32>
-//   return
-// }
-
-// func.func @reshape_2D_3D() {
-//   %input = util.unfoldable_constant dense<[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]> : tensor<2x6xi32>
-//   %result = "mhlo.reshape"(%input) : (tensor<2x6xi32>) -> tensor<2x1x6xi32>
-//   check.expect_eq_const(%result, dense<[[[1, 2, 3, 4, 5, 6]], [[7, 8, 9, 10, 11, 12]]]> : tensor<2x1x6xi32>) : tensor<2x1x6xi32>
-//   return
-// }
-
-// func.func @reshape_3D_1D() {
-//   %input = util.unfoldable_constant dense<[[[1, 2, 3, 4, 5, 6]], [[7, 8, 9, 10, 11, 12]]]> : tensor<2x1x6xi32>
-//   %result = "mhlo.reshape"(%input) : (tensor<2x1x6xi32>) -> tensor<2x6xi32>
-//   check.expect_eq_const(%result, dense<[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]> : tensor<2x6xi32>) : tensor<2x6xi32>
-//   return
-// }
diff --git a/tests/e2e/xla_ops/reverse.mlir b/tests/e2e/xla_ops/reverse.mlir
deleted file mode 100644
index 57328e1..0000000
--- a/tests/e2e/xla_ops/reverse.mlir
+++ /dev/null
@@ -1,22 +0,0 @@
-func.func @xla_reverse() {
-  %t1 = util.unfoldable_constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32>
-
-  %dim0 = "mhlo.reverse"(%t1) {dimensions = dense<0> : tensor<1xi64>} : (tensor<2x3xf32>) -> tensor<2x3xf32>
-  check.expect_almost_eq_const(
-      %dim0,
-      dense<[[4.0, 5.0, 6.0], [1.0, 2.0, 3.0]]> : tensor<2x3xf32>
-  ) : tensor<2x3xf32>
-
-  %dim1 = "mhlo.reverse"(%t1) {dimensions = dense<1> : tensor<1xi64>} : (tensor<2x3xf32>) -> tensor<2x3xf32>
-  check.expect_almost_eq_const(
-      %dim1,
-      dense<[[3.0, 2.0, 1.0], [6.0, 5.0, 4.0]]> : tensor<2x3xf32>
-  ) : tensor<2x3xf32>
-
-  %both_dims = "mhlo.reverse"(%t1) {dimensions = dense<[0, 1]> : tensor<2xi64>} : (tensor<2x3xf32>) -> tensor<2x3xf32>
-  check.expect_almost_eq_const(
-      %both_dims,
-      dense<[[6.0, 5.0, 4.0], [3.0, 2.0, 1.0]]> : tensor<2x3xf32>
-  ) : tensor<2x3xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/rng_normal.mlir b/tests/e2e/xla_ops/rng_normal.mlir
deleted file mode 100644
index 3711ca7..0000000
--- a/tests/e2e/xla_ops/rng_normal.mlir
+++ /dev/null
@@ -1,11 +0,0 @@
-func.func @rng_normal_2d() {
-  %mu = util.unfoldable_constant dense<0.0> : tensor<f32>
-  %sigma = util.unfoldable_constant dense<1.0> : tensor<f32>
-  %shape = util.unfoldable_constant dense<[3, 5]>  : tensor<2xi64>
-  %res = "mhlo.rng"(%mu, %sigma, %shape) {rng_distribution = #mhlo.rng_distribution<NORMAL>} : (tensor<f32>, tensor<f32>, tensor<2xi64>) -> tensor<3x5xf32>
-  check.expect_almost_eq_const(%res,
-    dense<[[0.570861, 0.317593, -0.726538, 1.45925, -1.59632],
-           [-0.639956, 0.703875, -0.8801, -0.848389, -0.453391],
-           [0.645563, 0.543174, 0.2255, 0.0809385, -1.17198]]> : tensor<3x5xf32>) : tensor<3x5xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/rng_uniform.mlir b/tests/e2e/xla_ops/rng_uniform.mlir
deleted file mode 100644
index 8f1bb83..0000000
--- a/tests/e2e/xla_ops/rng_uniform.mlir
+++ /dev/null
@@ -1,34 +0,0 @@
-// Note that they are stateless random generators, so they have fixed results.
-func.func @rng_uniform_1d() {
-    %min = util.unfoldable_constant dense<-10.0> : tensor<f32>
-    %max = util.unfoldable_constant dense<10.0> : tensor<f32>
-    %shape = util.unfoldable_constant dense<[10]>  : tensor<1xi32>
-    %res = "mhlo.rng"(%min, %max, %shape) {rng_distribution = #mhlo.rng_distribution<UNIFORM>} : (tensor<f32>, tensor<f32>, tensor<1xi32>) -> tensor<10xf32>
-    check.expect_almost_eq_const(%res, dense<[
-        -9.99994, -4.8613, 0.277344, 5.41599, -9.44537, -4.30673, 0.831918, 5.97056, -8.8908, -3.75215
-        ]> : tensor<10xf32>) : tensor<10xf32>
-    return
-}
-
-func.func @rng_uniform_2d() {
-    %min = util.unfoldable_constant dense<-10.0> : tensor<f32>
-    %max = util.unfoldable_constant dense<10.0> : tensor<f32>
-    %shape = util.unfoldable_constant dense<[3, 3]>  : tensor<2xi32>
-    %res = "mhlo.rng"(%min, %max, %shape) {rng_distribution = #mhlo.rng_distribution<UNIFORM>} : (tensor<f32>, tensor<f32>, tensor<2xi32>) -> tensor<3x3xf32>
-    check.expect_almost_eq_const(%res, dense<[
-        [6.55154, -8.30982, -3.17117],
-        [1.75741, 6.89606, -7.9653],
-        [-3.03671, 2.10193, 7.24057]]> : tensor<3x3xf32>) : tensor<3x3xf32>
-    return
-}
-
-func.func @rng_uniform_3d() {
-    %min = util.unfoldable_constant dense<-10.0> : tensor<f32>
-    %max = util.unfoldable_constant dense<10.0> : tensor<f32>
-    %shape = util.unfoldable_constant dense<[2, 2, 2]>  : tensor<3xi32>
-    %res = "mhlo.rng"(%min, %max, %shape) {rng_distribution = #mhlo.rng_distribution<UNIFORM>} : (tensor<f32>, tensor<f32>, tensor<3xi32>) -> tensor<2x2x2xf32>
-    check.expect_almost_eq_const(%res, dense<[
-        [[3.04814, 8.18679], [-1.74598, 3.39266]],
-        [[-6.91349, -1.77484], [8.29239, -6.56897]]]> : tensor<2x2x2xf32>) : tensor<2x2x2xf32>
-    return
-}
diff --git a/tests/e2e/xla_ops/round.mlir b/tests/e2e/xla_ops/round.mlir
deleted file mode 100644
index 29e5bc4..0000000
--- a/tests/e2e/xla_ops/round.mlir
+++ /dev/null
@@ -1,7 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[-0.7, -0.5, -0.2, 0.0, 0.2, 0.5, 0.7]> : tensor<7xf32>
-  %result = "mhlo.round_nearest_afz"(%input) : (tensor<7xf32>) -> tensor<7xf32>
-  check.expect_almost_eq_const(%result, dense<[-1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0]> : tensor<7xf32>) : tensor<7xf32>
-  return
-}
-
diff --git a/tests/e2e/xla_ops/rsqrt.mlir b/tests/e2e/xla_ops/rsqrt.mlir
deleted file mode 100644
index 595bfc6..0000000
--- a/tests/e2e/xla_ops/rsqrt.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.rsqrt"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 0.707107, 0.57735, 0.5]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<16.0> : tensor<f32>
-  %result = "mhlo.rsqrt"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<0.25> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/scatter.mlir b/tests/e2e/xla_ops/scatter.mlir
deleted file mode 100644
index e994f1d..0000000
--- a/tests/e2e/xla_ops/scatter.mlir
+++ /dev/null
@@ -1,238 +0,0 @@
-func.func @scatter_update_scalar_1D() {
-  %arg0 = util.unfoldable_constant dense<0> : tensor<8xi32>
-  %arg1 = util.unfoldable_constant dense<[[1], [3], [4], [7]]> : tensor<4x1xi32>
-  %arg2 = util.unfoldable_constant dense<[9, 10, 11, 12]> : tensor<4xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<8xi32>, tensor<4x1xi32>, tensor<4xi32>) -> tensor<8xi32>
-  check.expect_eq_const(%0, dense<[0, 9, 0, 10, 11, 0, 0, 12]> : tensor<8xi32>) : tensor<8xi32>
-  return
-}
-
-func.func @scatter_repeated_update_scalar_1D() {
-  %arg0 = util.unfoldable_constant dense<0> : tensor<8xi32>
-  %arg1 = util.unfoldable_constant dense<[[1], [1], [7], [7]]> : tensor<4x1xi32>
-  %arg2 = util.unfoldable_constant dense<[9, 10, 11, 12]> : tensor<4xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = false
-  } : (tensor<8xi32>, tensor<4x1xi32>, tensor<4xi32>) -> tensor<8xi32>
-  check.expect_eq_const(%0, dense<[0, 10, 0, 0, 0, 0, 0, 12]> : tensor<8xi32>) : tensor<8xi32>
-  return
-}
-
-func.func @scatter_update_scalar_2D() {
-  %arg0 = util.unfoldable_constant dense<0> : tensor<4x3xi32>
-  %arg1 = util.unfoldable_constant dense<[[0, 0], [1, 1], [2, 2]]> : tensor<3x2xi32>
-  %arg2 = util.unfoldable_constant dense<[1, 2, 3]> : tensor<3xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {indices_are_sorted = false,
-      scatter_dimension_numbers = #mhlo.scatter<
-        inserted_window_dims = [0, 1],
-        scatter_dims_to_operand_dims = [0, 1],
-        index_vector_dim = 1
-      >,
-      unique_indices = true
-  } : (tensor<4x3xi32>, tensor<3x2xi32>, tensor<3xi32>) -> tensor<4x3xi32>
-  check.expect_eq_const(%0, dense<[[1, 0, 0],
-                                   [0, 2, 0],
-                                   [0, 0, 3],
-                                   [0, 0, 0]]> : tensor<4x3xi32>) : tensor<4x3xi32>
-  return
-}
-
-func.func @scatter_update_slice_2D() {
-  %arg0 = util.unfoldable_constant dense<0> : tensor<6x3xi32>
-  %arg1 = util.unfoldable_constant dense<[[2], [4]]> : tensor<2x1xi32>
-  %arg2 = util.unfoldable_constant dense<[[1, 2, 3],
-                                          [4, 5, 6]]> : tensor<2x3xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<6x3xi32>, tensor<2x1xi32>, tensor<2x3xi32>) -> tensor<6x3xi32>
-  check.expect_eq_const(%0, dense<[[0, 0, 0],
-                                   [0, 0, 0],
-                                   [1, 2, 3],
-                                   [0, 0, 0],
-                                   [4, 5, 6],
-                                   [0, 0, 0]]> : tensor<6x3xi32>) : tensor<6x3xi32>
-  return
-}
-
-func.func @scatter_update_slice_partial_2D() {
-  %arg0 = util.unfoldable_constant dense<0> : tensor<6x3xi32>
-  %arg1 = util.unfoldable_constant dense<[[2], [4]]> : tensor<2x1xi32>
-  %arg2 = util.unfoldable_constant dense<[[1, 2],
-                                          [4, 5]]> : tensor<2x2xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<6x3xi32>, tensor<2x1xi32>, tensor<2x2xi32>) -> tensor<6x3xi32>
-  check.expect_eq_const(%0, dense<[[0, 0, 0],
-                                   [0, 0, 0],
-                                   [1, 2, 0],
-                                   [0, 0, 0],
-                                   [4, 5, 0],
-                                   [0, 0, 0]]> : tensor<6x3xi32>) : tensor<6x3xi32>
-  return
-}
-
-func.func @scatter_add_slice_2D() {
-  %arg0 = util.unfoldable_constant dense<1> : tensor<6x3xi32>
-  %arg1 = util.unfoldable_constant dense<[[2], [4]]> : tensor<2x1xi32>
-  %arg2 = util.unfoldable_constant dense<[[1, 2, 3],
-                                          [4, 5, 6]]> : tensor<2x3xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    %1 = mhlo.add %arg3, %arg4 : tensor<i32>
-    "mhlo.return"(%1) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<6x3xi32>, tensor<2x1xi32>, tensor<2x3xi32>) -> tensor<6x3xi32>
-  check.expect_eq_const(%0, dense<[[1, 1, 1],
-                                   [1, 1, 1],
-                                   [2, 3, 4],
-                                   [1, 1, 1],
-                                   [5, 6, 7],
-                                   [1, 1, 1]]> : tensor<6x3xi32>) : tensor<6x3xi32>
-  return
-}
-
-func.func @scatter_1D_large() {
-  %original = util.unfoldable_constant dense<1> : tensor<1400xi32>
-  %update = util.unfoldable_constant dense<2> : tensor<1400xi32>
-  %init = tensor.empty() : tensor<1400xi32>
-  %indices = linalg.generic {
-      indexing_maps = [affine_map<(d0) -> (d0)>],
-      iterator_types = ["parallel"]}
-      outs(%init : tensor<1400xi32>) {
-      ^bb0(%arg0: i32):
-        %0 = linalg.index 0 : index
-     %1 = arith.index_cast %0 : index to i32
-     linalg.yield %1 : i32
-      } -> tensor<1400xi32>
-  %indices_reshaped = tensor.expand_shape %indices [[0, 1]] :
-      tensor<1400xi32> into tensor<1400x1xi32>
-  %result = "mhlo.scatter"(%original, %indices_reshaped, %update)({
-    ^bb0(%arg3 : tensor<i32>, %arg4 : tensor<i32>):
-      "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-    }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<1400xi32>, tensor<1400x1xi32>, tensor<1400xi32>) -> tensor<1400xi32>
-  check.expect_eq_const(%result, dense<2> : tensor<1400xi32>) : tensor<1400xi32>
-  return
-}
-
-func.func @scatter_2D_large() {
-  %original = util.unfoldable_constant dense<1> : tensor<200x300xi32>
-  %update = util.unfoldable_constant dense<2> : tensor<200x300xi32>
-  %init = tensor.empty() : tensor<200xi32>
-  %indices = linalg.generic {
-      indexing_maps = [affine_map<(d0) -> (d0)>],
-      iterator_types = ["parallel"]}
-      outs(%init : tensor<200xi32>) {
-      ^bb0(%arg0: i32):
-        %0 = linalg.index 0 : index
-        %1 = arith.index_cast %0 : index to i32
-        linalg.yield %1 : i32
-      } -> tensor<200xi32>
-  %indices_reshaped = tensor.expand_shape %indices [[0, 1]] :
-      tensor<200xi32> into tensor<200x1xi32>
-  %result = "mhlo.scatter"(%original, %indices_reshaped, %update)({
-    ^bb0(%arg3 : tensor<i32>, %arg4 : tensor<i32>):
-      "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-    }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<200x300xi32>, tensor<200x1xi32>, tensor<200x300xi32>) -> tensor<200x300xi32>
-  check.expect_eq_const(%result, dense<2> : tensor<200x300xi32>) : tensor<200x300xi32>
-  return
-}
-
-func.func @scatter_2D_large_permuted() {
-  %original = util.unfoldable_constant dense<1> : tensor<200x300xi32>
-  %update = util.unfoldable_constant dense<2> : tensor<300x200xi32>
-  %init = tensor.empty() : tensor<300xi32>
-  %indices = linalg.generic {
-      indexing_maps = [affine_map<(d0) -> (d0)>],
-      iterator_types = ["parallel"]}
-      outs(%init : tensor<300xi32>) {
-      ^bb0(%arg0: i32):
-        %0 = linalg.index 0 : index
-        %1 = arith.index_cast %0 : index to i32
-        linalg.yield %1 : i32
-      } -> tensor<300xi32>
-  %indices_reshaped = tensor.expand_shape %indices [[0, 1]] :
-      tensor<300xi32> into tensor<300x1xi32>
-  %result = "mhlo.scatter"(%original, %indices_reshaped, %update)({
-    ^bb0(%arg3 : tensor<i32>, %arg4 : tensor<i32>):
-      "mhlo.return"(%arg4) : (tensor<i32>) -> ()
-    }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [1],
-      scatter_dims_to_operand_dims = [1],
-      index_vector_dim = 1,
-    >,
-    unique_indices = true
-  } : (tensor<200x300xi32>, tensor<300x1xi32>, tensor<300x200xi32>) -> tensor<200x300xi32>
-  check.expect_eq_const(%result, dense<2> : tensor<200x300xi32>) : tensor<200x300xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/scatter_dynamic.mlir b/tests/e2e/xla_ops/scatter_dynamic.mlir
deleted file mode 100644
index a7bb913..0000000
--- a/tests/e2e/xla_ops/scatter_dynamic.mlir
+++ /dev/null
@@ -1,28 +0,0 @@
-func.func @scatter_add_slice_2D_dynamic_num_updates() {
-  %arg0 = util.unfoldable_constant dense<1> : tensor<6x3xi32>
-  %arg1 = flow.tensor.constant dense<[[2], [4]]> : tensor<2x1xi32> -> tensor<?x1xi32>
-  %arg2 = flow.tensor.constant dense<[[1, 2, 3],
-                                             [4, 5, 6]]> : tensor<2x3xi32> -> tensor<?x3xi32>
-  %0 = "mhlo.scatter"(%arg0, %arg1, %arg2) ( {
-  ^bb0(%arg3: tensor<i32>, %arg4: tensor<i32>):  // no predecessors
-    %1 = mhlo.add %arg3, %arg4 : tensor<i32>
-    "mhlo.return"(%1) : (tensor<i32>) -> ()
-  }) {
-    indices_are_sorted = false,
-    scatter_dimension_numbers = #mhlo.scatter<
-      update_window_dims = [1],
-      inserted_window_dims = [0],
-      scatter_dims_to_operand_dims = [0],
-      index_vector_dim = 1,
-    >,
-    unique_indices = false
-  } : (tensor<6x3xi32>, tensor<?x1xi32>, tensor<?x3xi32>) -> tensor<6x3xi32>
-  check.expect_eq_const(%0, dense<[[1, 1, 1],
-                                   [1, 1, 1],
-                                   [2, 3, 4],
-                                   [1, 1, 1],
-                                   [5, 6, 7],
-                                   [1, 1, 1]]> : tensor<6x3xi32>) : tensor<6x3xi32>
-  return
-}
-
diff --git a/tests/e2e/xla_ops/select.mlir b/tests/e2e/xla_ops/select.mlir
deleted file mode 100644
index 2057059..0000000
--- a/tests/e2e/xla_ops/select.mlir
+++ /dev/null
@@ -1,10 +0,0 @@
-func.func @select() {
-  %input = util.unfoldable_constant dense<[1, 0, 1, 0]> : tensor<4xi1>
-  %zeros = util.unfoldable_constant dense<0> : tensor<4xi1>
-  %cond = "mhlo.compare"(%input, %zeros) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<4xi1>, tensor<4xi1>) -> tensor<4xi1>
-  %lhs = util.unfoldable_constant dense<[1, 2, 3, 4]> : tensor<4xi32>
-  %rhs = util.unfoldable_constant dense<[5, 6, 7, 8]> : tensor<4xi32>
-  %result = "mhlo.select"(%cond, %lhs, %rhs) : (tensor<4xi1>, tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[1,6, 3, 8]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/sine.mlir b/tests/e2e/xla_ops/sine.mlir
deleted file mode 100644
index 8d69740..0000000
--- a/tests/e2e/xla_ops/sine.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[0.0, 1.0, 1.5, 2.0]> : tensor<4xf32>
-  %result = "mhlo.sine"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[0.0, 0.8415, 0.9975, 0.9093]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<3.0> : tensor<f32>
-  %result = "mhlo.sine"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<0.14112> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/slice.mlir b/tests/e2e/xla_ops/slice.mlir
deleted file mode 100644
index 27a6875..0000000
--- a/tests/e2e/xla_ops/slice.mlir
+++ /dev/null
@@ -1,60 +0,0 @@
-func.func @slice_whole_buffer() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %result = "mhlo.slice"(%input) {
-    start_indices = dense<[0, 0]> : tensor<2xi64>,
-    limit_indices = dense<[3, 4]> : tensor<2xi64>,
-    strides = dense<1> : tensor<2xi64>
-  } : (tensor<3x4xi32>) -> tensor<3x4xi32>
-  check.expect_eq_const(%result, dense<[
-      [1, 2, 3, 4],
-      [5, 6, 7, 8],
-      [9, 10, 11, 12]]> : tensor<3x4xi32>) : tensor<3x4xi32>
-  return
-}
-
-func.func @slice_whole_stride() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %result = "mhlo.slice"(%input) {
-    start_indices = dense<[1, 0]> : tensor<2xi64>,
-    limit_indices = dense<[2, 4]> : tensor<2xi64>,
-    strides = dense<1> : tensor<2xi64>
-  } : (tensor<3x4xi32>) -> tensor<1x4xi32>
-  check.expect_eq_const(%result, dense<[[5, 6, 7, 8]]> : tensor<1x4xi32>) : tensor<1x4xi32>
-  return
-}
-
-func.func @slice_stride_part() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %result = "mhlo.slice"(%input) {
-    start_indices = dense<[1, 1]> : tensor<2xi64>,
-    limit_indices = dense<[2, 3]> : tensor<2xi64>,
-    strides = dense<1> : tensor<2xi64>
-  } : (tensor<3x4xi32>) -> tensor<1x2xi32>
-  check.expect_eq_const(%result, dense<[[6, 7]]> : tensor<1x2xi32>) : tensor<1x2xi32>
-  return
-}
-
-func.func @slice_multi_stride() {
-  %input = util.unfoldable_constant dense<[
-    [01, 02, 03, 04],
-    [05, 06, 07, 08],
-    [09, 10, 11, 12]]> : tensor<3x4xi32>
-  %result = "mhlo.slice"(%input) {
-    start_indices = dense<[1, 0]> : tensor<2xi64>,
-    limit_indices = dense<[3, 4]> : tensor<2xi64>,
-    strides = dense<1> : tensor<2xi64>
-  } : (tensor<3x4xi32>) -> tensor<2x4xi32>
-  check.expect_eq_const(%result, dense<[
-      [5, 6, 7, 8],
-      [9, 10, 11, 12]]> : tensor<2x4xi32>) : tensor<2x4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/sort.mlir b/tests/e2e/xla_ops/sort.mlir
deleted file mode 100644
index 81a5e1d..0000000
--- a/tests/e2e/xla_ops/sort.mlir
+++ /dev/null
@@ -1,53 +0,0 @@
-func.func @sort1D() {
-  %input = util.unfoldable_constant dense<[3, 2, 1, 4]> : tensor<4xi32>
-
-  %sort = "mhlo.sort"(%input) ( {
-  ^bb0(%arg1: tensor<i32>, %arg2: tensor<i32>):  // no predecessors
-    %compare = "mhlo.compare"(%arg1, %arg2) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%compare) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<4xi32>) -> tensor<4xi32>
-
-  check.expect_eq_const(%sort, dense<[1, 2, 3, 4]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @sort2D() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3, 4],
-                                           [4, 3, 2, 1]]> : tensor<2x4xi32>
-
-  %sort = "mhlo.sort"(%input) ( {
-  ^bb0(%arg1: tensor<i32>, %arg2: tensor<i32>):  // no predecessors
-    %compare = "mhlo.compare"(%arg1, %arg2) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%compare) : (tensor<i1>) -> ()
-  }) {dimension = 1 : i64, is_stable = false} : (tensor<2x4xi32>) -> tensor<2x4xi32>
-
-  check.expect_eq_const(%sort, dense<[[1, 2, 3, 4], [1, 2, 3, 4]]> : tensor<2x4xi32>) : tensor<2x4xi32>
-  return
-}
-
-func.func @sort3D() {
-  %input = util.unfoldable_constant dense<[[[1, 2, 3, 4],
-                                            [4, 3, 2, 1]]]> : tensor<1x2x4xi32>
-
-  %sort = "mhlo.sort"(%input) ( {
-  ^bb0(%arg1: tensor<i32>, %arg2: tensor<i32>):  // no predecessors
-    %compare = "mhlo.compare"(%arg1, %arg2) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%compare) : (tensor<i1>) -> ()
-  }) {dimension = 2 : i64, is_stable = false} : (tensor<1x2x4xi32>) -> tensor<1x2x4xi32>
-
-  check.expect_eq_const(%sort, dense<[[[1, 2, 3, 4], [1, 2, 3, 4]]]> : tensor<1x2x4xi32>) : tensor<1x2x4xi32>
-  return
-}
-
-func.func @sort_to_decreasing_seq() {
-  %input = util.unfoldable_constant dense<[3, 2, 1, 4]> : tensor<4xi32>
-
-  %sort = "mhlo.sort"(%input) ( {
-  ^bb0(%arg1: tensor<i32>, %arg2: tensor<i32>):  // no predecessors
-    %compare = "mhlo.compare"(%arg1, %arg2) {comparison_direction = #mhlo<comparison_direction GT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-    "mhlo.return"(%compare) : (tensor<i1>) -> ()
-  }) {dimension = 0 : i64, is_stable = false} : (tensor<4xi32>) -> tensor<4xi32>
-
-  check.expect_eq_const(%sort, dense<[4, 3, 2, 1]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/sqrt.mlir b/tests/e2e/xla_ops/sqrt.mlir
deleted file mode 100644
index 54f1256..0000000
--- a/tests/e2e/xla_ops/sqrt.mlir
+++ /dev/null
@@ -1,13 +0,0 @@
-func.func @tensor() {
-  %input = util.unfoldable_constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32>
-  %result = "mhlo.sqrt"(%input) : (tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[1.0, 1.4142, 1.7321, 2.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
-
-func.func @scalar() {
-  %input = util.unfoldable_constant dense<16.0> : tensor<f32>
-  %result = "mhlo.sqrt"(%input) : (tensor<f32>) -> tensor<f32>
-  check.expect_almost_eq_const(%result, dense<4.0> : tensor<f32>) : tensor<f32>
-  return
-}
diff --git a/tests/e2e/xla_ops/subtract.mlir b/tests/e2e/xla_ops/subtract.mlir
deleted file mode 100644
index 4d6aa79..0000000
--- a/tests/e2e/xla_ops/subtract.mlir
+++ /dev/null
@@ -1,15 +0,0 @@
-func.func @i32() {
-  %0 = util.unfoldable_constant dense<[5, 6, 3, 4]> : tensor<4xi32>
-  %1 = util.unfoldable_constant dense<[1, 4, 7, 6]> : tensor<4xi32>
-  %result = "mhlo.subtract"(%0, %1) : (tensor<4xi32>, tensor<4xi32>) -> tensor<4xi32>
-  check.expect_eq_const(%result, dense<[4, 2, -4, -2]> : tensor<4xi32>) : tensor<4xi32>
-  return
-}
-
-func.func @f32() {
-  %0 = util.unfoldable_constant dense<[5.0, 6.0, 3.0, 4.0]> : tensor<4xf32>
-  %1 = util.unfoldable_constant dense<[1.0, 4.0, 7.0, 6.0]> : tensor<4xf32>
-  %result = "mhlo.subtract"(%0, %1) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
-  check.expect_almost_eq_const(%result, dense<[4.0, 2.0, -4.0, -2.0]> : tensor<4xf32>) : tensor<4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/tanh.mlir b/tests/e2e/xla_ops/tanh.mlir
deleted file mode 100644
index db15e8c..0000000
--- a/tests/e2e/xla_ops/tanh.mlir
+++ /dev/null
@@ -1,10 +0,0 @@
-func.func @tanh() {
-  %input = util.unfoldable_constant dense<
-      [[-100.0, -5.0, -0.5,   1.0],
-       [   1.2,  2.0,  3.0, 100.0]]> : tensor<2x4xf32>
-  %result = "mhlo.tanh"(%input) : (tensor<2x4xf32>) -> tensor<2x4xf32>
-  check.expect_almost_eq_const(%result, dense<
-      [[-1.0000, -0.9999, -0.4622, 0.7616],
-       [ 0.8337,  0.9640,  0.9951, 1.0000]]> : tensor<2x4xf32>) : tensor<2x4xf32>
-  return
-}
diff --git a/tests/e2e/xla_ops/torch_index_select.mlir b/tests/e2e/xla_ops/torch_index_select.mlir
deleted file mode 100644
index 6284fec..0000000
--- a/tests/e2e/xla_ops/torch_index_select.mlir
+++ /dev/null
@@ -1,45 +0,0 @@
-func.func @torch_select_index_0() {
-  %input = util.unfoldable_constant dense<[
-    [[01, 02, 03, 04, 05]],
-    [[06, 07, 08, 09, 10]],
-    [[11, 12, 13, 14, 15]],
-    [[16, 17, 18, 19, 20]],
-    [[21, 22, 23, 24, 25]]]> : tensor<5x1x5xi32>
-  %indices = util.unfoldable_constant dense<[0, 2]> : tensor<2xi32>
-  %res = "mhlo.torch_index_select"(%input, %indices) {
-    dim = 0 : i64,
-    batch_dims = 0 : i64
-  } : (tensor<5x1x5xi32>, tensor<2xi32>) -> tensor<2x1x5xi32>
-  check.expect_eq_const(%res, dense<[[[01, 02, 03, 04, 05]], [[11, 12, 13, 14, 15]]]> : tensor<2x1x5xi32>) : tensor<2x1x5xi32>
-  return
-}
-
-func.func @torch_select_index_1() {
-  %input = util.unfoldable_constant dense<[
-    [[ 1,  2],[ 3,  4]],
-    [[ 5,  6],[ 7,  8]],
-    [[ 9, 10],[11, 12]]]> : tensor<3x2x2xi32>
-  %indices = util.unfoldable_constant dense<[0, 1]> : tensor<2xi32>
-  %res = "mhlo.torch_index_select"(%input, %indices) {
-    dim = 1 : i64,
-    batch_dims = 0 : i64
-  } : (tensor<3x2x2xi32>, tensor<2xi32>) -> tensor<3x2x2xi32>
-  check.expect_eq_const(%res, dense<[[[1,  2], [3,  4]], [[5,  6], [7,  8]],[[9, 10], [11, 12]]]> : tensor<3x2x2xi32>) : tensor<3x2x2xi32>
-  return
-}
-
-func.func @torch_select_index_2() {
-  %input = util.unfoldable_constant dense<[
-    [[01, 02, 03, 04, 05]],
-    [[06, 07, 08, 09, 10]],
-    [[11, 12, 13, 14, 15]],
-    [[16, 17, 18, 19, 20]],
-    [[21, 22, 23, 24, 25]]]> : tensor<5x1x5xi32>
-  %indices = util.unfoldable_constant dense<0> : tensor<i32>
-  %res = "mhlo.torch_index_select"(%input, %indices) {
-    dim = 0 : i64,
-    batch_dims = 0 : i64
-  } : (tensor<5x1x5xi32>, tensor<i32>) -> tensor<1x5xi32>
-  check.expect_eq_const(%res, dense<[[01, 02, 03, 04, 05]]> : tensor<1x5xi32>) : tensor<1x5xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/transpose.mlir b/tests/e2e/xla_ops/transpose.mlir
deleted file mode 100644
index 34e769d..0000000
--- a/tests/e2e/xla_ops/transpose.mlir
+++ /dev/null
@@ -1,29 +0,0 @@
-func.func @transpose_2d() {
-  %input = util.unfoldable_constant dense<[[1, 2, 3],
-                                           [4, 5, 6]]> : tensor<2x3xi32>
-  %0 = "mhlo.transpose"(%input) {
-    permutation = dense<[1, 0]> : tensor<2xi64>
-  } : (tensor<2x3xi32>) -> tensor<3x2xi32>
-  check.expect_eq_const(%0, dense<[[1, 4],
-                                   [2, 5],
-                                   [3, 6]]> : tensor<3x2xi32>) : tensor<3x2xi32>
-  return
-}
-
-func.func @transpose_3d() {
-  %input = util.unfoldable_constant dense<[[[ 1,  2,  3],
-                                            [ 4,  5,  6]],
-                                           [[ 7,  8,  9],
-                                            [10, 11, 12]]]> : tensor<2x2x3xi32>
-  %0 = "mhlo.transpose"(%input) {
-    permutation = dense<[0, 2, 1]> : tensor<3xi64>
-  } : (tensor<2x2x3xi32>) -> tensor<2x3x2xi32>
-  check.expect_eq_const(%0, dense<[
-    [[ 1,  4],
-     [ 2,  5],
-     [ 3,  6]],
-    [[ 7, 10],
-     [ 8, 11],
-     [ 9, 12]]]> : tensor<2x3x2xi32>) : tensor<2x3x2xi32>
-  return
-}
diff --git a/tests/e2e/xla_ops/while.mlir b/tests/e2e/xla_ops/while.mlir
deleted file mode 100644
index c079172..0000000
--- a/tests/e2e/xla_ops/while.mlir
+++ /dev/null
@@ -1,17 +0,0 @@
-// NOTE: this has already been legalized to CFG form in the TF import tools.
-func.func @while() {
-  %start = util.unfoldable_constant dense<1> : tensor<i32>
-  %bound = util.unfoldable_constant dense<3> : tensor<i32>
-  %cst_1 = arith.constant dense<4> : tensor<i32>
-  cf.br ^bb1(%start : tensor<i32>)
-^bb1(%2: tensor<i32>):
-  %3 = "mhlo.compare"(%2, %bound) {comparison_direction = #mhlo<comparison_direction LT>} : (tensor<i32>, tensor<i32>) -> tensor<i1>
-  %4 = tensor.extract %3[] : tensor<i1>
-  cf.cond_br %4, ^bb2(%2 : tensor<i32>), ^bb3(%2 : tensor<i32>)
-^bb2(%5: tensor<i32>):
-  %6 = mhlo.add %5, %5 : tensor<i32>
-  cf.br ^bb1(%6 : tensor<i32>)
-^bb3(%7: tensor<i32>):
-  check.expect_eq_const(%7, dense<4> : tensor<i32>) : tensor<i32>
-  return
-}