//===- VectorToAMX.cpp - Convert vector to X86 dialect AMX ops --*- C++ -*-===//
//
// 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/Conversion/VectorToAMX/VectorToAMX.h"

#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/X86/X86Dialect.h"
#include "mlir/IR/Builders.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/DebugLog.h"

#include <numeric>

namespace mlir {
#define GEN_PASS_DEF_CONVERTVECTORTOAMX
#include "mlir/Conversion/Passes.h.inc"
} // namespace mlir

using namespace mlir;

#define DEBUG_TYPE "vector-to-amx"

namespace {

/// Return true if vector shape is compatible with AMX tiles.
/// The validation accounts for VNNI packing.
static bool verifyAmxShape(VectorType vec) {
  // Check overall shape:
  //   - 2D for plain layout input or output
  //   - 3D for VNNI packed input
  if (vec.getRank() != 2 && vec.getRank() != 3)
    return false;

  ArrayRef<int64_t> shape = vec.getShape();
  int64_t rows = shape[0];
  int64_t cols = shape[1];
  unsigned elemBitWidth = vec.getElementType().getIntOrFloatBitWidth();

  // 3D shape indicates VNNI packed layout.
  if (vec.getRank() == 3) {
    int64_t vnniFactor = 32 / elemBitWidth;
    if (shape.back() != vnniFactor) {
      LDBG() << "invalid VNNI packing factor";
      return false;
    }
    cols *= vnniFactor;
  }

  // AMX tile supports up to 16 rows of 64 bytes each.
  constexpr unsigned maxRows = 16;
  constexpr unsigned maxBitsPerRow = 64 * 8;
  return rows <= maxRows && (cols * elemBitWidth) <= maxBitsPerRow;
}

/// Check if contraction operands are in AMX-compatible packed VNNI layout.
static LogicalResult isAmxVnniLayout(PatternRewriter &rewriter,
                                     vector::ContractionOp contractOp) {
  VectorType accType = dyn_cast<VectorType>(contractOp.getAcc().getType());
  if (!accType || accType.getRank() != 2)
    return rewriter.notifyMatchFailure(contractOp, "Expects acc 2D vector");

  // Expect 3D inputs for VNNI packed data.
  VectorType lhsType = contractOp.getLhs().getType();
  VectorType rhsType = contractOp.getRhs().getType();
  if (lhsType.getRank() != 3 || rhsType.getRank() != 3)
    return rewriter.notifyMatchFailure(contractOp,
                                       "Expects lhs and rhs 3D vectors");

  // Check if shapes are compatible with AMX tile.
  if (!verifyAmxShape(lhsType) || !verifyAmxShape(rhsType) ||
      !verifyAmxShape(accType))
    return rewriter.notifyMatchFailure(contractOp, "Invalid operand shape");

  // Validate affine maps.
  //
  // Iterators can be ordered arbitrarily. Indexing map positions are based on
  // operands' target shapes.
  // The matrix layouts must match the following:
  //   - matrix A - [M]x[K/vnniFactor]x[vnniFactor]
  //   - matrix B - [K/vnniFactor]x[N]x[vnniFactor]
  //   - matrix C - [M]x[N]
  SmallVector<AffineMap, 4> indexingMaps = contractOp.getIndexingMapsArray();
  AffineMap mapA = indexingMaps[0];
  AffineMap mapB = indexingMaps[1];
  if (mapA.getNumInputs() != 4 || mapA.getNumResults() != 3 ||
      mapB.getNumResults() != 3)
    return rewriter.notifyMatchFailure(contractOp,
                                       "Invalid input indexing maps");
  FailureOr<linalg::ContractionDimensions> dims =
      linalg::inferContractionDims(indexingMaps);
  if (failed(dims))
    return rewriter.notifyMatchFailure(contractOp,
                                       "Failed to infer contraction dims");
  // Two reduction dimensions are expected:
  //   - one for the K dimension
  //   - one for the VNNI factor
  if (dims->k.size() != 2)
    return rewriter.notifyMatchFailure(contractOp,
                                       "Expected two reduction dims");
  assert(dims->m.size() == 1 && dims->n.size() == 1 &&
         "Invalid parallel contraction dims");

  SmallVector<vector::IteratorType> iteratorTypes =
      contractOp.getIteratorTypesArray();
  // Check VNNI dim maps - the innermost dim for A and B inputs.
  auto vnniDimA = dyn_cast<AffineDimExpr>(mapA.getResult(2));
  auto vnniDimB = dyn_cast<AffineDimExpr>(mapB.getResult(2));
  if (!vnniDimA || !vnniDimB || vnniDimA != vnniDimB ||
      iteratorTypes[vnniDimA.getPosition()] != vector::IteratorType::reduction)
    return rewriter.notifyMatchFailure(contractOp, "Invalid VNNI dim map");
  // Check K dim maps - non-transposed row-major layout.
  auto redDimA = dyn_cast<AffineDimExpr>(mapA.getResult(1));
  auto redDimB = dyn_cast<AffineDimExpr>(mapB.getResult(0));
  if (!redDimA || !redDimB || redDimA != redDimB ||
      iteratorTypes[redDimA.getPosition()] != vector::IteratorType::reduction)
    return rewriter.notifyMatchFailure(contractOp, "Invalid K dim map");
  // Check M and N dim maps - map to non-transposed output.
  AffineMap mapC = indexingMaps[2];
  auto mDimC = dyn_cast<AffineDimExpr>(mapC.getResult(0));
  auto nDimC = dyn_cast<AffineDimExpr>(mapC.getResult(1));
  if (!mDimC || !nDimC)
    return rewriter.notifyMatchFailure(contractOp, "Invalid acc maps");
  auto parallelDimA = dyn_cast<AffineDimExpr>(mapA.getResult(0));
  if (!parallelDimA ||
      iteratorTypes[parallelDimA.getPosition()] !=
          vector::IteratorType::parallel ||
      parallelDimA != mDimC)
    return rewriter.notifyMatchFailure(contractOp, "Invalid M dim map");
  auto parallelDimB = dyn_cast<AffineDimExpr>(mapB.getResult(1));
  if (!parallelDimB ||
      iteratorTypes[parallelDimB.getPosition()] !=
          vector::IteratorType::parallel ||
      parallelDimB != nDimC)
    return rewriter.notifyMatchFailure(contractOp, "Invalid N dim map");

  return success();
}

/// Validate contraction operands for AMX lowering.
static LogicalResult validateOperands(PatternRewriter &rewriter,
                                      vector::ContractionOp contractOp) {
  VectorType accType = dyn_cast<VectorType>(contractOp.getAcc().getType());
  if (!accType)
    return rewriter.notifyMatchFailure(contractOp, "Expects vector acc");

  // Check if operand types are compatible with AMX compute ops.
  bool validElemTypes = false;
  Type lhsElemType = contractOp.getLhs().getType().getElementType();
  Type rhsElemType = contractOp.getRhs().getType().getElementType();
  Type accElemType = accType.getElementType();
  if (accElemType.isInteger(32)) {
    validElemTypes = lhsElemType.isInteger(8) && rhsElemType.isInteger(8);
  } else if (accElemType.isF32()) {
    validElemTypes = (lhsElemType.isF16() && rhsElemType.isF16()) ||
                     (lhsElemType.isBF16() && rhsElemType.isBF16());
  }
  if (!validElemTypes)
    return rewriter.notifyMatchFailure(contractOp,
                                       "Invalid combination of operand types");

  if (failed(isAmxVnniLayout(rewriter, contractOp)))
    return failure();

  return success();
}

/// Collapse the two innermost dimensions together.
static TypedValue<MemRefType> collapseLastDim(PatternRewriter &rewriter,
                                              TypedValue<MemRefType> memref) {
  int64_t rank = memref.getType().getRank();
  SmallVector<ReassociationIndices> reassocIndices;
  for (auto i : llvm::seq<int64_t>(0, rank - 2))
    reassocIndices.push_back({i});
  reassocIndices.push_back({rank - 2, rank - 1});
  return memref::CollapseShapeOp::create(rewriter, memref.getLoc(), memref,
                                         reassocIndices);
}

/// Attempt to create an AMX tile load/store operation equivalent to the given
/// vector transfer `xfer` op.
/// This approach allows to skip longer route through registers and a temporary
/// buffer otherwise required to move data to/from an AMX tile.
static Operation *
loadStoreFromTransfer(PatternRewriter &rewriter,
                      VectorTransferOpInterface xferOp, bool isPacked,
                      TypedValue<x86::amx::TileType> tileToStore = nullptr) {
  if (!xferOp || !isa<vector::TransferReadOp, vector::TransferWriteOp>(xferOp))
    return nullptr;
  if (xferOp.hasOutOfBoundsDim() ||
      !xferOp.getPermutationMap().isMinorIdentity())
    return nullptr;

  // Extra checks in case of a write op.
  // Stores must not be packed.
  if (isa<vector::TransferWriteOp>(xferOp) &&
      (!tileToStore || isPacked ||
       tileToStore.getType().getShape() != xferOp.getVectorType().getShape()))
    return nullptr;

  // Check for a memref source buffer.
  // AMX data transfer requires at least 2D shape to correctly
  // infer stride between rows.
  Value base = xferOp.getBase();
  auto memTy = dyn_cast<MemRefType>(base.getType());
  int64_t memRank = memTy.getRank();
  if (!memTy || memRank < 2)
    return nullptr;

  // Check that the source buffer has enough contiguous elements to load whole
  // AMX tile row.
  //
  // To ensure correctness, the validation is conservative and expects the
  // buffer's innermost dimensions to be statically known, equal to or larger
  // than the vector row length, and equal to the VNNI dimension if applicable.
  //
  // This check could be relaxed to accept more arbitrarily shaped buffers as
  // long as there are enough contiguous elements to load a whole row.
  if (!memTy.areTrailingDimsContiguous(isPacked ? 2 : 1))
    return nullptr;
  VectorType vecTy = xferOp.getVectorType();
  ArrayRef<int64_t> vecShape = vecTy.getShape();
  ArrayRef<int64_t> memShape = memTy.getShape();
  if (memShape.back() == ShapedType::kDynamic ||
      memShape.back() < vecShape.back())
    return nullptr;
  if (isPacked &&
      (memShape.back() != vecShape.back() ||
       memShape[memShape.size() - 2] == ShapedType::kDynamic ||
       memShape[memShape.size() - 2] < vecShape[vecShape.size() - 2]))
    return nullptr;

  // Load values directly from the buffer to an AMX tile.
  PatternRewriter::InsertionGuard g(rewriter);
  rewriter.setInsertionPoint(xferOp);
  Location loc = xferOp.getLoc();

  // Create a subview of the source buffer based on the transfer op to resolve
  // offsets.
  SmallVector<OpFoldResult> strides(memRank, rewriter.getIndexAttr(1));
  int64_t vecRank = vecTy.getRank();
  assert(memRank >= vecRank &&
         "Expects buffer to be the same or greater rank than vector");
  SmallVector<int64_t> shape(memRank - vecRank, 1);
  shape.append(vecShape.begin(), vecShape.end());
  TypedValue<MemRefType> src =
      memref::SubViewOp::create(
          rewriter, loc, base, getAsOpFoldResult(xferOp.getIndices()),
          getAsOpFoldResult(rewriter.getI64ArrayAttr(shape)), strides)
          .getResult();

  // Collapse the VNNI dimension in case of packing.
  if (isPacked)
    src = collapseLastDim(rewriter, src);
  int64_t rows = vecShape[0];
  int64_t cols = llvm::product_of(vecShape.drop_front());
  auto tileType = x86::amx::TileType::get({rows, cols}, vecTy.getElementType());

  Value zeroIndex = rewriter.createOrFold<arith::ConstantIndexOp>(loc, 0);
  SmallVector<Value> tileIndicides(src.getType().getRank(), zeroIndex);

  Operation *amxTileOp = nullptr;
  if (isa<vector::TransferReadOp>(xferOp)) {
    amxTileOp = x86::amx::TileLoadOp::create(rewriter, loc, tileType, src,
                                             tileIndicides);
  } else if (isa<vector::TransferWriteOp>(xferOp)) {
    amxTileOp = x86::amx::TileStoreOp::create(rewriter, loc, src, tileIndicides,
                                              tileToStore);
  } else {
    llvm_unreachable("unsupported vector transfer op");
  }

  return amxTileOp;
}

/// Attempt to create an AMX tile load operation equivalent to the given
/// vector transfer `readOp`.
/// Returns loaded AMX tile if successful.
static FailureOr<TypedValue<x86::amx::TileType>>
loadFromTransfer(PatternRewriter &rewriter, vector::TransferReadOp readOp,
                 bool isPacked) {
  x86::amx::TileLoadOp loadOp = dyn_cast_if_present<x86::amx::TileLoadOp>(
      loadStoreFromTransfer(rewriter, readOp, isPacked));
  if (!loadOp)
    return failure();
  return loadOp.getRes();
}

/// Attempt to create an AMX tile store operation equivalent to the given
/// vector transfer `writeOp`.
static LogicalResult
storeFromTransfer(PatternRewriter &rewriter, vector::TransferWriteOp writeOp,
                  TypedValue<x86::amx::TileType> tileToStore) {
  return success(loadStoreFromTransfer(rewriter, writeOp, /*isPacked=*/false,
                                       tileToStore));
}

/// Load vector values to an AMX tile.
static TypedValue<x86::amx::TileType> loadTile(PatternRewriter &rewriter,
                                               TypedValue<VectorType> vec) {
  Location loc = vec.getLoc();

  VectorType vecTy = vec.getType();
  bool isPacked = vecTy.getRank() == 3;

  // Try to load tile directly from vector producer's buffer.
  auto readOp = vec.getDefiningOp<vector::TransferReadOp>();
  FailureOr<TypedValue<x86::amx::TileType>> tile =
      loadFromTransfer(rewriter, readOp, isPacked);
  if (succeeded(tile))
    return *tile;

  // Transfer the vector to a tile through an intermediate buffer.
  Value buf = memref::AllocaOp::create(
      rewriter, loc, MemRefType::get(vecTy.getShape(), vecTy.getElementType()));
  Value zeroIndex = rewriter.createOrFold<arith::ConstantIndexOp>(loc, 0);
  SmallVector<Value> indices(vecTy.getRank(), zeroIndex);
  vector::TransferWriteOp::create(rewriter, loc, vec, buf, indices);

  // Collapse the VNNI dimension in case of packing.
  if (isPacked)
    buf = collapseLastDim(rewriter, cast<TypedValue<MemRefType>>(buf));

  ArrayRef<int64_t> shape = vecTy.getShape();
  int64_t rows = shape[0];
  int64_t cols = llvm::product_of(shape.drop_front());
  auto tileType = x86::amx::TileType::get({rows, cols}, vecTy.getElementType());

  return x86::amx::TileLoadOp::create(rewriter, loc, tileType, buf,
                                      {zeroIndex, zeroIndex});
}

/// Store an AMX tile in a vector.
static TypedValue<VectorType> storeTile(PatternRewriter &rewriter,
                                        TypedValue<x86::amx::TileType> tile) {
  Location loc = tile.getLoc();

  // Transfer the tile to a vector through an intermediate buffer.
  x86::amx::TileType tileTy = tile.getType();
  Value buf = memref::AllocaOp::create(
      rewriter, loc,
      MemRefType::get(tileTy.getShape(), tileTy.getElementType()));
  Value zeroIndex = rewriter.createOrFold<arith::ConstantIndexOp>(loc, 0);
  Repeated<Value> indices(2, zeroIndex);
  x86::amx::TileStoreOp::create(rewriter, loc, buf, indices, tile);

  auto vecTy = VectorType::get(tileTy.getShape(), tileTy.getElementType());
  return vector::TransferReadOp::create(rewriter, loc, vecTy, buf, indices, {});
}

struct ContractionToAMX : public OpRewritePattern<vector::ContractionOp> {
  using Base::Base;

  LogicalResult matchAndRewrite(vector::ContractionOp contractOp,
                                PatternRewriter &rewriter) const override {
    Location loc = contractOp.getLoc();

    if (contractOp.getKind() != vector::CombiningKind::ADD)
      return rewriter.notifyMatchFailure(contractOp,
                                         "Expects add combining kind");
    if (failed(validateOperands(rewriter, contractOp)))
      return failure();

    TypedValue<x86::amx::TileType> lhsTile =
        loadTile(rewriter, contractOp.getLhs());
    TypedValue<x86::amx::TileType> rhsTile =
        loadTile(rewriter, contractOp.getRhs());
    auto acc = dyn_cast<TypedValue<VectorType>>(contractOp.getAcc());
    assert(acc && "Invalid accumulator type");
    TypedValue<x86::amx::TileType> accTile = loadTile(rewriter, acc);

    TypedValue<x86::amx::TileType> tileMul;
    if (acc.getType().getElementType().isFloat()) {
      tileMul = x86::amx::TileMulFOp::create(rewriter, loc, accTile.getType(),
                                             lhsTile, rhsTile, accTile);
    } else {
      tileMul = x86::amx::TileMulIOp::create(rewriter, loc, accTile.getType(),
                                             lhsTile, rhsTile, accTile);
    }

    // If the contraction result is only written back to memory, try to replace
    // the vector op with an AMX store directly.
    Value res = contractOp.getResult();
    if (res.hasOneUse()) {
      auto writeOp = dyn_cast<vector::TransferWriteOp>(*res.getUsers().begin());
      LogicalResult storeRes = storeFromTransfer(rewriter, writeOp, tileMul);
      if (succeeded(storeRes)) {
        rewriter.eraseOp(writeOp);
        rewriter.eraseOp(contractOp);
        return success();
      }
    }

    // Load the result back into a vector.
    Value newResult = storeTile(rewriter, tileMul);
    rewriter.replaceOp(contractOp, newResult);

    return success();
  }
};

struct ConvertVectorToAMXPass
    : public impl::ConvertVectorToAMXBase<ConvertVectorToAMXPass> {
  void runOnOperation() override {
    MLIRContext &ctx = getContext();
    RewritePatternSet patterns(&ctx);
    populateVectorToAMXConversionPatterns(patterns);
    if (failed(applyPatternsGreedily(getOperation(), std::move(patterns))))
      return signalPassFailure();
  }
};

} // namespace

void mlir::populateVectorToAMXConversionPatterns(RewritePatternSet &patterns) {
  patterns.add<ContractionToAMX>(patterns.getContext());
}
