//===- TilingInterfaceImpl.cpp - Implementation of TilingInterface -------===//
//
// Part of the LLVM Project, 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 "mlir/Dialect/Linalg/Transforms/TilingInterfaceImpl.h"

#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Arith/Utils/Utils.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/Linalg/Utils/Utils.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/Interfaces/TilingInterface.h"
#include <optional>

using namespace mlir;
using namespace mlir::linalg;

//===----------------------------------------------------------------------===//
// Utility methods for implementation of Tiling Interface for Linalg ops
//===----------------------------------------------------------------------===//

/// Return the SSA values that represent the data point accessed using a given
/// `indexingMap` for a given point in the iteration space represented by `ivs`.
static SmallVector<Value> getIndicesForAccess(OpBuilder &b, Location loc,
                                              AffineMap indexingMap,
                                              ValueRange ivs) {
  SmallVector<Value> indices;
  indices.reserve(indexingMap.getNumResults());
  for (auto result : indexingMap.getResults()) {
    AffineMap m = AffineMap::get(indexingMap.getNumDims(),
                                 indexingMap.getNumSymbols(), result);
    Value v = b.create<affine::AffineApplyOp>(loc, m, ivs);
    indices.push_back(v);
  }
  return indices;
}

/// Method to inline the payload of a `linalgOp` given the iteration space
/// point and values for the arguments of the payload.
static LogicalResult inlinePayload(OpBuilder &b, LinalgOp linalgOp,
                                   ValueRange ivs, ValueRange argValues) {
  Block *body = linalgOp.getBlock();
  IRMapping map;
  map.map(body->getArguments(), argValues);
  for (auto &op : body->without_terminator()) {
    if (auto indexOp = dyn_cast<IndexOp>(&op)) {
      map.map(indexOp.getResult(), ivs[indexOp.getDim()]);
      continue;
    }
    b.clone(op, map);
  }

  Operation *terminator = body->getTerminator();
  Location loc = terminator->getLoc();
  for (const auto &operand : llvm::enumerate(terminator->getOperands())) {
    Value toStore = map.lookupOrDefault(operand.value());
    OpOperand *storeInto = linalgOp.getDpsInitOperand(operand.index());
    auto indices = getIndicesForAccess(
        b, loc, linalgOp.getMatchingIndexingMap(storeInto), ivs);
    b.create<memref::StoreOp>(
        loc, toStore, linalgOp.getDpsInitOperand(operand.index())->get(),
        indices);
  }
  return success();
}

//===----------------------------------------------------------------------===//
// External Model for implementing `TilingInterface` for `LinalgOp`s.
//===----------------------------------------------------------------------===//

namespace {
/// External model implementation of TilingInterface for LinalgOps. An external
/// model implementation is used for now till the use of `TilingInterface` is
/// on-par with the current Linalg tiling + fusion patterns. Once it is
/// maybe possible to move this into the op-definition (though there are
/// advantages to leaving it as an external model)
template <typename LinalgOpTy>
struct LinalgOpTilingInterface
    : public TilingInterface::ExternalModel<LinalgOpTilingInterface<LinalgOpTy>,
                                            LinalgOpTy> {
  /// Return the loop iterator type.
  SmallVector<utils::IteratorType> getLoopIteratorTypes(Operation *op) const {
    LinalgOpTy concreteOp = cast<LinalgOpTy>(op);
    return concreteOp.getIteratorTypesArray();
  }

  /// Return the iteration domain range.
  SmallVector<Range> getIterationDomain(Operation *op, OpBuilder &b) const {
    OpBuilder::InsertionGuard g(b);
    b.setInsertionPoint(op);
    Location loc = op->getLoc();
    LinalgOp linalgOp = cast<LinalgOp>(op);
    SmallVector<OpFoldResult> allShapesSizes =
        linalgOp.createFlatListOfOperandDims(b, loc);
    AffineMap map = linalgOp.getShapesToLoopsMap();

    return llvm::to_vector(
        llvm::map_range(map.getResults(), [&](AffineExpr loopExpr) {
          OpFoldResult ofr = affine::makeComposedFoldedAffineApply(
              b, loc, loopExpr, allShapesSizes);
          return Range{b.getIndexAttr(0), ofr, b.getIndexAttr(1)};
        }));
  }

  // Instantiate the tiled implementation of the operation.
  FailureOr<TilingResult>
  getTiledImplementation(Operation *op, OpBuilder &b,
                         ArrayRef<OpFoldResult> offsets,
                         ArrayRef<OpFoldResult> sizes) const {
    // Leave the `sizeBounds` value empty. That is only needed when the `sizes`
    // specified could lead to out of bounds accesses.
    Location loc = op->getLoc();
    LinalgOp linalgOp = cast<LinalgOp>(op);
    SmallVector<Value> valuesToTile = linalgOp->getOperands();
    SmallVector<Value, 4> tiledOperands = makeTiledShapes(
        b, loc, linalgOp, valuesToTile, offsets, sizes, {}, true);

    SmallVector<Type> resultTensorTypes =
        getTensorOutputTypes(linalgOp, tiledOperands);

    Operation *tiledOp = clone(b, linalgOp, resultTensorTypes, tiledOperands);
    offsetIndices(b, cast<LinalgOp>(tiledOp), offsets);

    return TilingResult{{tiledOp}, SmallVector<Value>(tiledOp->getResults())};
  }

  // Return the details of the output tile generated by the tiled
  // implementation.
  LogicalResult
  getResultTilePosition(Operation *op, OpBuilder &b, unsigned resultNumber,
                        ArrayRef<OpFoldResult> offsets,
                        ArrayRef<OpFoldResult> sizes,
                        SmallVector<OpFoldResult> &resultOffsets,
                        SmallVector<OpFoldResult> &resultSizes) const {
    Location loc = op->getLoc();
    LinalgOp linalgOp = cast<LinalgOp>(op);

    AffineExpr d0;
    bindDims(b.getContext(), d0);
    SmallVector<OpFoldResult> subShapeSizes =
        llvm::to_vector(llvm::map_range(sizes, [&](OpFoldResult ofr) {
          return affine::makeComposedFoldedAffineApply(b, loc, d0 - 1, ofr);
        }));

    OpOperand *outOperand = linalgOp.getDpsInitOperand(resultNumber);
    SliceParameters sliceParams = computeSliceParameters(
        b, loc, outOperand->get(), sizes,
        linalgOp.getMatchingIndexingMap(outOperand), offsets,
        /*ubs*/ {}, subShapeSizes, true);
    resultOffsets = sliceParams.offsets;
    resultSizes = sliceParams.sizes;
    return success();
  }

  FailureOr<TilingResult>
  generateResultTileValue(Operation *op, OpBuilder &b, unsigned resultNumber,
                          ArrayRef<OpFoldResult> offsets,
                          ArrayRef<OpFoldResult> sizes) const {
    auto linalgOp = cast<LinalgOp>(op);

    // Check that the indexing map used for the output is a projected
    // permutation. This could be relaxed with a more general approach that can
    // map the offsets and sizes from the result to iteration space tiles
    // (filling in full extent for dimensions not used to access the result).
    AffineMap indexingMap =
        linalgOp.getIndexingMapMatchingResult(op->getResult(resultNumber));
    if (!indexingMap.isProjectedPermutation()) {
      return op->emitOpError(
          "unhandled tiled implementation generation when result is not "
          "accessed using a permuted projection");
    }

    auto numLoops = linalgOp.getNumLoops();
    auto tilingInterfaceOp = cast<TilingInterface>(op);
    SmallVector<OpFoldResult> iterationTileOffsets(numLoops),
        iterationTileSizes(numLoops);
    if (!indexingMap.isPermutation()) {
      SmallVector<Range> iterationDomain =
          tilingInterfaceOp.getIterationDomain(b);
      for (const auto &range : llvm::enumerate(iterationDomain)) {
        iterationTileOffsets[range.index()] = range.value().offset;
        iterationTileSizes[range.index()] = range.value().size;
      }
    }
    for (const auto &resultExpr : llvm::enumerate(indexingMap.getResults())) {
      unsigned dimPosition =
          cast<AffineDimExpr>(resultExpr.value()).getPosition();
      iterationTileOffsets[dimPosition] = offsets[resultExpr.index()];
      iterationTileSizes[dimPosition] = sizes[resultExpr.index()];
    }

    FailureOr<TilingResult> tilingResult =
        tilingInterfaceOp.getTiledImplementation(b, iterationTileOffsets,
                                                 iterationTileSizes);
    if (tilingResult->tiledOps.size() != 1)
      return op->emitOpError("failed to generate tiled implementation");

    return TilingResult{
        tilingResult->tiledOps,
        SmallVector<Value>{tilingResult->tiledValues[resultNumber]}};
  }

  LogicalResult generateScalarImplementation(Operation *op, OpBuilder &builder,
                                             Location loc,
                                             ValueRange ivs) const {
    auto linalgOp = cast<LinalgOp>(op);
    if (!linalgOp.hasPureBufferSemantics())
      return op->emitOpError("expected operation to have buffer semantics");

    SmallVector<Value> indexedValues;
    indexedValues.reserve(linalgOp->getNumOperands());
    Location linalgOpLoc = op->getLoc();
    /// Load the data corresponding to the block arguments that
    /// represent input operands.
    for (OpOperand &operand : linalgOp->getOpOperands()) {
      if (!linalgOp.payloadUsesValueFromOperand(&operand)) {
        indexedValues.push_back(nullptr);
        continue;
      }
      if (linalgOp.isScalar(&operand)) {
        indexedValues.push_back(operand.get());
        continue;
      }
      SmallVector<Value> indices = getIndicesForAccess(
          builder, linalgOpLoc, linalgOp.getMatchingIndexingMap(&operand), ivs);
      Value load =
          builder.create<memref::LoadOp>(linalgOpLoc, operand.get(), indices);
      indexedValues.push_back(load);
    }

    /// Inline the op payload and store the result.
    return inlinePayload(builder, linalgOp, ivs, indexedValues);
  }
};

//===----------------------------------------------------------------------===//
// External Model for implementing `PartialReductionInterface` for `LinalgOp`s.
//===----------------------------------------------------------------------===//

/// External model implementation of PartialReductionInterface for LinalgOps.
template <typename LinalgOpTy>
struct LinalgOpPartialReductionInterface
    : public PartialReductionOpInterface::ExternalModel<
          LinalgOpPartialReductionInterface<LinalgOpTy>, LinalgOpTy> {
  FailureOr<Operation *> generateInitialTensorForPartialReduction(
      Operation *op, OpBuilder &b, Location loc, ArrayRef<OpFoldResult> sizes,
      ArrayRef<int> reductionDims) const {
    auto linalgOp = cast<LinalgOp>(op);
    OpBuilder::InsertionGuard guard(b);

    if (linalgOp.hasPureBufferSemantics())
      return op->emitOpError("expected operation to have tensor semantics");
    // Insert the new parallel dimension based on the index of the reduction
    // loops. This could be controlled by user for more flexibility.

    SmallVector<Operation *, 4> combinerOps;
    if (!matchReduction(linalgOp.getRegionOutputArgs(), 0, combinerOps) ||
        combinerOps.size() != 1)
      return op->emitOpError("Failed to anaysis the reduction operation.");

    Operation *reductionOp = combinerOps[0];
    std::optional<TypedAttr> identity = arith::getNeutralElement(reductionOp);
    if (!identity.has_value())
      return op->emitOpError(
          "Failed to get an identity value for the reduction operation.");

    ArrayRef<int64_t> oldShape =
        linalgOp.getShape(linalgOp.getDpsInitOperand(0));

    // Calculate the new shape, we insert the new dimensions based on the index
    // of the reduction dimensions.
    SmallVector<int64_t> newOutputShape;
    SmallVector<Value> dynamicDims;
    int64_t currReductionDims = 0;
    DenseSet<int> reductionDimsSet(reductionDims.begin(), reductionDims.end());
    for (int64_t idx :
         llvm::seq<int64_t>(0, oldShape.size() + reductionDims.size())) {
      if (reductionDimsSet.contains(idx)) {
        dispatchIndexOpFoldResults(sizes[idx], dynamicDims, newOutputShape);
        currReductionDims++;
        continue;
      }
      int64_t oldIdx = idx - currReductionDims;
      int64_t dim = oldShape[oldIdx];
      newOutputShape.push_back(dim);
      if (ShapedType::isDynamic(dim))
        dynamicDims.push_back(b.create<tensor::DimOp>(
            loc, linalgOp.getDpsInitOperand(0)->get(), oldIdx));
    }
    Value emptyTensor = b.create<tensor::EmptyOp>(
        loc, newOutputShape, linalgOp.getRegionOutputArgs()[0].getType(),
        dynamicDims);
    Value constantOp = b.create<arith::ConstantOp>(loc, *identity);
    auto identityTensor =
        b.create<linalg::FillOp>(loc, constantOp, emptyTensor);
    return identityTensor.getOperation();
  }

  Operation *tileToPartialReduction(Operation *op, OpBuilder &b, Location loc,
                                    ValueRange init,
                                    ArrayRef<OpFoldResult> offsets,
                                    ArrayRef<OpFoldResult> sizes,
                                    ArrayRef<int> reductionDims) const {
    OpBuilder::InsertionGuard guard(b);
    auto linalgOp = cast<LinalgOp>(op);

    AffineMap oldOutputMap =
        linalgOp.getMatchingIndexingMap(linalgOp.getDpsInitOperand(0));
    SmallVector<AffineExpr> outputExpr(oldOutputMap.getNumResults() +
                                       reductionDims.size());

    for (int idx : reductionDims)
      outputExpr[idx] = b.getAffineDimExpr(idx);
    int currExpr = 0;
    for (int idx : llvm::seq<int>(0, outputExpr.size())) {
      if (outputExpr[idx])
        continue;
      outputExpr[idx] = oldOutputMap.getResult(currExpr++);
    }

    // Step 1: Extract a slice of the input operands.
    SmallVector<Value> valuesToTile = linalgOp.getDpsInputs();
    SmallVector<Value, 4> tiledOperands = makeTiledShapes(
        b, loc, linalgOp, valuesToTile, offsets, sizes, {}, true);

    // Step 2: Extract the accumulator operands
    SmallVector<OpFoldResult> strides(offsets.size(), b.getIndexAttr(1));
    SmallVector<OpFoldResult> outOffsets(offsets.size(), b.getIndexAttr(0));
    // TODO: use SubsetExtractOpInterface once it is available.
    Value out = b.create<tensor::ExtractSliceOp>(loc, init[0], outOffsets,
                                                 sizes, strides);

    // Step3. Create a generic op where the reduction dimensions are replaced
    // by a parallel dimension of the size of reduction.
    SmallVector<utils::IteratorType> newIteratorTypes =
        linalgOp.getIteratorTypesArray();
    for (int dim : reductionDims)
      newIteratorTypes[dim] = utils::IteratorType::parallel;
    SmallVector<AffineMap> newMaps = linalgOp.getIndexingMapsArray();
    newMaps.back() = AffineMap::get(newMaps.back().getNumDims(), 0, outputExpr,
                                    linalgOp.getContext());
    auto genericOp =
        b.create<GenericOp>(loc, TypeRange({out.getType()}), tiledOperands,
                            ValueRange({out}), newMaps, newIteratorTypes);
    IRMapping mapping;
    op->getRegion(0).cloneInto(&genericOp.getRegion(),
                               genericOp.getRegion().begin(), mapping);
    return genericOp.getOperation();
  }

  Operation *mergeReductions(Operation *op, OpBuilder &b, Location loc,
                             ValueRange partialReduce,
                             ArrayRef<int> reductionDims) const {
    auto linalgOp = cast<LinalgOp>(op);

    DenseSet<int> reductionDimsSet(reductionDims.begin(), reductionDims.end());

    // Then create a new reduction that only reduce the newly added dimensions
    // from the previous op.
    int64_t intermRank = cast<ShapedType>(partialReduce[0].getType()).getRank();
    AffineMap inputMap = b.getMultiDimIdentityMap(intermRank);
    SmallVector<utils::IteratorType> reductionIteratorTypes;
    SmallVector<AffineExpr> exprs;

    for (int64_t i : llvm::seq<int64_t>(0, intermRank)) {
      if (reductionDimsSet.contains(i)) {
        reductionIteratorTypes.push_back(utils::IteratorType::reduction);
      } else {
        exprs.push_back(b.getAffineDimExpr(i));
        reductionIteratorTypes.push_back(utils::IteratorType::parallel);
      }
    }

    AffineMap outputMap =
        AffineMap::get(intermRank, 0, exprs, op->getContext());
    SmallVector<AffineMap> reductionMaps = {inputMap, outputMap};

    SmallVector<Operation *, 4> combinerOps;
    matchReduction(linalgOp.getRegionOutputArgs(), 0, combinerOps);
    Operation *reductionOp = combinerOps[0];

    auto reduction = b.create<GenericOp>(
        loc, op->getResultTypes(), ValueRange({partialReduce[0]}),
        linalgOp.getDpsInits(), reductionMaps, reductionIteratorTypes,
        [reductionOp](OpBuilder &b, Location loc, ValueRange inputs) {
          Operation *clonedReductionOp = b.clone(*reductionOp);
          clonedReductionOp->setOperand(0, inputs[0]);
          clonedReductionOp->setOperand(1, inputs[1]);
          b.create<linalg::YieldOp>(loc, clonedReductionOp->getResult(0));
        });
    return reduction.getOperation();
  }
};

} // namespace

template <typename OpType>
static void registerOne(MLIRContext *ctx) {
  OpType::template attachInterface<LinalgOpTilingInterface<OpType>>(*ctx);
  OpType::template attachInterface<LinalgOpPartialReductionInterface<OpType>>(
      *ctx);
}

/// Variadic helper function.
template <typename... OpTypes>
static void registerAll(MLIRContext *ctx) {
  (registerOne<OpTypes>(ctx), ...);
}

#define GET_OP_LIST

void mlir::linalg::registerTilingInterfaceExternalModels(
    DialectRegistry &registry) {
  registry.addExtension(+[](MLIRContext *ctx, linalg::LinalgDialect *dialect) {
    registerOne<linalg::GenericOp>(ctx);
    registerAll<
#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
        >(ctx);
  });
}
