// 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 "iree/compiler/Codegen/LLVMCPU/KernelDispatch.h"

#include "iree-dialects/Dialect/LinalgExt/IR/LinalgExtOps.h"
#include "iree/compiler/Codegen/Transforms/Transforms.h"
#include "iree/compiler/Codegen/Utils/MarkerUtils.h"
#include "iree/compiler/Codegen/Utils/Utils.h"
#include "iree/compiler/Dialect/Flow/IR/FlowOps.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/TargetSelect.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h"
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/MemRef/Transforms/Passes.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"

namespace mlir {
namespace iree_compiler {

/// NOTE: None of these flags are supported in any form long term. This are
/// temporary hooks added for development purposes. They could be
/// changed/modified at any time.
/// TODO: Find a way to plumb this through to not rely on these flags.

static llvm::cl::opt<int> clNativeVectorSizeInBytes(
    "iree-codegen-llvm-vector-size-in-bytes",
    llvm::cl::desc("native vector size to use on the hardware"),
    llvm::cl::init(16));

static llvm::cl::opt<int> clNumberOfRuntimeThreads(
    "iree-codegen-llvm-number-of-threads",
    llvm::cl::desc("number of threads that are used at runtime"),
    llvm::cl::init(8));

static llvm::cl::list<int> mmt4dWorkgroupTileSizes(
    "iree-codegen-llvm-mmt4d-workgroup-tile-sizes",
    llvm::cl::desc("linalg.mmt4d workgroup tile size"), llvm::cl::ZeroOrMore);

static llvm::cl::list<int> mmt4dL1TileSizes(
    "iree-codegen-llvm-mmt4d-l1-tile-size",
    llvm::cl::desc("linalg.mmt4d L1 tile size"), llvm::cl::ZeroOrMore);

static llvm::cl::list<int> mmt4dVectorSizes(
    "iree-codegen-llvm-mmt4d-vector-size",
    llvm::cl::desc("linalg.mmt4d vector tile size"), llvm::cl::ZeroOrMore);

static llvm::cl::opt<int> defaultWorkgroupTileSize(
    "iree-codegen-llvm-generic-ops-workgroup-size",
    llvm::cl::desc(
        "linalg.generic and linalg.indexed_generic workgroup tile size"),
    llvm::cl::init(64));

static llvm::cl::opt<bool> useLinalgTransformInterp(
    "iree-codegen-use-linalg-transform-interp",
    llvm::cl::desc(
        "experimental path to use the linalg transform dialect interpreter"),
    llvm::cl::init(false));

using IREE::Codegen::DispatchLoweringPassPipeline;

/// Looks for the `native_vector_size` attribute in the hal.executable.variant
/// op.
static Optional<int64_t> getNativeVectorSizeInBytes(func::FuncOp entryPointFn) {
  auto variantOp =
      entryPointFn->getParentOfType<IREE::HAL::ExecutableVariantOp>();
  if (!variantOp) return llvm::None;
  IREE::HAL::ExecutableTargetAttr targetAttr = variantOp.target();
  if (!targetAttr) return llvm::None;
  auto config = targetAttr.getConfiguration();
  if (!config) return llvm::None;
  auto nativeVectorSizeAttr = config.getAs<IntegerAttr>("native_vector_size");
  if (!nativeVectorSizeAttr) return llvm::None;
  int64_t nativeVectorSizeVal = nativeVectorSizeAttr.getInt();
  if (!nativeVectorSizeVal) return llvm::None;
  return nativeVectorSizeVal;
}

/// For a given `shapedType` or (`byteWidth` of element type) return the number
/// of elements that correspond to the native vector size. Returns 1 as the
/// fallback.
static int64_t getVectorSize(func::FuncOp entryPointFn, unsigned byteWidth) {
  if (Optional<int64_t> nativeVectorSize =
          getNativeVectorSizeInBytes(entryPointFn)) {
    return nativeVectorSize.getValue() / byteWidth;
  }
  return clNativeVectorSizeInBytes / byteWidth;
}
static int64_t getVectorSize(func::FuncOp entryPointFn, ShapedType shapedType) {
  Type elementType = shapedType.getElementType();
  if (!elementType.isIntOrFloat()) return 1;
  unsigned byteWidth = IREE::Util::getRoundedElementByteWidth(elementType);
  return getVectorSize(entryPointFn, byteWidth);
}

/// Returns minimum tiling sizes for each dimension. One dimension is possible
/// to access at different element types. It determines the tiling sizes by
/// looking into all the operands.
static SmallVector<int64_t> getMinTilingSizesForEachDim(
    func::FuncOp entryPointFn, linalg::LinalgOp op) {
  unsigned numLoops = op.getNumLoops();
  SmallVector<int64_t> minTileSizes(numLoops, 1);
  auto inputOutputOpOperands = op.getInputAndOutputOperands();
  for (auto map : llvm::enumerate(op.getIndexingMaps())) {
    // Check the fastest varying dimension of the operand. Set the vector size
    // of the corresponding loop to the vector size.
    if (map.value().getNumResults() == 0) continue;
    auto fastestVaryingDimExpr =
        map.value().getResults().back().dyn_cast<AffineDimExpr>();
    if (!fastestVaryingDimExpr) continue;
    unsigned fastestVaryingDim = fastestVaryingDimExpr.getPosition();

    // If the indexing map has result it has to be a shaped type.
    auto operandType =
        inputOutputOpOperands[map.index()]->get().getType().cast<ShapedType>();
    minTileSizes[fastestVaryingDim] =
        std::max<int64_t>(minTileSizes[fastestVaryingDim],
                          getVectorSize(entryPointFn, operandType));
  }
  return minTileSizes;
}

/// Returns the type length in bytes. Looks through all the interface binding
/// ops to see the ABI types and guess-timates the type size to use. This is
/// used to convert the vector size in bytes to vector size in number of
/// elements.
static unsigned getReferenceTypeLengthInBytes(func::FuncOp entryPointFn) {
  unsigned referenceTypeLengthInBytes = 4;
  entryPointFn.walk([&](IREE::HAL::InterfaceBindingSubspanOp subSpanOp) {
    Type type = subSpanOp.getResult().getType();
    Type elementType = TypeSwitch<Type, Type>(type)
                           .Case<ShapedType, IREE::Flow::DispatchTensorType>(
                               [&](auto shapedType) -> Type {
                                 // Ignore operands that are 0D tensors. These
                                 // are not vector-loadable, so using these to
                                 // get vector length would be a pessimization.
                                 if (!shapedType.getRank()) return nullptr;
                                 return shapedType.getElementType();
                               })
                           .Default([&](Type t) -> Type { return nullptr; });
    if (!elementType || !elementType.isIntOrFloat()) return;
    unsigned typeWidthInBytes =
        IREE::Util::getRoundedElementByteWidth(elementType);
    referenceTypeLengthInBytes =
        std::min<unsigned>(referenceTypeLengthInBytes, typeWidthInBytes);
  });
  return referenceTypeLengthInBytes;
}

/// Returns the default tile sizes to use for the loops that are distributed at
/// Flow level.
static SmallVector<int64_t> getDefaultDistributedLoopTileSizes(
    ArrayRef<int64_t> lbs, ArrayRef<int64_t> ubs,
    ArrayRef<int64_t> minTileSizes, ArrayRef<int64_t> maxTileSizes) {
  assert(lbs.size() == ubs.size() && lbs.size() == minTileSizes.size() &&
         lbs.size() == maxTileSizes.size() &&
         "expected all vectors to be of equal size");
  if (lbs.empty()) {
    return {};
  }
  size_t numDims = lbs.size();
  SmallVector<int64_t> distributedTileSizes(numDims, 1);
  SmallVector<int64_t> numWorkgroupsPerDim(numDims, 1);
  SmallVector<int64_t> workload(numDims, 1);
  auto ceilFn = [](int64_t a, int64_t b) { return (a + b - 1) / b; };

  for (auto i : llvm::seq<size_t>(0, numDims)) {
    if (ShapedType::isDynamic(lbs[i]) || ShapedType::isDynamic(ubs[i])) {
      distributedTileSizes[i] = maxTileSizes[i];
      workload[i] = ShapedType::kDynamicSize;
      continue;
    }
    int64_t candidateTileSize = 1;
    if (ubs[i] > lbs[i]) {
      // Pick a value that evenly distributes the workload.
      candidateTileSize = std::max<int64_t>(
          llvm::PowerOf2Floor(static_cast<uint64_t>(ubs[i] - lbs[i]) / 2),
          minTileSizes[i]);
    }

    // Limit the workload per workgroup to the default being the max to keep the
    // work per invocation reasonable.
    distributedTileSizes[i] =
        std::min<int64_t>(candidateTileSize, maxTileSizes[i]);
    workload[i] = (ubs[i] <= lbs[i] ? 1 : ubs[i] - lbs[i]);
    numWorkgroupsPerDim[i] = ceilFn(workload[i], distributedTileSizes[i]);
  }

  // Reduce the number of workgroups in cases where we are dividing the work too
  // much. Over-provision the number of workgroups to twice the number of
  // threads.
  int64_t numWorkgroupsLimit = 2 * clNumberOfRuntimeThreads;
  int64_t numWorkgroups = 1;
  for (auto ng : numWorkgroupsPerDim) {
    numWorkgroups *= ng;
  }
  unsigned currDim = numDims;
  while (numWorkgroups > numWorkgroupsLimit && currDim > 0) {
    if (distributedTileSizes[currDim - 1] >= maxTileSizes[currDim - 1] ||
        workload[currDim - 1] == ShapedType::kDynamicSize ||
        distributedTileSizes[currDim - 1] >= workload[currDim - 1]) {
      currDim--;
      continue;
    }
    distributedTileSizes[currDim - 1] = std::min<int64_t>(
        distributedTileSizes[currDim - 1] * 2, maxTileSizes[currDim - 1]);
    int64_t nwg =
        ceilFn(workload[currDim - 1], distributedTileSizes[currDim - 1]);
    if (nwg < numWorkgroupsPerDim[currDim - 1]) {
      numWorkgroups /= numWorkgroupsPerDim[currDim - 1];
      numWorkgroups *= nwg;
    } else {
      currDim--;
    }
  }
  return distributedTileSizes;
}

/// Adjusts the workload per workgroup to be a multiple of vector size to ensure
/// that the op vectorizes.
static int64_t getMaxTileSize(int64_t lb, int64_t ub, int64_t maxSize,
                              int64_t vectorSizeVal) {
  if (ub == ShapedType::kDynamicSize || lb == ShapedType::kDynamicSize) {
    return maxSize;
  }
  int64_t dim = ub - lb;
  if (dim < vectorSizeVal) return dim;
  for (int64_t i = std::min(maxSize, dim); i > 0; --i) {
    if (dim % i == 0 && i % vectorSizeVal == 0) {
      return i;
    }
  }
  // If it can't be a multiple of vectorSizeVal, let's choose a factor of dim
  // sizes heuristically.
  int64_t start = std::min(maxSize, dim);
  start = std::min(start, vectorSizeVal * 2);
  for (int64_t i = start; i > 0; --i) {
    if (dim % i == 0) {
      return i;
    }
  }
  return 1;
}

/// Returns the tile size to use for the Flow level of an operation that
/// implements the `PartitionableLoopsInterface`.
static SmallVector<int64_t> getDefaultDistributedLevelTileSizes(
    ArrayRef<Range> iterationDomain,
    IREE::Flow::PartitionableLoopsInterface partitionableLoopInterfaceOp,
    ArrayRef<int64_t> minTileSizes, ArrayRef<int64_t> maxTileSizes) {
  assert(iterationDomain.size() == minTileSizes.size() &&
         "expected as many min tile sizes as number of loops");
  auto getStaticValue = [](Value v) -> int64_t {
    IntegerAttr attr;
    if (!matchPattern(v, m_Constant(&attr))) return ShapedType::kDynamicSize;
    return attr.getInt();
  };
  auto lbs = llvm::to_vector(llvm::map_range(
      iterationDomain, [&](Range r) { return getStaticValue(r.offset); }));
  auto ubs = llvm::to_vector(llvm::map_range(
      iterationDomain, [&](Range r) { return getStaticValue(r.size); }));

  SmallVector<unsigned> partitionableLoops =
      partitionableLoopInterfaceOp.getPartitionableLoops(kNumMaxParallelDims);
  llvm::SmallDenseSet<unsigned, 4> partitionableLoopsSet;
  partitionableLoopsSet.insert(partitionableLoops.begin(),
                               partitionableLoops.end());

  size_t numPartitionedLoops = partitionableLoops.size();
  SmallVector<int64_t> distributedLoopLbs(numPartitionedLoops,
                                          ShapedType::kDynamicSize),
      distributedLoopUbs(numPartitionedLoops, ShapedType::kDynamicSize),
      minDistributedLoopTileSizes(numPartitionedLoops, 1),
      maxDistributedLoopTileSizes(numPartitionedLoops,
                                  defaultWorkgroupTileSize);
  // Find the bounds of the partitionable loops
  unsigned index = 0;
  for (auto range : llvm::enumerate(iterationDomain)) {
    if (!partitionableLoopsSet.count(range.index())) continue;

    minDistributedLoopTileSizes[index] = minTileSizes[range.index()];
    maxDistributedLoopTileSizes[index] = maxTileSizes[range.index()];
    distributedLoopLbs[index] = lbs[range.index()];
    distributedLoopUbs[index] = ubs[range.index()];
    index++;
  }

  SmallVector<int64_t> distributedTileSizes =
      getDefaultDistributedLoopTileSizes(distributedLoopLbs, distributedLoopUbs,
                                         minDistributedLoopTileSizes,
                                         maxDistributedLoopTileSizes);
  SmallVector<int64_t> distributedLevelTileSizes(iterationDomain.size(), 0);
  for (auto loopID : llvm::enumerate(partitionableLoops)) {
    distributedLevelTileSizes[loopID.value()] =
        distributedTileSizes[loopID.index()];
  }
  // Final fix up of the tile sizes to make sure that they divide the problem
  // size to make it vectorizable.
  for (auto i : llvm::seq<unsigned>(0, distributedLevelTileSizes.size())) {
    distributedLevelTileSizes[i] =
        distributedLevelTileSizes[i] != 0
            ? getMaxTileSize(lbs[i], ubs[i], distributedLevelTileSizes[i],
                             minTileSizes[i])
            : 0;
  }
  return distributedLevelTileSizes;
}

/// Splits the tile sizes in `parallelSizes` into `reductionSizes` for the
/// reduction loops.
static void splitParallelAndReductionTiles(
    linalg::LinalgOp op, SmallVectorImpl<int64_t> &parallelSizes,
    SmallVectorImpl<int64_t> &reductionSizes) {
  reductionSizes.assign(parallelSizes.begin(), parallelSizes.end());
  for (auto iteratorType : llvm::enumerate(op.iterator_types())) {
    if (iteratorType.value().cast<StringAttr>().getValue() ==
        getParallelIteratorTypeName()) {
      reductionSizes[iteratorType.index()] = 0;
    } else {
      parallelSizes[iteratorType.index()] = 0;
    }
  }
}

static void setAlwaysVectorizeSizes(linalg::LinalgOp op,
                                    SmallVectorImpl<int64_t> &parallelSizes,
                                    SmallVectorImpl<int64_t> &reductionSizes) {
  Optional<SmallVector<int64_t, 4>> staticLoopRanges = op.getStaticLoopRanges();
  for (auto en :
       llvm::enumerate(llvm::zip(*staticLoopRanges, op.iterator_types()))) {
    auto size = std::get<0>(en.value());
    if (!ShapedType::isDynamic(size)) continue;
    auto iterType = std::get<1>(en.value()).cast<StringAttr>().getValue();
    if (iterType == getParallelIteratorTypeName()) {
      parallelSizes[en.index()] = 1;
    } else {
      reductionSizes[en.index()] = 1;
    }
  }
}

/// Sets the default configuration to use for an operation that implements the
/// `PartitionableLoopsInterface`, given the iteration domain of all the loops.
static LogicalResult setDefaultRootConfig(
    func::FuncOp entryPointFn,
    IREE::Flow::PartitionableLoopsInterface partitionableLoopsInterfaceOp,
    ArrayRef<Range> iterationDomain) {
  if (getLoweringConfig(partitionableLoopsInterfaceOp)) return success();

  SmallVector<unsigned> partitionableLoops =
      partitionableLoopsInterfaceOp.getPartitionableLoops(kNumMaxParallelDims);

  SmallVector<int64_t> minTileSizes(iterationDomain.size(), 1);
  SmallVector<int64_t> maxTileSizes(iterationDomain.size(), 1);
  if (!partitionableLoops.empty()) {
    // TODO: Here the min tile size is just looking at the type of the data in
    // the entry point function, and using a vector size that depends on just
    // that. For `LinalgOp`s we can use the indexing map, find the loops that
    // are fastest varying and set those to have a min tile size of vector
    // length. A version of this is done for generic ops. Generalize that and
    // use it for `LinalgOp`s.
    unsigned typeWidthInBytes = getReferenceTypeLengthInBytes(entryPointFn);
    minTileSizes[partitionableLoops.back()] =
        getVectorSize(entryPointFn, typeWidthInBytes);
    for (auto partitionableLoopId : partitionableLoops) {
      maxTileSizes[partitionableLoopId] = defaultWorkgroupTileSize;
    }
  }

  SmallVector<int64_t> flowTileSizes = getDefaultDistributedLevelTileSizes(
      iterationDomain, partitionableLoopsInterfaceOp, minTileSizes,
      maxTileSizes);
  TileSizesListType tileSizes;
  tileSizes.emplace_back(std::move(flowTileSizes));
  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, partitionableLoopsInterfaceOp, tileSizes,
      DispatchLoweringPassPipeline::CPUDefault);
}

static LogicalResult setSandboxRootConfig(func::FuncOp entryPointFn,
                                          linalg::ContractionOpInterface op,
                                          ArrayRef<int64_t> flowTileSizes,
                                          ArrayRef<int64_t> target2ndTileSizes,
                                          int vectorSize) {
  assert(target2ndTileSizes.size() == 3 &&
         "the current configuration is driven by matmul which has exactly "
         "three loops");
  // The tiling for parallel dims and reduction dims should be separated.
  SmallVector<int64_t> parallelTileSizes;
  auto linalgOp = cast<linalg::LinalgOp>(op.getOperation());
  int64_t nLoops = linalgOp.getNumLoops();
  if (nLoops >= 3) {
    parallelTileSizes.append(nLoops - 3, 1);
    parallelTileSizes.push_back(getMaxTileSize(
        0, flowTileSizes[nLoops - 3], target2ndTileSizes[0], vectorSize));
  }
  if (nLoops >= 2) {
    parallelTileSizes.push_back(getMaxTileSize(
        0, flowTileSizes[nLoops - 2], target2ndTileSizes[1], vectorSize));
  }
  parallelTileSizes.push_back(0);

  auto lhsShapedType = op.lhs().getType().cast<ShapedType>();
  int64_t K = lhsShapedType.getShape().back();
  SmallVector<int64_t> reductionTileSizes;
  reductionTileSizes.append(nLoops - 1, 0);
  reductionTileSizes.push_back(
      getMaxTileSize(0, K, target2ndTileSizes[2], vectorSize));

  setAlwaysVectorizeSizes(linalgOp, parallelTileSizes, reductionTileSizes);

  TileSizesListType tileSizes;
  tileSizes.emplace_back(flowTileSizes.begin(), flowTileSizes.end());
  tileSizes.push_back(parallelTileSizes);
  tileSizes.push_back(reductionTileSizes);

  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, op, tileSizes,
      DispatchLoweringPassPipeline::CPUDoubleTilingExpert);
}

static LogicalResult setARMRootConfig(func::FuncOp entryPointFn,
                                      linalg::ContractionOpInterface op,
                                      ArrayRef<int64_t> flowTileSizes,
                                      int vectorSize) {
  // Hardcoded tile sizes, where v is the native vector size.
  // L1 tile sizes are {1, ..., 5v, v, 16v}.
  // Vector tile sizes are {1, ..., v, v, v}
  SmallVector<int64_t> l1TileSizes, vectorTileSizes;
  int64_t nLoops = cast<linalg::LinalgOp>(op.getOperation()).getNumLoops();
  if (nLoops >= 3) {
    l1TileSizes.append(nLoops - 3, 1);
    l1TileSizes.push_back(getMaxTileSize(0, flowTileSizes[nLoops - 3],
                                         5 * vectorSize, vectorSize));
    vectorTileSizes.append(nLoops - 3, 1);
    vectorTileSizes.push_back(vectorSize);
  }
  if (nLoops >= 2) {
    l1TileSizes.push_back(
        getMaxTileSize(0, flowTileSizes[nLoops - 2], vectorSize, vectorSize));
    vectorTileSizes.push_back(vectorSize);
  }

  // L1/vector tile size for k dimensions.
  auto lhsShapedType = op.lhs().getType().cast<ShapedType>();
  int64_t K = lhsShapedType.getShape().back();
  l1TileSizes.push_back(getMaxTileSize(0, K, 16 * vectorSize, vectorSize));
  vectorTileSizes.push_back(vectorSize);
  TileSizesListType tileSizes;
  tileSizes.emplace_back(flowTileSizes.begin(), flowTileSizes.end());
  tileSizes.push_back(l1TileSizes);
  tileSizes.push_back(vectorTileSizes);

  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, op, tileSizes,
      DispatchLoweringPassPipeline::CPUTileFuseAndVectorize);
}

/// Sets the lowering configuration for dispatch region with root op that
/// implements the contraction operation interface.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::ContractionOpInterface contractionOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  auto linalgOp = cast<linalg::LinalgOp>(contractionOp.getOperation());
  unsigned numLoops = linalgOp.getNumLoops();
  {
    SmallVector<unsigned> dims;
    linalgOp.getReductionDims(dims);
    if (dims.size() != 1 || dims[0] != numLoops - 1) {
      return contractionOp.emitOpError(
          "expected to have exactly one reduction dim, and it is the innermost "
          "dim");
    }
  }

  // Consider all element types and use the smallest vector size. The tiling
  // sizes are chosen based on the vector size.
  auto lhsShapedType = contractionOp.lhs().getType().cast<ShapedType>();
  auto rhsShapedType = contractionOp.rhs().getType().cast<ShapedType>();
  auto resShapedType =
      linalgOp.getOutputOperand(0)->get().getType().cast<ShapedType>();
  int64_t vectorSize = getVectorSize(entryPointFn, lhsShapedType);
  vectorSize = std::min(vectorSize, getVectorSize(entryPointFn, rhsShapedType));
  vectorSize = std::min(vectorSize, getVectorSize(entryPointFn, resShapedType));

  // Use the default distribution for the matmul loops.
  SmallVector<int64_t> minTileSizes =
      getMinTilingSizesForEachDim(entryPointFn, linalgOp);
  SmallVector<int64_t> maxTileSizes(numLoops, defaultWorkgroupTileSize);
  if (numLoops > 3) {
    minTileSizes[0] = 1;
    maxTileSizes[0] = 1;
  }

  OpBuilder builder(entryPointFn.getContext());
  builder.setInsertionPoint(contractionOp);
  SmallVector<Range> iterationDomain =
      linalgOp.createLoopRanges(builder, linalgOp->getLoc());
  SmallVector<int64_t> flowTileSizes = getDefaultDistributedLevelTileSizes(
      iterationDomain,
      cast<IREE::Flow::PartitionableLoopsInterface>(
          contractionOp.getOperation()),
      minTileSizes, maxTileSizes);

  // TODO(dcaballe): Find better configurations for RISC-V backends.
  if (isX86(entryPointFn) || isRISCV(entryPointFn)) {
    SmallVector<int64_t> tileSizes = {8, 32, 16};
    return setSandboxRootConfig(entryPointFn, contractionOp, flowTileSizes,
                                tileSizes, vectorSize);
  }

  // Fall back to ARM configurations.
  bool isQuantized =
      lhsShapedType.getElementType() != resShapedType.getElementType();
  if (isQuantized) {
    SmallVector<int64_t> tileSizes = {4, 16, 4};
    return setSandboxRootConfig(entryPointFn, contractionOp, flowTileSizes,
                                tileSizes, vectorSize);
  } else {
    return setARMRootConfig(entryPointFn, contractionOp, flowTileSizes,
                            vectorSize);
  }
}

/// Sets the lowering configuration for dispatch region for linalg.mmt4d root
/// op
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::Mmt4DOp mmt4dOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  // TODO(ataei): These are hand tuned for some performance benchmarks for
  // now, we want to adapt the same strategy as matmul that dynamically sets
  // tile size.
  auto getWorkgroupTileSizes = [&]() -> SmallVector<int64_t> {
    if (!mmt4dWorkgroupTileSizes.empty()) {
      return SmallVector<int64_t>(mmt4dWorkgroupTileSizes.begin(),
                                  mmt4dWorkgroupTileSizes.end());
    }
    return {48, 32};
  };

  auto getL1TileSizes = [&]() -> SmallVector<int64_t> {
    auto lhsShape = mmt4dOp.inputs()[0].getType().cast<ShapedType>().getShape();
    auto rhsShape = mmt4dOp.inputs()[1].getType().cast<ShapedType>().getShape();
    int M0 = lhsShape[2];
    int N0 = rhsShape[2];
    int K0 = lhsShape[3];
    if (!mmt4dL1TileSizes.empty()) {
      return SmallVector<int64_t>(mmt4dL1TileSizes.begin(),
                                  mmt4dL1TileSizes.end());
    }
    return {1, 1, 1, M0, N0, K0};
  };

  auto getVectorSizes = [&]() -> SmallVector<int64_t> {
    auto lhsShape = mmt4dOp.inputs()[0].getType().cast<ShapedType>().getShape();
    auto rhsShape = mmt4dOp.inputs()[1].getType().cast<ShapedType>().getShape();
    int M0 = lhsShape[2];
    int N0 = rhsShape[2];
    int K0 = lhsShape[3];
    if (!mmt4dVectorSizes.empty()) {
      return SmallVector<int64_t>(mmt4dVectorSizes.begin(),
                                  mmt4dVectorSizes.end());
    }
    return {1, 1, 1, M0, N0, K0};
  };

  SmallVector<int64_t> nativeVectorSize = getVectorSizes();

  TileSizesListType tileSizes = {getWorkgroupTileSizes(), getL1TileSizes(),
                                 nativeVectorSize};

  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, mmt4dOp, tileSizes,
      DispatchLoweringPassPipeline::CPUTileFuseAndVectorize);
}

/// Sets the lowering configuration for dispatch region for linalg_ext.fft
/// root op.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, IREE::LinalgExt::FftOp fftOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  unsigned numLoops = fftOp.getLoopIteratorTypes().size();
  auto partitionedLoops = fftOp.getPartitionableLoops(kNumMaxParallelDims);
  SmallVector<int64_t> workgroupTileSizes(numLoops, defaultWorkgroupTileSize);
  llvm::DenseSet<unsigned> partitionedLoopsSet(partitionedLoops.begin(),
                                               partitionedLoops.end());
  for (auto dim : llvm::seq<int64_t>(0, workgroupTileSizes.size())) {
    if (!partitionedLoopsSet.count(dim)) {
      workgroupTileSizes[dim] = 0;
    }
  }

  auto rank = fftOp.getOperandRank();
  if (workgroupTileSizes.size() >= rank && workgroupTileSizes[rank - 1] != 0) {
    APInt value;
    if (matchPattern(fftOp.getStage(), m_ConstantInt(&value))) {
      workgroupTileSizes[rank - 1] = 1ll << value.getSExtValue();
      workgroupTileSizes[rank - 1] =
          std::max(workgroupTileSizes[rank - 1],
                   static_cast<int64_t>(defaultWorkgroupTileSize));
    } else {
      return fftOp.emitOpError("non-constant stage might not work for fft op");
    }
  }
  TileSizesListType tileSizes = {workgroupTileSizes};
  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, fftOp, tileSizes, DispatchLoweringPassPipeline::CPUDefault);
}

static void setX86WorkgroupTileSizes(
    linalg::GenericOp genericOp, unsigned numLoops,
    ArrayRef<int64_t> flowTileSizes, ArrayRef<int64_t> minTileSizes,
    ArrayRef<int64_t> maxTileSizes,
    SmallVectorImpl<int64_t> &workgroupTileSizes) {
  workgroupTileSizes.append(numLoops, 0);
  Optional<SmallVector<int64_t, 4>> staticLoopRanges =
      genericOp.getStaticLoopRanges();
  for (auto loopNum : llvm::seq<unsigned>(0, numLoops)) {
    if (flowTileSizes[loopNum]) {
      workgroupTileSizes[loopNum] =
          getMaxTileSize(0, flowTileSizes[loopNum], minTileSizes[loopNum],
                         minTileSizes[loopNum]);
    } else {
      // If the flow level tile size is zero, and static loop range is 0 as
      // well, set the tile sizes here to zero as well.
      workgroupTileSizes[loopNum] =
          (staticLoopRanges && staticLoopRanges.getValue()[loopNum] == 1)
              ? 0
              : minTileSizes[loopNum];
    }
  }
}

/// Returns true if the operation is a GenericOp implementing a supported
/// transposition.
static bool isSupportedTransposeOp(linalg::GenericOp genericOp) {
  // Check that the op has at least 2 dimensions.
  if (genericOp.getNumLoops() < 2) {
    return false;
  }

  // Check that the op has only one input and one output.
  // TODO(diegocaballero): Generalize to multiple inputs.
  if ((genericOp.getNumInputs() != 1) || (genericOp.getNumOutputs() != 1)) {
    return false;
  }

  // Check that all the iterators are parallel.
  if (genericOp.getNumParallelLoops() != genericOp.getNumLoops()) {
    return false;
  }

  // Check that the two indexing maps are a permutation of each other.
  auto indexing_maps = genericOp.getIndexingMaps();
  return !indexing_maps[0].isEmpty() && !indexing_maps[1].isEmpty() &&
         ((indexing_maps[0].isIdentity() && !indexing_maps[1].isIdentity() &&
           indexing_maps[1].isPermutation()) ||
          (!indexing_maps[0].isIdentity() && indexing_maps[0].isPermutation() &&
           indexing_maps[1].isIdentity()));
}

/// Sets the default lowering configuration for a generic op to use
/// CPUDoubleTilingExpert pipeline.
static LogicalResult setDefaultGenericOpRootConfig(
    func::FuncOp entryPointFn, linalg::GenericOp genericOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (getLoweringConfig(genericOp)) {
    return success();
  }

  // If there are no loops, there is nothing to do.
  unsigned numLoops = genericOp.getNumLoops();
  if (numLoops == 0) return success();

  SmallVector<int64_t> minTileSizes =
      getMinTilingSizesForEachDim(entryPointFn, genericOp);
  SmallVector<int64_t> maxTileSizes(numLoops, defaultWorkgroupTileSize);
  if (llvm::all_of(minTileSizes, [](int64_t vs) { return vs == 1; })) {
    // Nothing to vectorize just lower to loops.
    return success();
  }

  // Set the flow level tiling to the default.
  OpBuilder builder(genericOp.getContext());
  builder.setInsertionPoint(genericOp);
  auto linalgOp = cast<linalg::LinalgOp>(genericOp.getOperation());
  SmallVector<Range> iterationDomain =
      linalgOp.createLoopRanges(builder, genericOp.getLoc());
  auto partitionableLoopsInterfaceOp =
      cast<IREE::Flow::PartitionableLoopsInterface>(genericOp.getOperation());
  SmallVector<int64_t> flowTileSizes = getDefaultDistributedLevelTileSizes(
      iterationDomain, partitionableLoopsInterfaceOp, minTileSizes,
      maxTileSizes);

  // Set the next level tile sizes.
  SmallVector<int64_t> parallelTileSizes;
  SmallVector<int64_t> reductionTileSizes;
  setX86WorkgroupTileSizes(genericOp, numLoops, flowTileSizes, minTileSizes,
                           maxTileSizes, parallelTileSizes);
  splitParallelAndReductionTiles(genericOp, parallelTileSizes,
                                 reductionTileSizes);
  setAlwaysVectorizeSizes(linalgOp, parallelTileSizes, reductionTileSizes);

  TileSizesListType tileSizes;
  tileSizes.push_back(flowTileSizes);
  tileSizes.push_back(parallelTileSizes);
  tileSizes.push_back(reductionTileSizes);

  // For non-tensor based ops use the Buffer ops pipeline.
  auto passPipeline =
      genericOp.hasTensorSemantics()
          ? DispatchLoweringPassPipeline::CPUDoubleTilingExpert
          : DispatchLoweringPassPipeline::CPUBufferOpsTileAndVectorize;
  return setOpConfigAndEntryPointFnTranslation(entryPointFn, genericOp,
                                               tileSizes, passPipeline);
}

/// Sets the lowering configuration for a generic op implementing a
/// transposition to use CPUDoubleTilingExpert pipeline.
static LogicalResult setTransposeLikeOpRootConfig(
    func::FuncOp entryPointFn, linalg::GenericOp genericOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (getLoweringConfig(genericOp)) {
    return success();
  }

  if (!hasAVX2Features(genericOp) || !isSupportedTransposeOp(genericOp)) {
    return success();
  }

  unsigned numLoops = genericOp.getNumLoops();
  SmallVector<int64_t> minTileSizes =
      getMinTilingSizesForEachDim(entryPointFn, genericOp);
  SmallVector<int64_t> maxTileSizes(numLoops, defaultWorkgroupTileSize);
  if (llvm::all_of(minTileSizes, [](int64_t vs) { return vs == 1; })) {
    // Nothing to vectorize just lower to loops.
    return success();
  }

  if (llvm::count_if(minTileSizes,
                     [](int64_t tileSize) { return tileSize > 1; }) != 2) {
    // Transpose patterns are not applicable if vectorizing more or less than
    // two dims.
    return success();
  }

  // Make sure that the original tile sizes are multiple of the tile sizes
  // to be used for the transpose op (i.e., 8x8).
  // TODO(diegocaballero): Enable 4x8 tile sizes if we find it useful.
  if (llvm::any_of(minTileSizes, [](int64_t tileSize) {
        return tileSize > 1 && (tileSize % 8) != 0;
      })) {
    return success();
  }

  // Replace dims to be vectorized with the new 8x8 tile sizes.
  std::replace_if(
      minTileSizes.begin(), minTileSizes.end(),
      [](int64_t tileSize) { return tileSize > 1; }, 8);

  // Set the flow level tiling to the default.
  OpBuilder builder(genericOp.getContext());
  builder.setInsertionPoint(genericOp);
  auto linalgOp = cast<linalg::LinalgOp>(genericOp.getOperation());
  SmallVector<Range> iterationDomain =
      linalgOp.createLoopRanges(builder, genericOp.getLoc());
  auto partitionableLoopsInterfaceOp =
      cast<IREE::Flow::PartitionableLoopsInterface>(genericOp.getOperation());
  SmallVector<int64_t> flowTileSizes = getDefaultDistributedLevelTileSizes(
      iterationDomain, partitionableLoopsInterfaceOp, minTileSizes,
      maxTileSizes);

  // Set the next level tile sizes.
  SmallVector<int64_t> parallelTileSizes;
  setX86WorkgroupTileSizes(genericOp, numLoops, flowTileSizes, minTileSizes,
                           maxTileSizes, parallelTileSizes);

  TileSizesListType tileSizes;
  tileSizes.push_back(flowTileSizes);
  tileSizes.push_back(parallelTileSizes);
  tileSizes.push_back(/*reduction tile sizes*/ {});

  // For non-tensor based ops use the Buffer ops pipeline.
  auto passPipeline =
      genericOp.hasTensorSemantics()
          ? DispatchLoweringPassPipeline::CPUDoubleTilingExpert
          : DispatchLoweringPassPipeline::CPUBufferOpsTileAndVectorize;
  return setOpConfigAndEntryPointFnTranslation(entryPointFn, genericOp,
                                               tileSizes, passPipeline);
}

/// Sets the lowering configuration for a generic op to use
/// CPUDoubleTilingExpert pipeline.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::GenericOp genericOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (failed(
          setTransposeLikeOpRootConfig(entryPointFn, genericOp, tiledLoops)) ||
      failed(
          setDefaultGenericOpRootConfig(entryPointFn, genericOp, tiledLoops))) {
    return failure();
  }
  return success();
}

/// Sets the lowering configuration for linalg.conv_2d_nhwc_hwcf and
/// linalg.depthwise_conv_2d_nhwc_hwc operations.
static LogicalResult setConvRootConfig(
    func::FuncOp entryPointFn, linalg::LinalgOp convOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops,
    ArrayRef<int64_t> targetTileSizes, int64_t vectorSize) {
  if (!isa<linalg::Conv2DNhwcHwcfOp, linalg::DepthwiseConv2DNhwcHwcOp>(
          convOp.getOperation())) {
    return failure();
  }

  // Use the default distribution for the conv loops.
  unsigned numLoops = convOp.getNumLoops();
  SmallVector<int64_t> minTileSizes(numLoops, 1);
  SmallVector<int64_t> maxTileSizes(numLoops, defaultWorkgroupTileSize);

  // Set the flow level tiling to the default.
  OpBuilder builder(convOp.getContext());
  builder.setInsertionPoint(convOp);
  SmallVector<Range> iterationDomain =
      convOp.createLoopRanges(builder, convOp.getLoc());
  auto partitionableLoopsInterfaceOp =
      cast<IREE::Flow::PartitionableLoopsInterface>(convOp.getOperation());
  SmallVector<int64_t> flowTileSizes = getDefaultDistributedLevelTileSizes(
      iterationDomain, partitionableLoopsInterfaceOp, minTileSizes,
      maxTileSizes);

  // Shapes of N, OH, OW, OC, KH, KW, (IC)
  Optional<SmallVector<int64_t, 4>> shapes = convOp.getStaticLoopRanges();
  SmallVector<int64_t> parallelTileSizes(targetTileSizes.begin(),
                                         targetTileSizes.end());
  for (auto i : llvm::seq<unsigned>(0, parallelTileSizes.size())) {
    auto tileSize = flowTileSizes[i] ? flowTileSizes[i] : shapes.getValue()[i];
    // If the tile size is intended to be 1, do not adjust it to `vectorSize`.
    // The ops will be decomposed to lower-rank named ops.
    if (parallelTileSizes[i] != 1) {
      parallelTileSizes[i] =
          getMaxTileSize(0, tileSize, parallelTileSizes[i], vectorSize);
    }
  }
  SmallVector<int64_t> reductionTileSizes;
  splitParallelAndReductionTiles(convOp, parallelTileSizes, reductionTileSizes);
  setAlwaysVectorizeSizes(convOp, parallelTileSizes, reductionTileSizes);

  TileSizesListType tileSizes;
  tileSizes.push_back(flowTileSizes);
  tileSizes.push_back(parallelTileSizes);
  tileSizes.push_back(reductionTileSizes);
  return setOpConfigAndEntryPointFnTranslation(
      entryPointFn, convOp, tileSizes,
      DispatchLoweringPassPipeline::CPUConvTileAndDecomposeExpert);
}

static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::Conv2DNhwcHwcfOp convOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  auto linalgOp = cast<linalg::LinalgOp>(convOp.getOperation());
  int64_t vectorSize =
      getVectorSize(entryPointFn, convOp.getResult(0).getType());
  SmallVector<int64_t> targetTileSizes = {1, 1, 8, vectorSize * 2, 1, 1, 8};
  return setConvRootConfig(entryPointFn, linalgOp, tiledLoops, targetTileSizes,
                           vectorSize);
}

/// Sets the lowering configuration for linalg.depthwise_conv_2d_nhwc_hwc
/// operations.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::DepthwiseConv2DNhwcHwcOp convOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  auto linalgOp = cast<linalg::LinalgOp>(convOp.getOperation());
  int64_t vectorSize =
      getVectorSize(entryPointFn, convOp.getResult(0).getType());
  SmallVector<int64_t> targetTileSizes = {1, 1, 8, vectorSize * 2, 1, 3};
  return setConvRootConfig(entryPointFn, linalgOp, tiledLoops, targetTileSizes,
                           vectorSize);
}

/// Set default configuration for Linalg ops.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, linalg::LinalgOp linalgOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (getLoweringConfig(linalgOp)) return success();

  OpBuilder builder(linalgOp.getContext());
  builder.setInsertionPoint(linalgOp);
  SmallVector<Range> iterationDomain =
      linalgOp.createLoopRanges(builder, linalgOp.getLoc());

  auto partitionableLoopOp =
      cast<IREE::Flow::PartitionableLoopsInterface>(linalgOp.getOperation());
  return setDefaultRootConfig(entryPointFn, partitionableLoopOp,
                              iterationDomain);
}

/// Set the default configuration for operations that implement the
/// `TiledOpInterface`.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn,
    IREE::LinalgExt::TiledOpInterface tiledOpInterfaceOp,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (getLoweringConfig(tiledOpInterfaceOp)) return success();

  OpBuilder builder(tiledOpInterfaceOp.getContext());
  builder.setInsertionPoint(tiledOpInterfaceOp);
  SmallVector<Range> iterationDomain =
      tiledOpInterfaceOp.getIterationDomain(builder);
  auto partitionableLoopInterfaceOp =
      cast<IREE::Flow::PartitionableLoopsInterface>(
          tiledOpInterfaceOp.getOperation());
  return setDefaultRootConfig(entryPointFn, partitionableLoopInterfaceOp,
                              iterationDomain);
}

/// Redirects to methods that set the configuration based on operation type.
static LogicalResult setRootConfigImpl(
    func::FuncOp entryPointFn, Operation *op,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  // Do not overwrite default configuration.
  if (getLoweringConfig(op)) return success();

  // Redirect to individual operations.
  auto setRootConfigFn = [&](Operation *op) -> LogicalResult {
    return TypeSwitch<Operation *, LogicalResult>(op)
        .Case<IREE::LinalgExt::FftOp, linalg::GenericOp, linalg::Mmt4DOp,
              linalg::Conv2DNhwcHwcfOp, linalg::DepthwiseConv2DNhwcHwcOp>(
            [&](auto op) {
              return setRootConfig(entryPointFn, op, tiledLoops);
            })
        .Case<linalg::ContractionOpInterface>([&](auto op) {
          return setRootConfig(entryPointFn, op, tiledLoops);
        })
        .Case<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(
            [&](auto op) {
              return setRootConfig(entryPointFn, op, tiledLoops);
            })
        .Default([&](Operation *op) { return success(); });
  };
  return setRootConfigFn(op);
}

/// Redirects to methods that set the configuration based on operation type for
/// VMVX backend.
static LogicalResult setVMVXRootConfigImpl(
    func::FuncOp entryPointFn, Operation *op,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  if (getLoweringConfig(op)) return success();

  // Redirect to individual operations.
  auto setRootConfigFn = [&](Operation *op) -> LogicalResult {
    return TypeSwitch<Operation *, LogicalResult>(op)
        .Case<linalg::LinalgOp, IREE::LinalgExt::TiledOpInterface>(
            [&](auto op) {
              return setRootConfig(entryPointFn, op, tiledLoops);
            })
        .Default([&](Operation *op) { return success(); });
  };
  return setRootConfigFn(op);
}

/// Find the root operation for the dispatch region.
static FailureOr<Operation *> getRootOperation(
    ArrayRef<Operation *> computeOps) {
  Operation *rootOperation = nullptr;
  auto updateRootOperation = [&](Operation *op) -> LogicalResult {
    if (rootOperation) {
      return op->emitOpError(
          "unhandled multiple root operations in dispatch region");
    }
    rootOperation = op;
    return success();
  };
  for (auto op : computeOps) {
    if (auto linalgOp = dyn_cast<linalg::LinalgOp>(op)) {
      // Do not not treat linalg ops that are all parallel as root operations in
      // this sweep.
      if (linalgOp.getNumLoops() == linalgOp.getNumParallelLoops()) continue;

      // All other linalg ops are root ops.
      if (failed(updateRootOperation(op))) return failure();
      continue;
    }

    if (auto tiledOpInterfaceOp =
            dyn_cast<IREE::LinalgExt::TiledOpInterface>(op)) {
      // TODO(ravishankarm): For now
      // `tensor.extract_slice`/`tensor.insert_slice` implement the
      // `tiledInterfaceOp`. With tile + distribute moved out of Flow
      // dialect, this doesnt work anymore. Remove this when the external
      // model implementation of
      // `tensor.extract_slice`/`tensor.insert_slice` are dropped.
      if (isa<tensor::ExtractSliceOp, tensor::InsertSliceOp>(op)) continue;

      // All other operations that implement this interface are root ops.
      if (failed(updateRootOperation(op))) return failure();
      continue;
    }
  }
  if (rootOperation) return rootOperation;

  // If no root operation is found yet. Look for linalg generic ops.
  for (auto op : llvm::reverse(computeOps)) {
    if (isa<linalg::LinalgOp>(op)) {
      if (failed(updateRootOperation(op))) return failure();
    }
  }
  return rootOperation;
}

/// Finds the root operation in the given list of Linalg operations and sets
/// its configuration. Returns error for multiple root operations.
static LogicalResult setRootConfig(
    func::FuncOp entryPointFn, ArrayRef<Operation *> computeOps,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  FailureOr<Operation *> rootOp = getRootOperation(computeOps);
  if (failed(rootOp)) {
    return failure();
  }
  Operation *rootOperation = rootOp.getValue();

  if (rootOperation) {
    if (isVMVXBackend(entryPointFn)) {
      if (failed(
              setVMVXRootConfigImpl(entryPointFn, rootOperation, tiledLoops))) {
        return failure();
      }
    } else {
      if (failed(setRootConfigImpl(entryPointFn, rootOperation, tiledLoops))) {
        return failure();
      }
    }
  }

  if (!getTranslationInfo(entryPointFn)) {
    // Fall back, just set the translation to CPUDefault.
    setTranslationInfo(entryPointFn, DispatchLoweringPassPipeline::CPUDefault,
                       /*workloadPerWorkgroup=*/ArrayRef<int64_t>{},
                       /*workgroupSize=*/ArrayRef<int64_t>{});
  }

  return success();
}

/// Sets the translation information to use for a dispatch region.
static LogicalResult setTranslationInfoAndRootConfig(
    func::FuncOp entryPointFn, ArrayRef<Operation *> computeOps,
    ArrayRef<LoopTilingAndDistributionInfo> tiledLoops) {
  // First check if the operations have a preset pipeline.
  for (auto computeOp : computeOps) {
    if (IREE::Codegen::CompilationInfoAttr compilationInfo =
            getCompilationInfo(computeOp)) {
      // If the function already has a translation, error out.
      if (auto translationInfo = getTranslationInfo(entryPointFn)) {
        return computeOp->emitOpError(
            "multiple ops within dispatch trying to set the translation "
            "info");
      }

      SmallVector<int64_t> workgroupSize =
          compilationInfo.getWorkgroupSizeVals();
      setTranslationInfo(entryPointFn, compilationInfo.getTranslationInfo(),
                         workgroupSize);
      setLoweringConfig(computeOp, compilationInfo.getLoweringConfig());
      eraseCompilationInfo(computeOp);
    }
  }

  // Next set the configuration of the operations.
  return setRootConfig(entryPointFn, computeOps, tiledLoops);
}

LogicalResult initCPULaunchConfig(ModuleOp moduleOp) {
  llvm::StringMap<IREE::HAL::ExecutableEntryPointOp> entryPointOps =
      getAllEntryPoints(moduleOp);
  for (auto funcOp : moduleOp.getOps<func::FuncOp>()) {
    auto entryPointOp = entryPointOps.lookup(funcOp.getName());
    if (!entryPointOp) continue;
    if (getTranslationInfo(entryPointOp)) continue;

    // If using sandbox passes, currently set the workload_per_wg to be
    // empty for single-threaded execution.
    if (useLinalgTransformInterp) {
      auto translationInfo = IREE::Codegen::TranslationInfoAttr::get(
          moduleOp.getContext(), IREE::Codegen::DispatchLoweringPassPipeline::
                                     LinalgTransformInterpCodegen);
      setTranslationInfo(funcOp, translationInfo);
      continue;
    }

    SmallVector<Operation *> computeOps;
    SmallVector<LoopTilingAndDistributionInfo> tiledLoops;

    // If there are no linalg ops, not using Linalg based lowering.
    if (failed(getComputeOps(funcOp, computeOps, tiledLoops))) {
      return failure();
    }

    if (failed(
            setTranslationInfoAndRootConfig(funcOp, computeOps, tiledLoops))) {
      return failure();
    }
  }

  // The root confguration setting introduces `tensor.dim` operations. Resolve
  // those away.
  RewritePatternSet patterns(moduleOp.getContext());
  memref::populateResolveRankedShapeTypeResultDimsPatterns(patterns);
  return applyPatternsAndFoldGreedily(moduleOp, std::move(patterns));
}

}  // namespace iree_compiler
}  // namespace mlir
