//===- VectorToXeGPU.cpp - Convert vector to XeGPU dialect ------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file implements lowering of vector operations to XeGPU dialect ops.
//
//===----------------------------------------------------------------------===//

#include "mlir/Conversion/VectorToXeGPU/VectorToXeGPU.h"
#include "mlir/Conversion/VectorToGPU/VectorToGPU.h"

#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/UB/IR/UBOps.h"
#include "mlir/Dialect/Utils/IndexingUtils.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/XeGPU/IR/XeGPU.h"
#include "mlir/Dialect/XeGPU/Utils/XeGPUUtils.h"
#include "mlir/Dialect/XeGPU/uArch/uArchBase.h"
#include "mlir/Dialect/XeGPU/uArch/uArchCommon.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "llvm/ADT/TypeSwitch.h"

#include <algorithm>
#include <optional>

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

using namespace mlir;

namespace {

// Return true if value represents a zero constant.
static bool isZeroConstant(Value val) {
  auto constant = val.getDefiningOp<arith::ConstantOp>();
  if (!constant)
    return false;

  return TypeSwitch<Attribute, bool>(constant.getValue())
      .Case([](FloatAttr floatAttr) { return floatAttr.getValue().isZero(); })
      .Case([](IntegerAttr intAttr) { return intAttr.getValue().isZero(); })
      .Default(false);
}

// Return true if the transfer padding value is compatible with the implicit
// padding of an nd block load. LoadNdOp fills out-of-bounds elements with zero,
// so a zero constant matches its semantics exactly. A poison padding means the
// out-of-bounds elements are "don't care", so any implicit padding (including
// zero) is also acceptable.
static bool isZeroOrPoisonPadding(Value val) {
  return isZeroConstant(val) || val.getDefiningOp<ub::PoisonOp>();
}

// Return true if the permutation map keeps every dimension in place except the
// innermost two, which are swapped, e.g.:
//   (d0, d1) -> (d1, d0)
//   (d0, d1, d2) -> (d2, d1)
//   (d0, d1, d2, d3) -> (d0, d1, d3, d2)
// This is the only non-identity permutation an nd block load can realize (by
// loading the untransposed block and applying a trailing vector.transpose).
static bool isInnermostTwoDimsTransposed(AffineMap map) {
  unsigned numResults = map.getNumResults();
  if (numResults < 2)
    return false;
  MLIRContext *ctx = map.getContext();
  unsigned numInputs = map.getNumInputs();
  // All but the innermost two results must match the minor-identity map.
  for (unsigned i = 0; i + 2 < numResults; ++i)
    if (map.getResult(i) != getAffineDimExpr(numInputs - numResults + i, ctx))
      return false;
  // The innermost two results must be the last two input dims, swapped.
  return map.getResult(numResults - 2) ==
             getAffineDimExpr(numInputs - 1, ctx) &&
         map.getResult(numResults - 1) == getAffineDimExpr(numInputs - 2, ctx);
}

// Return true if `uArch` can transfer a `shape`-shaped tile of `elemTy`
// elements with the subgroup 2D block instruction `instKind`.
//
// A 2D block instruction accesses the two innermost dimensions of the tile;
// leading dimensions are unrolled into a sequence of 2D accesses. The
// innermost 2D tile does not have to match a hardware block exactly, because
// the later XeGPU passes (layout propagation and blocking) split it into
// hardware-sized blocks - but that split only exists when each of the two
// innermost extents is a multiple of a supported block extent. Transfers
// without such a split cannot be expressed with block instructions at all and
// must use a different lowering.
static bool isSupportedBlockShape(const xegpu::uArch::uArch *uArch,
                                  xegpu::uArch::InstructionKind instKind,
                                  ArrayRef<int64_t> shape, Type elemTy,
                                  bool hasTranspose = false) {
  if (shape.size() < 2)
    return false;
  if (!uArch || !uArch->isSupportedInstruction(instKind))
    return false;

  const auto *blockInst = dyn_cast<xegpu::uArch::BlockIOInstructionInterface>(
      uArch->getInstruction(instKind));
  if (!blockInst)
    return false;

  int width = static_cast<int>(shape.back());
  int height = static_cast<int>(shape[shape.size() - 2]);

  // A tile is accessible when both of its extents are multiples of a supported
  // block extent, so that the later XeGPU passes can split it into hardware
  // blocks. A missing entry means this variant does not support the element
  // type.
  auto fitsBlockShapes = [&](bool hasTransform) {
    std::optional<xegpu::uArch::BlockIOInstructionInterface::BlockShapes>
        blockShapes = blockInst->getBlockWidthHeightCount(elemTy, hasTransform,
                                                          hasTranspose);
    if (!blockShapes)
      return false;
    auto [widths, heights, counts] = *blockShapes;
    return xegpu::getLargestDivisor(width, widths) != -1 &&
           xegpu::getLargestDivisor(height, heights) != -1;
  };

  // Whether a tile is eventually loaded with the transformed (VNNI) variant is
  // only decided later, when layout propagation knows whether it feeds the B
  // operand of a matrix operation, so accept a tile that either variant can
  // access.
  return fitsBlockShapes(/*hasTransform=*/false) ||
         fitsBlockShapes(/*hasTransform=*/true);
}

static LogicalResult transferPreconditions(PatternRewriter &rewriter,
                                           VectorTransferOpInterface xferOp) {
  if (xferOp.getMask())
    return rewriter.notifyMatchFailure(xferOp,
                                       "Masked transfer is not supported");

  auto srcTy = dyn_cast<MemRefType>(xferOp.getShapedType());
  if (!srcTy)
    return rewriter.notifyMatchFailure(xferOp, "Expects memref source");

  // Validate further transfer op semantics.
  SmallVector<int64_t> strides;
  int64_t offset;
  if (failed(srcTy.getStridesAndOffset(strides, offset)))
    return rewriter.notifyMatchFailure(xferOp,
                                       "The memref strides cannot be inferred");
  if (strides.empty())
    return rewriter.notifyMatchFailure(xferOp, "0D memref is not supported");
  if (strides.back() != 1)
    return rewriter.notifyMatchFailure(
        xferOp, "Buffer must be contiguous in the innermost dimension");

  VectorType vecTy = xferOp.getVectorType();
  unsigned vecRank = vecTy.getRank();
  if (vecRank == 0)
    return rewriter.notifyMatchFailure(xferOp, "0D vectors are not supported");

  AffineMap map = xferOp.getPermutationMap();
  if (!map.isProjectedPermutation(/*allowZeroInResults=*/false))
    return rewriter.notifyMatchFailure(xferOp, "Unsupported permutation map");
  unsigned numInputDims = map.getNumInputs();
  for (AffineExpr expr : map.getResults().take_back(vecRank)) {
    auto dim = dyn_cast<AffineDimExpr>(expr);
    if (dim.getPosition() < (numInputDims - vecRank))
      return rewriter.notifyMatchFailure(
          xferOp, "Only the innermost dimensions can be accessed");
  }

  return success();
}

// Adjusts the strides of a memref according to a given permutation map for
// vector operations.
//
// This function updates the innermost strides in the `strides` array to
// reflect the permutation specified by `permMap`. The permutation is computed
// using the inverse and broadcasting-aware version of the permutation map,
// and is applied to the relevant strides. This ensures that memory accesses
// are consistent with the logical permutation of vector elements.
//
// Example:
//   Suppose we have a memref of rank 4 with strides `[s0, s1, s2, s3]`.
//   If the permutation map swaps the last two dimensions (e.g., [0, 1] -> [1,
//   0]), then after calling this function, the last two strides will be
//   swapped:
//     Original strides: [s0, s1, s2, s3]
//     After permutation: [s0, s1, s3, s2]
//
static void adjustStridesForPermutation(AffineMap permMap,
                                        SmallVectorImpl<Value> &strides) {

  AffineMap invMap = inverseAndBroadcastProjectedPermutation(permMap);
  SmallVector<unsigned> perms;
  invMap.isPermutationOfMinorIdentityWithBroadcasting(perms);
  SmallVector<int64_t> perms64(perms.begin(), perms.end());
  strides = applyPermutation(strides, perms64);
}

// Computes memory strides and a memref offset for vector transfer operations,
// handling both static and dynamic memrefs while applying permutation
// transformations for XeGPU lowering.
template <
    typename OpType,
    typename = std::enable_if_t<llvm::is_one_of<
        std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
        vector::GatherOp, vector::ScatterOp>::value>>
static std::pair<SmallVector<Value>, Value>
computeMemrefMeta(OpType xferOp, PatternRewriter &rewriter) {
  SmallVector<Value> strides;
  Value baseMemref = xferOp.getBase();
  MemRefType memrefType = dyn_cast<MemRefType>(baseMemref.getType());

  Location loc = xferOp.getLoc();
  Value offsetVal = nullptr;
  if (memrefType.hasStaticShape()) {
    int64_t offset;
    SmallVector<int64_t> intStrides;
    if (failed(memrefType.getStridesAndOffset(intStrides, offset)))
      return {{}, offsetVal};
    bool hasDynamicStrides = llvm::any_of(intStrides, [](int64_t strideVal) {
      return ShapedType::isDynamic(strideVal);
    });

    if (!hasDynamicStrides)
      for (int64_t s : intStrides)
        strides.push_back(arith::ConstantIndexOp::create(rewriter, loc, s));

    if (!ShapedType::isDynamic(offset))
      offsetVal = arith::ConstantIndexOp::create(rewriter, loc, offset);
  }

  if (strides.empty() || !offsetVal) {
    // For dynamic shape memref, use memref.extract_strided_metadata to get
    // stride values
    unsigned rank = memrefType.getRank();
    Type indexType = rewriter.getIndexType();

    // Result types: [base_memref, offset, stride0, stride1, ..., strideN-1,
    // size0, size1, ..., sizeN-1]
    SmallVector<Type> resultTypes;
    resultTypes.push_back(MemRefType::get(
        {}, memrefType.getElementType())); // base memref (unranked)
    resultTypes.push_back(indexType);      // offset

    for (unsigned i = 0; i < rank; ++i)
      resultTypes.push_back(indexType); // strides

    for (unsigned i = 0; i < rank; ++i)
      resultTypes.push_back(indexType); // sizes

    auto meta = memref::ExtractStridedMetadataOp::create(
        rewriter, loc, resultTypes, baseMemref);

    if (strides.empty())
      strides.append(meta.getStrides().begin(), meta.getStrides().end());

    if (!offsetVal)
      offsetVal = meta.getOffset();
  }

  // Strides are returned in original memref order; permutation is applied in
  // computeOffsets only where offsets are indexed in vector order.
  return {strides, offsetVal};
}

// Adds the transfer's indices to `baseOffset`, the memref's own element offset:
// the element at `indices` sits at `baseOffset + sum(indices[d] * strides[d])`.
static Value computeBaseOffset(VectorTransferOpInterface xferOp,
                               PatternRewriter &rewriter,
                               ArrayRef<Value> strides, Value baseOffset) {
  Location loc = xferOp.getLoc();
  for (auto [index, stride] : llvm::zip_equal(xferOp.getIndices(), strides)) {
    Value contrib = arith::MulIOp::create(rewriter, loc, index, stride);
    baseOffset = arith::AddIOp::create(rewriter, loc, baseOffset, contrib);
  }
  return baseOffset;
}

// This function compute the vectors of localOffsets for scattered load/stores.
// It is used in the lowering of vector.transfer_read/write to
// load_gather/store_scatter Example:
//   %0 = vector.transfer_read %expand_shape[%block_id_y, %c0, %c0, %c0, %c0],
//               %cst {in_bounds = [true, true, true, true]}>} :
//               memref<8x4x2x6x32xbf16>, vector<4x2x6x32xbf16>
//
//   %6 = vector.step: vector<4xindex>
//   %7 = vector.step: vector<2xindex>
//   %8 = vector.step: vector<6xindex>
//   %9 = vector.step: vector<32xindex>
//   %10 = arith.mul %6, 384
//   %11 = arith.mul %7, 192
//   %12 = arith.mul %8, 32
//   %13 = arith.mul %9, 1
//   %14 = vector.shape_cast %10: vector<4xindex> -> vector<4x1x1x1xbf16>
//   %15 = vector.shape_cast %11: vector<2xindex> -> vector<1x2x1x1xbf16>
//   %16 = vector.shape_cast %12: vector<6xindex> -> vector<1x1x6x1xbf16>
//   %17 = vector.shape_cast %13: vector<32xindex> -> vector<1x1x1x32xbf16>
//   %18 = vector.broadcast %14: vector<4x1x1x1xbf16> -> vector<4x2x6x32xindex>
//   %19 = vector.broadcast %15: vector<1x2x1x1xbf16> -> vector<4x2x6x32xindex>
//   %20 = vector.broadcast %16: vector<1x1x6x1xbf16> -> vector<4x2x6x32xindex>
//   %21 = vector.broadcast %17: vector<1x1x1x32xbf16> -> vector<4x2x6x32xindex>
//   %22 = arith.add %18, %19
//   %23 = arith.add %20, %21
//   %local_offsets = arith.add %22, %23
//   %orig_offset = %block_id_y * 4x2x6x32 // consider using affine map
//   %offsets =  memref_offset + orig_offset + local_offsets
static Value computeOffsets(VectorTransferOpInterface xferOp,
                            PatternRewriter &rewriter, ArrayRef<Value> strides,
                            Value baseOffset) {
  Location loc = xferOp.getLoc();
  VectorType vectorType = xferOp.getVectorType();
  ArrayRef<int64_t> vectorShape = vectorType.getShape();

  // Create vector.step operations for each dimension
  SmallVector<Value> stepVectors;
  llvm::map_to_vector(vectorShape, [&](int64_t dim) {
    auto stepType = VectorType::get({dim}, rewriter.getIndexType());
    auto stepOp = vector::StepOp::create(rewriter, loc, stepType);
    stepVectors.push_back(stepOp);
    return stepOp;
  });

  // Local offsets are indexed in vector order, so permute strides; the base
  // offset below uses the original memref-order strides.
  SmallVector<Value> permutedStrides(strides.begin(), strides.end());
  adjustStridesForPermutation(xferOp.getPermutationMap(), permutedStrides);

  // Multiply step vectors by corresponding strides
  size_t memrefRank = permutedStrides.size();
  size_t vectorRank = vectorShape.size();
  SmallVector<Value> strideMultiplied;
  for (size_t i = 0; i < vectorRank; ++i) {
    size_t memrefDim = memrefRank - vectorRank + i;
    Value strideValue = permutedStrides[memrefDim];
    auto mulType = dyn_cast<VectorType>(stepVectors[i].getType());
    auto bcastOp =
        vector::BroadcastOp::create(rewriter, loc, mulType, strideValue);
    auto mulOp = arith::MulIOp::create(rewriter, loc, stepVectors[i], bcastOp);
    strideMultiplied.push_back(mulOp);
  }

  // Shape cast each multiplied vector to add singleton dimensions
  SmallVector<Value> shapeCasted;
  for (size_t i = 0; i < vectorRank; ++i) {
    SmallVector<int64_t> newShape(vectorRank, 1);
    newShape[i] = vectorShape[i];
    auto newType = VectorType::get(newShape, rewriter.getIndexType());
    auto castOp = vector::ShapeCastOp::create(rewriter, loc, newType,
                                              strideMultiplied[i]);
    shapeCasted.push_back(castOp);
  }

  // Broadcast each shape-casted vector to full vector shape
  SmallVector<Value> broadcasted;
  auto fullIndexVectorType =
      VectorType::get(vectorShape, rewriter.getIndexType());
  for (Value shapeCastVal : shapeCasted) {
    auto broadcastOp = vector::BroadcastOp::create(
        rewriter, loc, fullIndexVectorType, shapeCastVal);
    broadcasted.push_back(broadcastOp);
  }

  // Add all broadcasted vectors together to compute local offsets
  Value localOffsets = broadcasted[0];
  for (size_t i = 1; i < broadcasted.size(); ++i)
    localOffsets =
        arith::AddIOp::create(rewriter, loc, localOffsets, broadcasted[i]);

  // Broadcast base offset to match vector shape
  baseOffset = computeBaseOffset(xferOp, rewriter, strides, baseOffset);
  Value bcastBase = vector::BroadcastOp::create(
      rewriter, loc, fullIndexVectorType, baseOffset);
  localOffsets = arith::AddIOp::create(rewriter, loc, bcastBase, localOffsets);
  return localOffsets;
}

// Returns the size of memref dimension `dim` as a value.
static Value getMemrefDimSize(VectorTransferOpInterface xferOp, unsigned dim,
                              PatternRewriter &rewriter) {
  Location loc = xferOp.getLoc();
  auto memrefTy = cast<MemRefType>(xferOp.getShapedType());
  if (memrefTy.isDynamicDim(dim))
    return memref::DimOp::create(rewriter, loc, xferOp.getBase(), dim)
        .getResult();
  return arith::ConstantIndexOp::create(rewriter, loc, memrefTy.getDimSize(dim))
      .getResult();
}

// Builds the mask a scattered access needs to stay within the source bounds.
//
// The element at vector position `i` along vector dimension `v` accesses memref
// dimension `d` (the one `v` maps to) at `indices[d] + i`, so it is in bounds
// iff `i < dim(d) - indices[d]`. Dimensions the transfer declares in-bounds are
// skipped; non-vector dimensions are always in bounds by the op's contract. The
// per-dimension masks are spread over the full vector shape and combined, the
// same way `computeOffsets` spreads the per-dimension offsets.
//
// Example, for a `vector<8xf32>` read of a `memref<?xf32>` at `%off`:
//   %dim = memref.dim %src, %c0
//   %limit = arith.subi %dim, %off
//   %step = vector.step : vector<8xindex>
//   %bcast = vector.broadcast %limit : index to vector<8xindex>
//   %mask = arith.cmpi slt, %step, %bcast : vector<8xindex>
static Value computeInBoundsMask(VectorTransferOpInterface xferOp,
                                 PatternRewriter &rewriter) {
  Location loc = xferOp.getLoc();
  ArrayRef<int64_t> vectorShape = xferOp.getVectorType().getShape();
  auto maskType = VectorType::get(vectorShape, rewriter.getI1Type());
  AffineMap map = xferOp.getPermutationMap();
  OperandRange indices = xferOp.getIndices();

  Value mask;
  for (unsigned v = 0, e = vectorShape.size(); v < e; ++v) {
    if (xferOp.isDimInBounds(v))
      continue;
    unsigned d = cast<AffineDimExpr>(map.getResult(v)).getPosition();
    Value bound = getMemrefDimSize(xferOp, d, rewriter);
    // A negative limit masks the dimension off entirely, which is what a
    // starting index past the end of the dimension should do.
    Value limit = arith::SubIOp::create(rewriter, loc, bound, indices[d]);
    auto stepType = VectorType::get({vectorShape[v]}, rewriter.getIndexType());
    Value step = vector::StepOp::create(rewriter, loc, stepType);
    Value limitVec =
        vector::BroadcastOp::create(rewriter, loc, stepType, limit);
    Value dimMask = arith::CmpIOp::create(
        rewriter, loc, arith::CmpIPredicate::slt, step, limitVec);
    if (vectorShape.size() > 1) {
      SmallVector<int64_t> expandedShape(vectorShape.size(), 1);
      expandedShape[v] = vectorShape[v];
      dimMask = vector::ShapeCastOp::create(
          rewriter, loc, VectorType::get(expandedShape, rewriter.getI1Type()),
          dimMask);
      dimMask = vector::BroadcastOp::create(rewriter, loc, maskType, dimMask);
    }
    mask = mask
               ? arith::AndIOp::create(rewriter, loc, mask, dimMask).getResult()
               : dimMask;
  }
  if (mask)
    return mask;
  return vector::ConstantMaskOp::create(rewriter, loc, maskType, vectorShape);
}

// Builds that mask as a scalar `i1`, for a transfer of a single element. The
// element sits at `indices`, so `i < dim(d) - indices[d]` at `i == 0` reduces
// to `indices[d] < dim(d)`, which needs neither the limit subtraction nor the
// step vector. The dimensions checked are the same.
//
// Example, for a `vector<1xf32>` read of a `memref<?xf32>` at `%off`:
//   %dim = memref.dim %src, %c0
//   %mask = arith.cmpi slt, %off, %dim : index
static Value computeUnitInBoundsMask(VectorTransferOpInterface xferOp,
                                     PatternRewriter &rewriter) {
  Location loc = xferOp.getLoc();
  AffineMap map = xferOp.getPermutationMap();
  OperandRange indices = xferOp.getIndices();

  Value mask;
  for (unsigned v = 0, e = xferOp.getVectorType().getRank(); v < e; ++v) {
    if (xferOp.isDimInBounds(v))
      continue;
    unsigned d = cast<AffineDimExpr>(map.getResult(v)).getPosition();
    Value bound = getMemrefDimSize(xferOp, d, rewriter);
    Value dimMask = arith::CmpIOp::create(
        rewriter, loc, arith::CmpIPredicate::slt, indices[d], bound);
    mask = mask
               ? arith::AndIOp::create(rewriter, loc, mask, dimMask).getResult()
               : dimMask;
  }
  if (mask)
    return mask;
  return arith::ConstantOp::create(rewriter, loc, rewriter.getBoolAttr(true));
}

// Compute the element-wise offsets for vector.gather or vector.scatter ops.
//
// This function linearizes the base offsets of the gather/scatter operation
// and combines them with the per-element indices to produce a final vector of
// memory offsets.
template <
    typename OpType,
    typename = std::enable_if_t<llvm::is_one_of<
        std::decay_t<OpType>, vector::GatherOp, vector::ScatterOp>::value>>
static Value computeOffsets(PatternRewriter &rewriter, OpType gatScatOp,
                            ArrayRef<Value> strides, Value baseOffset) {
  Location loc = gatScatOp.getLoc();
  SmallVector<Value> offsets = gatScatOp.getOffsets();
  for (size_t i = 0; i < offsets.size(); ++i) {
    Value offsetContrib =
        arith::MulIOp::create(rewriter, loc, offsets[i], strides[i]);
    baseOffset =
        arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
  }
  Value indices = gatScatOp.getIndices();
  VectorType vecType = cast<VectorType>(indices.getType());

  Value strideVector =
      vector::BroadcastOp::create(rewriter, loc, vecType, strides.back())
          .getResult();
  Value stridedIndices =
      arith::MulIOp::create(rewriter, loc, strideVector, indices).getResult();

  Value baseVector =
      vector::BroadcastOp::create(
          rewriter, loc,
          VectorType::get(vecType.getShape(), rewriter.getIndexType()),
          baseOffset)
          .getResult();
  return arith::AddIOp::create(rewriter, loc, baseVector, stridedIndices)
      .getResult();
}

// Collapses shapes of a nD memref to the target rank while applying offsets for
// the collapsed dimensions. Returns the new memref value and the remaining
// offsets for the last targetRank dimensions. For example:
//   input: %memref = memref<2x4x8x32xf32>, offsets=[%i0, %i1, %i2, %i3],
//   output: %memref[%i0, %i1, 0, 0] -> memref<8x32xf32>, offsets: [%i2, %i3]
static std::pair<Value, SmallVector<OpFoldResult>>
convertMemrefAndOffsetsToTargetRank(PatternRewriter &rewriter, Location loc,
                                    Value memref,
                                    SmallVector<OpFoldResult> offsets,
                                    int64_t targetRank) {
  auto memrefType = cast<MemRefType>(memref.getType());
  unsigned rank = memrefType.getRank();

  if (rank <= targetRank)
    return {memref, offsets};

  int64_t numCombinedDims = rank - targetRank;
  SmallVector<OpFoldResult> subviewOffsets;
  SmallVector<OpFoldResult> subviewSizes;
  SmallVector<OpFoldResult> subviewStrides;

  // For the combined dimensions: use the provided offsets, size=1, stride=1
  for (unsigned i = 0; i < numCombinedDims; ++i) {
    subviewOffsets.push_back(offsets[i]);
    subviewSizes.push_back(rewriter.getI64IntegerAttr(1));
    subviewStrides.push_back(rewriter.getI64IntegerAttr(1));
  }

  // For the last targetRank dimensions: offset=0, use full size, stride=1
  SmallVector<int64_t> resultShape;
  auto originalShape = memrefType.getShape();
  auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc, memref);
  for (unsigned i = numCombinedDims; i < rank; ++i) {
    subviewOffsets.push_back(rewriter.getI64IntegerAttr(0));
    if (ShapedType::isDynamic(originalShape[i])) {
      subviewSizes.push_back(meta.getSizes()[i]);
      resultShape.push_back(ShapedType::kDynamic);
    } else {
      subviewSizes.push_back(rewriter.getI64IntegerAttr(originalShape[i]));
      resultShape.push_back(originalShape[i]);
    }
    subviewStrides.push_back(rewriter.getI64IntegerAttr(1));
  }

  auto resultType = memref::SubViewOp::inferRankReducedResultType(
      resultShape, memrefType, subviewOffsets, subviewSizes, subviewStrides);
  auto subviewOp =
      memref::SubViewOp::create(rewriter, loc, resultType, memref,
                                subviewOffsets, subviewSizes, subviewStrides);

  // Return the remaining offsets for the last targetRank dimensions
  SmallVector<OpFoldResult> newOffsets(offsets.begin() + numCombinedDims,
                                       offsets.end());
  return {subviewOp.getResult(), newOffsets};
}

template <
    typename OpType,
    typename = std::enable_if_t<llvm::is_one_of<
        std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
        vector::GatherOp, vector::ScatterOp>::value>>
// Convert memref to i64 base pointer
static Value memrefToIndexPtr(OpType xferOp, PatternRewriter &rewriter) {
  Location loc = xferOp.getLoc();
  auto indexPtr = memref::ExtractAlignedPointerAsIndexOp::create(
                      rewriter, loc, xferOp.getBase())
                      .getResult();
  return arith::IndexCastOp::create(rewriter, loc, rewriter.getI64Type(),
                                    indexPtr)
      .getResult();
}

// Returns true if every use of `vec` extracts a scalar element from it. An
// unused value does not qualify.
static bool isUsedAsScalar(Value vec) {
  if (vec.use_empty())
    return false;
  return llvm::all_of(vec.getUsers(), [](Operation *user) {
    auto extractOp = dyn_cast<vector::ExtractOp>(user);
    return extractOp && !isa<VectorType>(extractOp.getResult().getType());
  });
}

// Lowers a transfer of a single element to a scalar `xegpu.load`.
//
// The transfer touches one location, which its own indices name, so the load
// takes a scalar offset and a scalar mask - no descriptor, no lane vectors -
// and the result is broadcast back to the transfer's unit-size vector type.
//
//   %off = arith.addi %base, %contrib : index
//   %inb = arith.cmpi slt, %idx, %dim : index
//   %val = xegpu.load %src[%off], %inb : i64, index, i1 -> f32
//   %vec = vector.broadcast %val : f32 to vector<1xf32>
static LogicalResult lowerToScalarLoadOp(vector::TransferReadOp readOp,
                                         PatternRewriter &rewriter) {
  Location loc = readOp.getLoc();
  VectorType vectorType = readOp.getVectorType();
  if (!isa<MemRefType>(readOp.getShapedType()))
    return rewriter.notifyMatchFailure(readOp, "Expected memref source");

  auto meta = computeMemrefMeta(readOp, rewriter);
  if (meta.first.empty())
    return rewriter.notifyMatchFailure(readOp, "Failed to compute strides");

  Value offset = computeBaseOffset(readOp, rewriter, meta.first, meta.second);
  Value flatMemref = memrefToIndexPtr(readOp, rewriter);

  Value mask = computeUnitInBoundsMask(readOp, rewriter);
  auto loadOp = xegpu::LoadGatherOp::create(
      rewriter, loc, vectorType.getElementType(), flatMemref, offset, mask,
      /*l1_hint=*/xegpu::CachePolicyAttr{},
      /*l2_hint=*/xegpu::CachePolicyAttr{},
      /*l3_hint=*/xegpu::CachePolicyAttr{},
      /*layout=*/nullptr, /*contiguity=*/nullptr);

  // A masked-off xegpu.load is unspecified, so the padding has to be applied
  // explicitly, as in lowerToScatteredLoadOp. A poison padding is "don't care".
  Value scalar = loadOp.getResult();
  if (readOp.hasOutOfBoundsDim() &&
      !readOp.getPadding().getDefiningOp<ub::PoisonOp>())
    scalar = arith::SelectOp::create(rewriter, loc, mask, scalar,
                                     readOp.getPadding());

  rewriter.replaceOpWithNewOp<vector::BroadcastOp>(readOp, vectorType, scalar);
  return success();
}

static LogicalResult lowerToScatteredLoadOp(vector::TransferReadOp readOp,
                                            PatternRewriter &rewriter) {

  Location loc = readOp.getLoc();
  VectorType vectorType = readOp.getVectorType();
  auto memrefType = dyn_cast<MemRefType>(readOp.getShapedType());
  if (!memrefType)
    return rewriter.notifyMatchFailure(readOp, "Expected memref source");

  auto meta = computeMemrefMeta(readOp, rewriter);
  if (meta.first.empty())
    return rewriter.notifyMatchFailure(readOp, "Failed to compute strides");

  Value localOffsets =
      computeOffsets(readOp, rewriter, meta.first, meta.second);

  Value flatMemref = memrefToIndexPtr(readOp, rewriter);

  Value mask = computeInBoundsMask(readOp, rewriter);
  auto gatherOp = xegpu::LoadGatherOp::create(
      rewriter, loc, vectorType, flatMemref, localOffsets, mask,
      /*l1_hint=*/xegpu::CachePolicyAttr{},
      /*l2_hint=*/xegpu::CachePolicyAttr{},
      /*l3_hint=*/xegpu::CachePolicyAttr{},
      /*layout=*/nullptr, /*contiguity=*/nullptr);

  // The masked-off lanes of an xegpu.load are unspecified, so the transfer's
  // padding has to be applied explicitly. A poison padding leaves them "don't
  // care", so the select can be skipped.
  Value result = gatherOp.getResult();
  if (readOp.hasOutOfBoundsDim() &&
      !readOp.getPadding().getDefiningOp<ub::PoisonOp>()) {
    Value padding = vector::BroadcastOp::create(rewriter, loc, vectorType,
                                                readOp.getPadding());
    result = arith::SelectOp::create(rewriter, loc, mask, result, padding);
  }

  rewriter.replaceOp(readOp, result);
  return success();
}

static LogicalResult lowerToScatteredStoreOp(vector::TransferWriteOp writeOp,
                                             PatternRewriter &rewriter) {

  Location loc = writeOp.getLoc();
  auto memrefType = dyn_cast<MemRefType>(writeOp.getShapedType());
  if (!memrefType)
    return rewriter.notifyMatchFailure(writeOp, "Expected memref source");

  auto meta = computeMemrefMeta(writeOp, rewriter);
  if (meta.first.empty())
    return rewriter.notifyMatchFailure(writeOp, "Failed to compute strides");

  Value localOffsets =
      computeOffsets(writeOp, rewriter, meta.first, meta.second);

  Value flatMemref = memrefToIndexPtr(writeOp, rewriter);

  // Out-of-bounds elements are simply not stored, so the mask is all this
  // needs - no counterpart to the read's padding.
  Value mask = computeInBoundsMask(writeOp, rewriter);
  xegpu::StoreScatterOp::create(rewriter, loc, writeOp.getVector(), flatMemref,
                                localOffsets, mask,
                                /*l1_hint=*/xegpu::CachePolicyAttr{},
                                /*l2_hint=*/xegpu::CachePolicyAttr{},
                                /*l3_hint=*/xegpu::CachePolicyAttr{},
                                /*layout=*/nullptr, /*contiguity=*/nullptr);
  rewriter.eraseOp(writeOp);
  return success();
}

struct TransferReadLowering : public OpRewritePattern<vector::TransferReadOp> {
  using Base::Base;

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

    if (failed(transferPreconditions(rewriter, readOp)))
      return failure();
    auto readMemTy = cast<MemRefType>(readOp.getShapedType());
    VectorType loadedVecTy = readOp.getVectorType();
    bool isOutOfBounds = readOp.hasOutOfBoundsDim();
    // Check if the memref has address space 3 (shared local memory)
    bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(readMemTy);
    // Handle the SLM case.
    if (isSharedMemory) {
      // load_matrix supports 1D and 2D loads from SLM.
      if (loadedVecTy.getRank() != 1 && loadedVecTy.getRank() != 2)
        return rewriter.notifyMatchFailure(
            readOp, "Only 1D and 2D vector loads are supported for SLM");
      AffineMap readMap = readOp.getPermutationMap();
      if (!readMap.isMinorIdentity())
        return rewriter.notifyMatchFailure(
            readOp,
            "Non identity transposition is not supported for SLM loads.");
      // Out of bounds case is not supported for SLM loads.
      if (isOutOfBounds)
        return rewriter.notifyMatchFailure(
            readOp, "Out-of-bounds access is not supported for SLM loads");

      // Create mem_desc for SLM
      auto memDescType =
          xegpu::MemDescType::get(rewriter.getContext(), readMemTy.getShape(),
                                  readMemTy.getElementType(),
                                  /*mem_layout=*/nullptr);
      auto createMemDescOp = xegpu::CreateMemDescOp::create(
          rewriter, loc, memDescType, readOp.getBase());
      // Convert indices to OpFoldResult for LoadMatrixOp
      SmallVector<OpFoldResult> indices =
          getAsOpFoldResult(readOp.getIndices());
      auto loadMatrixOp = xegpu::LoadMatrixOp::create(
          rewriter, loc, loadedVecTy, createMemDescOp.getResult(), indices,
          /*layout=*/nullptr);

      rewriter.replaceOp(readOp, loadMatrixOp.getResult());
      return success();
    }

    // A transfer of a single element that is only ever extracted to a scalar
    // becomes a scalar load, at any rank: the vector is a wrapper its consumers
    // undo, so neither an nd descriptor nor a lane-vector gather buys anything.
    // A unit-size vector genuinely used as a vector keeps the paths below.
    if (loadedVecTy.getNumElements() == 1 && isUsedAsScalar(readOp.getResult()))
      return lowerToScalarLoadOp(readOp, rewriter);

    const xegpu::uArch::uArch *uArch =
        xegpu::uArch::getUArch(xegpu::getChipStr(readOp).value_or(""));

    // An nd block load can realize a minor-identity map directly, or an
    // innermost-two-dims transpose via a trailing vector.transpose. Any other
    // permutation (e.g. a mid-vector transpose of a high-dim load) is left to
    // the scattered path, which permutes strides explicitly.
    AffineMap readMap = readOp.getPermutationMap();
    bool isTransposeLoad = isInnermostTwoDimsTransposed(readMap);

    // A block load transfers the tile as it is laid out in memory, so a
    // transposing read describes a tile whose innermost two dims are swapped.
    Type elementType = loadedVecTy.getElementType();
    SmallVector<int64_t> descShape(loadedVecTy.getShape());
    if (isTransposeLoad) {
      size_t rank = descShape.size();
      assert(rank >= 2 && "Transpose requires at least 2 dimensions");
      std::swap(descShape[rank - 1], descShape[rank - 2]);
    }

    // Prefer an nd block load. It requires a vector of rank >= 2 backed by a
    // scalar-element memref, a map the block load can realize, and a tile shape
    // the target's 2D block load can access. 1D vectors use the scattered
    // xegpu.load path instead, which has a richer interface (e.g. layout
    // capabilities). Out-of-bounds reads are allowed as long as the padding
    // matches load_nd's implicit zero padding.
    bool canLowerToLoadNd =
        loadedVecTy.getRank() > 1 &&
        (readMap.isMinorIdentity() || isTransposeLoad) &&
        readMemTy.getElementType().isIntOrFloat() &&
        (!isOutOfBounds || isZeroOrPoisonPadding(readOp.getPadding())) &&
        isSupportedBlockShape(
            uArch, xegpu::uArch::InstructionKind::Subgroup2DBlockLoad,
            descShape, elementType, /*hasTranspose=*/isTransposeLoad);

    if (canLowerToLoadNd) {
      // The load produces the memory-ordered tile; the transpose below restores
      // the shape the transfer_read asked for.
      if (isTransposeLoad)
        loadedVecTy = VectorType::get(descShape, elementType);
      auto descType = xegpu::TensorDescType::get(
          descShape, elementType, /*array_length=*/1,
          /*boundary_check=*/isOutOfBounds, xegpu::MemorySpace::Global);
      auto [src, indices] = convertMemrefAndOffsetsToTargetRank(
          rewriter, loc, readOp.getBase(),
          getAsOpFoldResult(readOp.getIndices()), loadedVecTy.getRank());
      // By default, no specific caching policy is assigned.
      xegpu::CachePolicyAttr hint = nullptr;
      xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
          rewriter, loc, descType, dyn_cast<TypedValue<MemRefType>>(src));

      Operation *loadedOp =
          xegpu::LoadNdOp::create(rewriter, loc, loadedVecTy, ndDesc, indices,
                                  /*packed=*/nullptr, /*transpose=*/nullptr,
                                  /*l1_hint=*/hint,
                                  /*l2_hint=*/hint, /*l3_hint=*/hint,
                                  /*layout=*/nullptr);
      if (isTransposeLoad) {
        // Undo the innermost-two-dims swap with a trailing vector.transpose:
        // keep the leading dimensions in place and interchange only the last
        // two.
        int64_t rank = loadedVecTy.getRank();
        SmallVector<int64_t> perm(llvm::to_vector(llvm::seq<int64_t>(0, rank)));
        std::swap(perm[rank - 1], perm[rank - 2]);
        loadedOp = vector::TransposeOp::create(rewriter, loc,
                                               loadedOp->getResult(0), perm);
      }
      rewriter.replaceOp(readOp, loadedOp);
      return success();
    }

    // Fall back to a scattered load. It supports arbitrary permutations and any
    // rank, and masks off the out-of-bounds elements.
    return lowerToScatteredLoadOp(readOp, rewriter);
  }
};

struct TransferWriteLowering
    : public OpRewritePattern<vector::TransferWriteOp> {
  using Base::Base;

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

    if (failed(transferPreconditions(rewriter, writeOp)))
      return failure();
    // Perform common data transfer checks.
    VectorType vecTy = writeOp.getVectorType();
    auto writeMemTy = cast<MemRefType>(writeOp.getShapedType());
    // Check if the memref has address space 3 (shared local memory)
    bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(writeMemTy);

    // For shared local memory (address space 3), use create_mem_desc +
    // store_matrix
    if (isSharedMemory) {
      // store_matrix supports 1D and 2D stores to SLM.
      if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
        return rewriter.notifyMatchFailure(
            writeOp, "Only 1D and 2D vector stores are supported for SLM");
      // Out of bounds case is not supported for SLM stores.
      if (writeOp.hasOutOfBoundsDim())
        return rewriter.notifyMatchFailure(
            writeOp, "Out-of-bounds access is not supported for SLM stores");
      // Create mem_desc for SLM
      auto memDescType =
          xegpu::MemDescType::get(rewriter.getContext(), writeMemTy.getShape(),
                                  writeMemTy.getElementType(),
                                  /*mem_layout=*/nullptr);

      auto createMemDescOp = xegpu::CreateMemDescOp::create(
          rewriter, loc, memDescType, writeOp.getBase());

      // Convert indices to OpFoldResult for StoreMatrixOp
      SmallVector<OpFoldResult> indices =
          getAsOpFoldResult(writeOp.getIndices());

      xegpu::StoreMatrixOp::create(rewriter, loc, writeOp.getVector(),
                                   createMemDescOp.getResult(), indices,
                                   /*layout=*/nullptr);

      rewriter.eraseOp(writeOp);
      return success();
    }

    const xegpu::uArch::uArch *uArch =
        xegpu::uArch::getUArch(xegpu::getChipStr(writeOp).value_or(""));

    // Prefer an nd block store. It requires a vector of rank >= 2 backed by a
    // scalar-element memref, a minor-identity map (block stores have no
    // transpose support), and a tile shape the target's 2D block store can
    // access. 1D vectors use the scattered xegpu.store path instead, which has
    // a richer interface. Out-of-bounds writes are handled by the descriptor's
    // boundary check.
    AffineMap map = writeOp.getPermutationMap();
    bool canLowerToStoreNd =
        vecTy.getRank() > 1 && map.isMinorIdentity() &&
        writeMemTy.getElementType().isIntOrFloat() &&
        isSupportedBlockShape(
            uArch, xegpu::uArch::InstructionKind::Subgroup2DBlockStore,
            vecTy.getShape(), vecTy.getElementType());

    if (canLowerToStoreNd) {
      auto [src, indices] = convertMemrefAndOffsetsToTargetRank(
          rewriter, loc, writeOp.getBase(),
          getAsOpFoldResult(writeOp.getIndices()), vecTy.getRank());

      auto descType = xegpu::TensorDescType::get(
          vecTy.getShape(), vecTy.getElementType(),
          /*array_length=*/1, /*boundary_check=*/writeOp.hasOutOfBoundsDim(),
          xegpu::MemorySpace::Global);
      // By default, no specific caching policy is assigned.
      xegpu::CachePolicyAttr hint = nullptr;
      xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
          rewriter, loc, descType, dyn_cast<TypedValue<MemRefType>>(src));

      auto storeOp = xegpu::StoreNdOp::create(
          rewriter, loc, writeOp.getVector(), ndDesc, indices,
          /*l1_hint=*/hint,
          /*l2_hint=*/hint, /*l3_hint=*/hint,
          /*layout=*/nullptr);
      rewriter.replaceOp(writeOp, storeOp);
      return success();
    }

    // Fall back to a scattered store. It supports arbitrary permutations and
    // any rank, and masks off the out-of-bounds elements.
    return lowerToScatteredStoreOp(writeOp, rewriter);
  }
};

struct GatherLowering : public OpRewritePattern<vector::GatherOp> {
  using Base::Base;

  LogicalResult matchAndRewrite(vector::GatherOp gatherOp,
                                PatternRewriter &rewriter) const override {
    auto srcTy = dyn_cast<MemRefType>(gatherOp.getBase().getType());
    if (!srcTy)
      return rewriter.notifyMatchFailure(gatherOp, "Expects memref source");

    Location loc = gatherOp.getLoc();
    VectorType vectorType = gatherOp.getVectorType();

    auto meta = computeMemrefMeta(gatherOp, rewriter);
    if (meta.first.empty())
      return rewriter.notifyMatchFailure(gatherOp, "Failed to compute strides");

    Value localOffsets =
        computeOffsets(rewriter, gatherOp, meta.first, meta.second);
    Value flatMemref = memrefToIndexPtr(gatherOp, rewriter);

    auto xeGatherOp = xegpu::LoadGatherOp::create(
        rewriter, loc, vectorType, flatMemref, localOffsets, gatherOp.getMask(),
        /*l1_hint=*/xegpu::CachePolicyAttr{},
        /*l2_hint=*/xegpu::CachePolicyAttr{},
        /*l3_hint=*/xegpu::CachePolicyAttr{},
        /*layout=*/nullptr, /*contiguity=*/nullptr);

    auto selectOp =
        arith::SelectOp::create(rewriter, loc, gatherOp.getMask(),
                                xeGatherOp.getResult(), gatherOp.getPassThru());
    rewriter.replaceOp(gatherOp, selectOp.getResult());
    return success();
  }
};

struct ScatterLowering : public OpRewritePattern<vector::ScatterOp> {
  using Base::Base;

  LogicalResult matchAndRewrite(vector::ScatterOp scatterOp,
                                PatternRewriter &rewriter) const override {
    auto srcTy = dyn_cast<MemRefType>(scatterOp.getBase().getType());
    if (!srcTy)
      return rewriter.notifyMatchFailure(scatterOp, "Expects memref source");

    Location loc = scatterOp.getLoc();
    auto meta = computeMemrefMeta(scatterOp, rewriter);
    if (meta.first.empty())
      return rewriter.notifyMatchFailure(scatterOp,
                                         "Failed to compute strides");

    Value localOffsets =
        computeOffsets(rewriter, scatterOp, meta.first, meta.second);
    Value flatMemref = memrefToIndexPtr(scatterOp, rewriter);

    xegpu::StoreScatterOp::create(rewriter, loc, scatterOp.getValueToStore(),
                                  flatMemref, localOffsets, scatterOp.getMask(),
                                  /*l1_hint=*/xegpu::CachePolicyAttr{},
                                  /*l2_hint=*/xegpu::CachePolicyAttr{},
                                  /*l3_hint=*/xegpu::CachePolicyAttr{},
                                  /*layout=*/nullptr,
                                  /*contiguity=*/nullptr);
    rewriter.eraseOp(scatterOp);
    return success();
  }
};

struct LoadLowering : public OpRewritePattern<vector::LoadOp> {
  using Base::Base;

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

    VectorType vecTy = loadOp.getResult().getType();
    MemRefType memTy = loadOp.getBase().getType();
    // The plain vector.load lowering only supports 1D/2D block loads.
    if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
      return rewriter.notifyMatchFailure(loadOp, "Expects 1D or 2D vector");
    if (!memTy.getElementType().isIntOrFloat())
      return rewriter.notifyMatchFailure(
          loadOp, "Unsupported memref element type: expected integer or float");

    // Boundary check is available only for block instructions.
    bool boundaryCheck = vecTy.getRank() > 1;
    // By default, no specific caching policy is assigned.
    xegpu::CachePolicyAttr hint = nullptr;

    auto [src, indices] = convertMemrefAndOffsetsToTargetRank(
        rewriter, loc, loadOp.getBase(), getAsOpFoldResult(loadOp.getIndices()),
        vecTy.getRank());

    auto descType = xegpu::TensorDescType::get(
        vecTy.getShape(), vecTy.getElementType(), /*array_length=*/1,
        boundaryCheck, xegpu::MemorySpace::Global);

    xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
        rewriter, loc, descType, dyn_cast<TypedValue<MemRefType>>(src));
    auto loadNdOp =
        xegpu::LoadNdOp::create(rewriter, loc, vecTy, ndDesc, indices,
                                /*packed=*/nullptr, /*transpose=*/nullptr,
                                /*l1_hint=*/hint,
                                /*l2_hint=*/hint, /*l3_hint=*/hint,
                                /*layout=*/nullptr);
    rewriter.replaceOp(loadOp, loadNdOp);

    return success();
  }
};

struct StoreLowering : public OpRewritePattern<vector::StoreOp> {
  using Base::Base;

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

    TypedValue<VectorType> vector = storeOp.getValueToStore();
    VectorType vecTy = vector.getType();
    MemRefType memTy = storeOp.getBase().getType();
    // The plain vector.store lowering only supports 1D/2D block stores.
    if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
      return rewriter.notifyMatchFailure(storeOp, "Expects 1D or 2D vector");
    if (!memTy.getElementType().isIntOrFloat())
      return rewriter.notifyMatchFailure(
          storeOp,
          "Unsupported memref element type: expected integer or float");

    // Boundary check is available only for block instructions.
    bool boundaryCheck = vecTy.getRank() > 1;

    auto [src, indices] = convertMemrefAndOffsetsToTargetRank(
        rewriter, loc, storeOp.getBase(),
        getAsOpFoldResult(storeOp.getIndices()), vecTy.getRank());

    auto descType = xegpu::TensorDescType::get(
        vecTy.getShape(), vecTy.getElementType(),
        /*array_length=*/1, boundaryCheck, xegpu::MemorySpace::Global);

    // By default, no specific caching policy is assigned.
    xegpu::CachePolicyAttr hint = nullptr;
    xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
        rewriter, loc, descType, dyn_cast<TypedValue<MemRefType>>(src));

    auto storeNdOp =
        xegpu::StoreNdOp::create(rewriter, loc, vector, ndDesc, indices,
                                 /*l1_hint=*/hint,
                                 /*l2_hint=*/hint, /*l3_hint=*/hint,
                                 /*layout=*/nullptr);

    rewriter.replaceOp(storeOp, storeNdOp);

    return success();
  }
};

// If `indexingMaps` describe a (batched) row-major matmul
//   lhs[b..., m, k], rhs[b..., k, n], acc[b..., m, n]
// return the number of leading batch dims (0 for a plain 2D matmul);
// otherwise return std::nullopt.
static std::optional<int64_t>
getRowMajorMatmulBatchRank(ArrayAttr indexingMaps) {
  if (indexingMaps.size() != 3)
    return std::nullopt;

  AffineMap mapA = cast<AffineMapAttr>(indexingMaps[0]).getValue();
  AffineMap mapB = cast<AffineMapAttr>(indexingMaps[1]).getValue();
  AffineMap mapC = cast<AffineMapAttr>(indexingMaps[2]).getValue();

  // The result map exposes the batch dims followed by the core (m, n) dims.
  if (mapC.getNumResults() < 2)
    return std::nullopt;
  int64_t batchRank = mapC.getNumResults() - 2;

  // A single `k` reduction gives batchRank + 3 iteration dims; each operand
  // map exposes batchRank + 2 dims (batch dims + 2 core dims).
  unsigned numDims = static_cast<unsigned>(batchRank) + 3;
  unsigned numOperandResults = static_cast<unsigned>(batchRank) + 2;
  if (mapA.getNumInputs() != numDims || mapB.getNumInputs() != numDims ||
      mapC.getNumInputs() != numDims)
    return std::nullopt;
  if (mapA.getNumResults() != numOperandResults ||
      mapB.getNumResults() != numOperandResults)
    return std::nullopt;

  // Reconstruct the canonical maps from the batch/m/n dims of the result and
  // the k dim of lhs, then compare against the actual maps.
  MLIRContext *context = indexingMaps.getContext();
  ArrayRef<AffineExpr> batchDims = mapC.getResults().take_front(batchRank);
  AffineExpr m = mapC.getResult(batchRank);
  AffineExpr n = mapC.getResult(batchRank + 1);
  AffineExpr k = mapA.getResult(batchRank + 1);

  SmallVector<AffineExpr> aDims = llvm::to_vector(batchDims);
  aDims.push_back(m);
  aDims.push_back(k);
  SmallVector<AffineExpr> bDims = llvm::to_vector(batchDims);
  bDims.push_back(k);
  bDims.push_back(n);
  SmallVector<AffineExpr> cDims = llvm::to_vector(batchDims);
  cDims.push_back(m);
  cDims.push_back(n);

  auto expected = ArrayAttr::get(
      context,
      {AffineMapAttr::get(AffineMap::get(numDims, 0, aDims, context)),
       AffineMapAttr::get(AffineMap::get(numDims, 0, bDims, context)),
       AffineMapAttr::get(AffineMap::get(numDims, 0, cDims, context))});
  if (indexingMaps != expected)
    return std::nullopt;
  return batchRank;
}

struct ContractionLowering : 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");

    TypedValue<VectorType> lhs = contractOp.getLhs();
    TypedValue<VectorType> rhs = contractOp.getRhs();
    TypedValue<Type> acc = contractOp.getAcc();
    VectorType accType = dyn_cast<VectorType>(acc.getType());
    if (!accType)
      return rewriter.notifyMatchFailure(contractOp, "Expects vector acc");

    std::optional<int64_t> batchRank =
        getRowMajorMatmulBatchRank(contractOp.getIndexingMapsAttr());
    if (!batchRank)
      return rewriter.notifyMatchFailure(
          contractOp,
          "Expects a (batched) row-major matmul: leading dims must "
          "be batch dims shared by lhs, rhs, and acc; innermost two "
          "dims must be (M, K), (K, N), and (M, N)");

    // xegpu.dpas operands are limited to 2 batch + 2 core dims.
    if (*batchRank > 2)
      return rewriter.notifyMatchFailure(contractOp,
                                         "Expects operands of rank 4 or less");

    auto dpasOp = xegpu::DpasOp::create(
        rewriter, loc, contractOp.getResultType(), lhs, rhs, acc,
        /*layout_a=*/nullptr, /*layout_b=*/nullptr, /*layout_cd=*/nullptr);
    rewriter.replaceOp(contractOp, dpasOp);

    return success();
  }
};

// Returns the `vector.shape_cast` that flattened a value of type `ndType` into
// `flat`, if that is how `flat` was produced.
static vector::ShapeCastOp getFlattenCast(Value flat, VectorType ndType) {
  auto shapeCast = flat.getDefiningOp<vector::ShapeCastOp>();
  if (shapeCast && shapeCast.getSourceVectorType() == ndType)
    return shapeCast;
  return nullptr;
}

static DenseElementsAttr getDenseConstant(Value flat) {
  DenseElementsAttr elements;
  if (matchPattern(flat, m_Constant(&elements)))
    return elements;
  return nullptr;
}

static vector::BroadcastOp getSplatBroadcast(Value flat) {
  auto broadcast = flat.getDefiningOp<vector::BroadcastOp>();
  if (broadcast && !isa<VectorType>(broadcast.getSourceType()))
    return broadcast;
  return nullptr;
}

// Returns true if the cast `unflatten` creates will fold away, i.e. if `flat`
// is a flattening cast, a constant or a splat.
static bool canUnflatten(Value flat, VectorType ndType) {
  return getFlattenCast(flat, ndType) || getDenseConstant(flat) ||
         getSplatBroadcast(flat);
}

// Reshape `flat` to `ndType`; `canUnflatten` must hold so the cast folds away.
static Value unflatten(PatternRewriter &rewriter, Value flat,
                       VectorType ndType) {
  assert(canUnflatten(flat, ndType) && "expected the cast to fold away");
  return vector::ShapeCastOp::create(rewriter, flat.getLoc(), ndType, flat);
}

// Restore the N-D form of a flattened `vector.gather` / `vector.scatter`.
//
// XeGPU layouts are expressed in terms of the N-D shape of the accessed data,
// so a flattened gather/scatter forces layout propagation to reason through the
// surrounding `vector.shape_cast` ops. That adds complexity and tends to yield
// layouts that lower to unoptimized code.
//
// Before:
//   %cst = arith.constant dense<0.0> : vector<8192xbf16>
//   %fi = vector.shape_cast %idx : vector<128x64xindex> to vector<8192xindex>
//   %fm = vector.shape_cast %mask : vector<128x64xi1> to vector<8192xi1>
//   %fr = vector.gather %src[%c0] [%fi], %fm, %cst : memref<?xbf16>,
//       vector<8192xindex>, vector<8192xi1>, vector<8192xbf16>
//       into vector<8192xbf16>
//   %res = vector.shape_cast %fr : vector<8192xbf16> to vector<128x64xbf16>
//
// After:
//   %cst = arith.constant dense<0.0> : vector<128x64xbf16>
//   %res = vector.gather %src[%c0] [%idx], %mask, %cst : memref<?xbf16>,
//       vector<128x64xindex>, vector<128x64xi1>, vector<128x64xbf16>
//       into vector<128x64xbf16>
template <typename OpTy>
struct UnflattenGatherScatter : public OpRewritePattern<OpTy> {
  using OpRewritePattern<OpTy>::OpRewritePattern;

  LogicalResult matchAndRewrite(OpTy op,
                                PatternRewriter &rewriter) const override {
    constexpr bool isGather = std::is_same_v<OpTy, vector::GatherOp>;

    if (!isa<MemRefType>(op.getBase().getType()))
      return rewriter.notifyMatchFailure(op, "expects a memref source");

    if (op.getIndexVectorType().getRank() != 1)
      return rewriter.notifyMatchFailure(op, "index vector is not 1-D");

    // The N-D shape comes from the index operand's producer: this only undoes
    // a flattening that already happened, it never invents a shape.
    auto indexCast =
        op.getIndices().template getDefiningOp<vector::ShapeCastOp>();
    if (!indexCast || indexCast.getSourceVectorType().getRank() < 2)
      return rewriter.notifyMatchFailure(
          op, "index vector is not a shape_cast of an N-D vector");
    VectorType ndIndexType = indexCast.getSourceVectorType();
    VectorType ndMaskType =
        ndIndexType.cloneWith(std::nullopt, rewriter.getI1Type());
    VectorType ndType = ndIndexType.cloneWith(
        std::nullopt, op.getVectorType().getElementType());

    // Check everything before creating any IR: a partially applied rewrite
    // would leave dead ops behind.
    if (!canUnflatten(op.getMask(), ndMaskType))
      return rewriter.notifyMatchFailure(op, "cannot un-flatten the mask");

    if constexpr (isGather) {
      if (!canUnflatten(op.getPassThru(), ndType))
        return rewriter.notifyMatchFailure(op,
                                           "cannot un-flatten the pass-thru");

      Value mask = unflatten(rewriter, op.getMask(), ndMaskType);
      Value passThru = unflatten(rewriter, op.getPassThru(), ndType);
      auto ndGather = vector::GatherOp::create(
          rewriter, op.getLoc(), ndType, op.getBase(), op.getOffsets(),
          indexCast.getSource(), mask, passThru, op.getAlignmentAttr());
      ndGather->setDiscardableAttrs(op->getDiscardableAttrDictionary());
      rewriter.replaceOpWithNewOp<vector::ShapeCastOp>(op, op.getVectorType(),
                                                       ndGather);
    } else {
      if (!canUnflatten(op.getValueToStore(), ndType))
        return rewriter.notifyMatchFailure(
            op, "cannot un-flatten the stored value");

      Value mask = unflatten(rewriter, op.getMask(), ndMaskType);
      Value valueToStore = unflatten(rewriter, op.getValueToStore(), ndType);
      // Only operand types change, and this keeps the optional tensor result
      // untouched.
      rewriter.modifyOpInPlace(op, [&] {
        op.getIndicesMutable().assign(indexCast.getSource());
        op.getMaskMutable().assign(mask);
        op.getValueToStoreMutable().assign(valueToStore);
      });
    }
    return success();
  }
};

// Un-flatten every gather/scatter that was flattened to 1-D operands, so that
// the conversion patterns and the XeGPU layouts downstream of them see the N-D
// shape of the accessed data.
static LogicalResult unflattenGatherScatter(Operation *root) {
  MLIRContext *ctx = root->getContext();
  RewritePatternSet patterns(ctx);
  patterns.add<UnflattenGatherScatter<vector::GatherOp>,
               UnflattenGatherScatter<vector::ScatterOp>>(ctx);
  vector::ShapeCastOp::getCanonicalizationPatterns(patterns, ctx);
  return applyPatternsGreedily(root, std::move(patterns));
}

// Returns `memrefTy` with its memory space replaced by `newMemSpace`.
static MemRefType withMemorySpace(MemRefType memrefTy, Attribute newMemSpace) {
  return MemRefType::get(memrefTy.getShape(), memrefTy.getElementType(),
                         memrefTy.getLayout(), newMemSpace);
}

// Rewrite every `memref.alloca` not already in shared local memory (SLM) to
// be in SLM (address space 3), and propagate the new memory space through
// memref-producing aliasing users (e.g. memref.cast, memref.subview,
// memref.expand_shape, ...). Consumers that take a memref operand but
// produce a non-memref result (e.g. vector.transfer_read, vector.load) are
// left untouched: their operand type simply reflects the new memory space.
//
// This makes `xegpu.load_matrix`/`xegpu.store_matrix` lowering work end-to-end
// for IR coming from bufferization, which by default assigns memory space 0/1
// to allocations.
static void promoteAllocasToSLM(Operation *root) {
  MLIRContext *ctx = root->getContext();
  Attribute slmAttr = IntegerAttr::get(IntegerType::get(ctx, 64), 3);

  // A user is treated as a memref-producing alias (e.g. memref.cast,
  // memref.subview, memref.expand_shape, ...) if it is side-effect free and
  // produces at least one memref result. This excludes ops like memref.copy
  // that have memory effects.
  auto isMemrefResultOp = [](Operation *op) {
    if (!isMemoryEffectFree(op))
      return false;
    return llvm::any_of(op->getResultTypes(),
                        [](Type t) { return isa<MemRefType>(t); });
  };

  // Update `v`'s type to have SLM memory space, then walk forward through
  // memref-producing users and update their result types accordingly.
  std::function<void(Value)> propagate = [&](Value v) {
    auto memrefTy = dyn_cast<MemRefType>(v.getType());
    if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
      return;
    v.setType(withMemorySpace(memrefTy, slmAttr));
    for (Operation *user : v.getUsers()) {
      if (!isMemrefResultOp(user))
        continue;
      for (Value result : user->getResults())
        propagate(result);
    }
  };

  SmallVector<memref::AllocaOp> allocas;
  root->walk([&](memref::AllocaOp op) {
    auto memrefTy = dyn_cast<MemRefType>(op.getResult().getType());
    if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
      return;
    allocas.push_back(op);
  });

  for (memref::AllocaOp alloca : allocas) {
    OpBuilder builder(alloca);
    auto memrefTy = cast<MemRefType>(alloca.getResult().getType());
    auto newTy = withMemorySpace(memrefTy, slmAttr);
    auto newOp = memref::AllocaOp::create(
        builder, alloca.getLoc(), newTy, alloca.getDynamicSizes(),
        alloca.getSymbolOperands(), alloca.getAlignmentAttr());
    alloca.getResult().replaceAllUsesWith(newOp.getResult());
    alloca.erase();
    // Propagate the new memory space through memref-producing consumers.
    for (Operation *user : newOp.getResult().getUsers()) {
      if (!isMemrefResultOp(user))
        continue;
      for (Value result : user->getResults())
        propagate(result);
    }
  }
}

struct ConvertVectorToXeGPUPass
    : public impl::ConvertVectorToXeGPUBase<ConvertVectorToXeGPUPass> {
  void runOnOperation() override {
    // Promote local allocations to SLM (address space 3) so that
    // load_matrix/store_matrix lowerings have well-typed memref operands.
    promoteAllocasToSLM(getOperation());

    // Undo any flattening of gather/scatter operands, so that the conversion
    // below sees the N-D shape the XeGPU layouts are expressed in.
    if (failed(unflattenGatherScatter(getOperation())))
      return signalPassFailure();

    RewritePatternSet patterns(&getContext());
    populateVectorToXeGPUConversionPatterns(patterns);
    populatePrepareVectorToMMAPatterns(patterns);
    if (failed(applyPatternsGreedily(getOperation(), std::move(patterns))))
      return signalPassFailure();
  }
};

} // namespace

void mlir::populateVectorToXeGPUConversionPatterns(
    RewritePatternSet &patterns) {
  patterns
      .add<TransferReadLowering, TransferWriteLowering, LoadLowering,
           ScatterLowering, GatherLowering, StoreLowering, ContractionLowering>(
          patterns.getContext());
}
