//===- ParallelLoopFusion.cpp - Code to perform loop fusion ---------------===//
//
// 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 loop fusion on parallel loops.
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/SCF/Transforms/Passes.h"

#include "mlir/Analysis/AliasAnalysis.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Index/IR/IndexOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/MemRef/Utils/MemRefUtils.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/SCF/Utils/Utils.h"
#include "mlir/Dialect/Utils/IndexingUtils.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OperationSupport.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/Value.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/InterleavedRange.h"

#include "llvm/Support/DebugLog.h"
#include <numeric>
#include <optional>
#include <tuple>
#define DEBUG_TYPE "parallel-loop-fusion"

namespace mlir {
#define GEN_PASS_DEF_SCFPARALLELLOOPFUSION
#include "mlir/Dialect/SCF/Transforms/Passes.h.inc"
} // namespace mlir

using namespace mlir;
using namespace mlir::scf;

/// Verify there are no nested ParallelOps.
static bool hasNestedParallelOp(ParallelOp ploop) {
  auto walkResult =
      ploop.getBody()->walk([](ParallelOp) { return WalkResult::interrupt(); });
  return walkResult.wasInterrupted();
}

/// Verify equal iteration spaces.
static bool equalIterationSpaces(ParallelOp firstPloop,
                                 ParallelOp secondPloop) {
  if (firstPloop.getNumLoops() != secondPloop.getNumLoops() ||
      firstPloop.getUnsignedCmp() != secondPloop.getUnsignedCmp())
    return false;

  // Two bounds match if they are the same value, or if both are constants
  // holding the same value. The latter matters because equivalent bounds are
  // often materialized by distinct `arith.constant` ops, which leaves the
  // iteration spaces equal even though the SSA values differ.
  auto matchOperands = [&](const OperandRange &lhs,
                           const OperandRange &rhs) -> bool {
    // TODO: Extend this to support aliases.
    return std::equal(lhs.begin(), lhs.end(), rhs.begin(),
                      [](Value lhsValue, Value rhsValue) {
                        if (lhsValue == rhsValue)
                          return true;
                        std::optional<int64_t> lhsConst =
                            getConstantIntValue(lhsValue);
                        std::optional<int64_t> rhsConst =
                            getConstantIntValue(rhsValue);
                        return lhsConst && rhsConst && *lhsConst == *rhsConst;
                      });
  };
  return matchOperands(firstPloop.getLowerBound(),
                       secondPloop.getLowerBound()) &&
         matchOperands(firstPloop.getUpperBound(),
                       secondPloop.getUpperBound()) &&
         matchOperands(firstPloop.getStep(), secondPloop.getStep());
}

/// Check if both operations are the same type of memory write op and
/// write to the same memory location (same buffer and same indices).
static bool opsWriteSameMemLocation(Operation *op1, Operation *op2) {
  if (!op1 || !op2 || op1->getName() != op2->getName())
    return false;
  if (op1 == op2)
    return true;
  // support only these memory-writing ops for now
  if (!isa<memref::StoreOp, vector::TransferWriteOp, vector::StoreOp>(op1))
    return false;
  bool opsAreIdentical =
      llvm::TypeSwitch<Operation *, bool>(op1)
          .Case([&](memref::StoreOp storeOp1) {
            auto storeOp2 = cast<memref::StoreOp>(op2);
            return (storeOp1.getMemRef() == storeOp2.getMemRef()) &&
                   (storeOp1.getIndices() == storeOp2.getIndices());
          })
          .Case([&](vector::TransferWriteOp writeOp1) {
            auto writeOp2 = cast<vector::TransferWriteOp>(op2);
            return (writeOp1.getBase() == writeOp2.getBase()) &&
                   (writeOp1.getIndices() == writeOp2.getIndices()) &&
                   (writeOp1.getMask() == writeOp2.getMask()) &&
                   (writeOp1.getValueToStore().getType() ==
                    writeOp2.getValueToStore().getType()) &&
                   (writeOp1.getInBounds() == writeOp2.getInBounds());
          })
          .Case([&](vector::StoreOp vecStoreOp1) {
            auto vecStoreOp2 = cast<vector::StoreOp>(op2);
            return (vecStoreOp1.getBase() == vecStoreOp2.getBase()) &&
                   (vecStoreOp1.getIndices() == vecStoreOp2.getIndices()) &&
                   (vecStoreOp1.getValueToStore().getType() ==
                    vecStoreOp2.getValueToStore().getType()) &&
                   (vecStoreOp1.getAlignment() == vecStoreOp2.getAlignment()) &&
                   (vecStoreOp1.getNontemporal() ==
                    vecStoreOp2.getNontemporal());
          })
          .Default([](Operation *) { return false; });
  return opsAreIdentical;
}

/// Check if val1 (from the first parallel loop) and val2 (from the
/// second) are equivalent, considering the mapping of induction variables from
/// the first to the second parallel loop.
static bool valsAreEquivalent(Value val1, Value val2,
                              const IRMapping &loopsIVsMap) {
  if (val1 == val2 || loopsIVsMap.lookupOrDefault(val1) == val2 ||
      loopsIVsMap.lookupOrDefault(val2) == val1)
    return true;
  Operation *val1DefOp = val1.getDefiningOp();
  Operation *val2DefOp = val2.getDefiningOp();
  if (!val1DefOp || !val2DefOp)
    return false;
  if (!isMemoryEffectFree(val1DefOp) || !isMemoryEffectFree(val2DefOp))
    return false;
  return OperationEquivalence::isEquivalentTo(
      val1DefOp, val2DefOp,
      [&](Value v1, Value v2) {
        return success(loopsIVsMap.lookupOrDefault(v1) == v2 ||
                       loopsIVsMap.lookupOrDefault(v2) == v1);
      },
      /*markEquivalent=*/nullptr, OperationEquivalence::Flags::IgnoreLocations);
}

/// If the `expr` value is the result of an integer addition of `base` and a
/// constant, return the constant.
static std::optional<int64_t> getAddConstant(Value expr, Value base,
                                             const IRMapping &loopsIVsMap) {
  if (auto addOp = expr.getDefiningOp<arith::AddIOp>()) {
    if (auto constOp = getConstantIntValue(addOp.getLhs());
        constOp && valsAreEquivalent(addOp.getRhs(), base, loopsIVsMap))
      return constOp.value();
    if (auto constOp = getConstantIntValue(addOp.getRhs());
        constOp && valsAreEquivalent(addOp.getLhs(), base, loopsIVsMap))
      return constOp.value();
    return std::nullopt;
  }

  if (auto addOp = expr.getDefiningOp<index::AddOp>()) {
    if (auto constOp = getConstantIntValue(addOp.getLhs());
        constOp && valsAreEquivalent(addOp.getRhs(), base, loopsIVsMap))
      return constOp.value();
    if (auto constOp = getConstantIntValue(addOp.getRhs());
        constOp && valsAreEquivalent(addOp.getLhs(), base, loopsIVsMap))
      return constOp.value();
    return std::nullopt;
  }

  if (auto applyOp = expr.getDefiningOp<affine::AffineApplyOp>()) {
    AffineMap map = applyOp.getAffineMap();
    if (map.getNumResults() != 1 || map.getNumDims() != 1 ||
        map.getNumSymbols() != 0)
      return std::nullopt;
    if (!valsAreEquivalent(applyOp.getOperand(0), base, loopsIVsMap))
      return std::nullopt;
    AffineExpr result = map.getResult(0);
    auto bin = dyn_cast<AffineBinaryOpExpr>(result);
    if (!bin || bin.getKind() != AffineExprKind::Add)
      return std::nullopt;
    auto lhsDim = dyn_cast<AffineDimExpr>(bin.getLHS());
    auto rhsDim = dyn_cast<AffineDimExpr>(bin.getRHS());
    auto lhsConst = dyn_cast<AffineConstantExpr>(bin.getLHS());
    auto rhsConst = dyn_cast<AffineConstantExpr>(bin.getRHS());
    if (lhsConst && rhsDim)
      return lhsConst.getValue();
    if (rhsConst && lhsDim)
      return rhsConst.getValue();
  }
  return std::nullopt;
}

// Return true if the scalar load index may hit any element covered by a
// vector.store/transfer_write along a single memref dimension. Supported cases:
//
// 1) Direct index match (with optional offset):
//    vector.transfer_write %v, %A[%i] : vector<4xf32>, memref<...>
//    %x = memref.load %A[%i] : memref<...>
//
// 2) Loop IV range intersects the write range:
//    vector.transfer_write %v, %A[%c0] : vector<4xf32>, memref<...>
//    scf.for %k = %c0 to %c4 step %c1 { %x = memref.load %A[%k] }
//
// 3) Constant index (or IV + constant) within the write range:
//    vector.transfer_write %v, %A[%c0] : vector<4xf32>, memref<...>
//    %x = memref.load %A[%c2] : memref<...>
//    %y = memref.load %A[%i + %c1] : memref<...>
//
// Args:
// - loadIndex: index used by the scalar load for this dimension.
// - offset: subview offset for the base memref dimension (if any).
// - writeIndex: index used by the transfer_write for this dimension. Can be
// null if the dim was dropped by a rank reducing subview, whose result is
// written by the vector.write.
// - extent: vector size along this dimension (number of elements written).
// - loopsIVsMap: IV equivalence map between fused loops.
static bool loadIndexWithinWriteRange(Value loadIndex, OpFoldResult offset,
                                      Value writeIndex, int64_t extent,
                                      const IRMapping &loopsIVsMap) {
  if (extent <= 0)
    return false;

  // Extract constant loop bounds for loop IVs (e.g. from scf.for).
  auto getConstLoopBoundsForIV =
      [](Value index) -> std::optional<std::tuple<int64_t, int64_t, int64_t>> {
    auto blockArg = dyn_cast<BlockArgument>(index);
    if (!blockArg)
      return std::nullopt;
    auto *parentOp = blockArg.getOwner()->getParentOp();
    auto loopLike = dyn_cast<LoopLikeOpInterface>(parentOp);
    if (!loopLike)
      return std::nullopt;
    auto ranges = getConstLoopBounds(loopLike);
    if (ranges.empty())
      return std::nullopt;

    auto ivs = loopLike.getLoopInductionVars();
    if (!ivs)
      return std::nullopt;
    auto it = llvm::find(*ivs, blockArg);
    if (it == ivs->end())
      return std::nullopt;
    unsigned pos = std::distance(ivs->begin(), it);
    if (pos >= ranges.size())
      return std::nullopt;
    auto [lb, ub, step] = ranges[pos];
    return std::make_tuple(lb, ub, step);
  };

  std::optional<int64_t> offsetConst = getConstantIntValue(offset);
  std::optional<int64_t> writeConst =
      writeIndex ? getConstantIntValue(writeIndex) : std::optional<int64_t>(0);
  if (!writeConst && writeIndex) {
    // Treat single-iteration IVs as constants for matching.
    if (auto bounds = getConstLoopBoundsForIV(writeIndex)) {
      auto [lb, ub, step] = *bounds;
      if (step > 0 && ub == lb + step)
        writeConst = lb;
    }
  }

  // Check whether a loop IV is fully contained in a constant write range.
  auto loopIVWithinRange = [](int64_t lb, int64_t ub, int64_t step,
                              int64_t rangeStart, int64_t rangeExtent) -> bool {
    if (rangeExtent <= 0 || step <= 0)
      return false;
    if (ub <= lb)
      return false;
    int64_t rangeEnd = rangeStart + rangeExtent;
    return lb >= rangeStart && ub <= rangeEnd;
  };

  if (offsetConst && writeConst) {
    // Constant start of the write range; check constant load or loop IV range.
    int64_t start = *offsetConst + *writeConst;
    if (auto loadConst = getConstantIntValue(loadIndex))
      return (*loadConst >= start && *loadConst < start + extent);
    if (auto bounds = getConstLoopBoundsForIV(loadIndex)) {
      auto [lb, ub, step] = *bounds;
      return loopIVWithinRange(lb, ub, step, start, extent);
    }
  }

  if (writeIndex) {
    // Direct IV match (or IV + constant) against the write index.
    if (offsetConst && *offsetConst == 0 &&
        valsAreEquivalent(loadIndex, writeIndex, loopsIVsMap))
      return true;
    if (auto addConst = getAddConstant(loadIndex, writeIndex, loopsIVsMap)) {
      // Match load index of the form writeIndex + C within the write extent.
      if (offsetConst) {
        int64_t start = *offsetConst;
        return (*addConst >= start && *addConst < start + extent);
      }
    }
    return false;
  }

  if (auto offsetVal = dyn_cast<Value>(offset)) {
    // Exact match when extent is 1 and the load hits the offset value.
    if (extent == 1 && valsAreEquivalent(loadIndex, offsetVal, loopsIVsMap))
      return true;
  }

  return false;
}

/// Return the base memref value used by the given memory op.
static Value getBaseMemref(Operation *op) {
  // TODO: use the common interface for memory ops once available.
  return llvm::TypeSwitch<Operation *, Value>(op)
      .Case([&](memref::LoadOp load) { return load.getMemRef(); })
      .Case([&](memref::StoreOp store) { return store.getMemRef(); })
      .Case([&](vector::TransferReadOp read) { return read.getBase(); })
      .Case([&](vector::TransferWriteOp write) { return write.getBase(); })
      .Case([&](vector::LoadOp load) { return load.getBase(); })
      .Case([&](vector::StoreOp store) { return store.getBase(); })
      .Default([](Operation *) { return Value(); });
}

/// Recognize scalar memref.load of an element produced by a vector write
/// (vector.transfer_write or vector.store, optionally through a rank-reducing
/// unit-stride subview) of the same buffer. This covers the pattern where a
/// vector write stores a full lane pack and a subsequent scalar load reads an
/// element from that lane pack. EXAMPLE:
///  vector.transfer_write %V, %arg[%x, %y, ..., 0] {in_bounds = [true]} :
///             vector<4xf32>, memref<4xf32, strided<[1], offset: ?>>
///  scf.for %iter = %c0 to %c4 step %c1 iter_args(...) -> (f32) {
///    %0 = memref.load %arg[%x, %y, ..., %iter] : memref<1x128x16x4xf32>
///    ...
///  }
///
static bool isLoadOnWrittenVector(memref::LoadOp loadOp, Value writeBase,
                                  ValueRange writeIndices, VectorType vecTy,
                                  ArrayRef<int64_t> vectorDimForWriteDim,
                                  const IRMapping &ivsMap) {
  if (!vecTy)
    return false;

  Value base = writeBase;
  // The write base if there is no subview, or the subview source otherwise.
  MemrefValue baseMemref = nullptr;
  SmallVector<OpFoldResult> offsets;
  llvm::SmallBitVector droppedDims;
  bool hasSubview = false;
  auto *ctx = loadOp.getContext();
  if (auto subView = base.getDefiningOp<memref::SubViewOp>()) {
    if (!subView.hasUnitStride())
      return false;
    baseMemref = cast<MemrefValue>(subView.getSource());
    offsets = llvm::to_vector(subView.getMixedOffsets());
    droppedDims = subView.getDroppedDims();
    hasSubview = true;
  } else {
    baseMemref = dyn_cast<MemrefValue>(base);
    if (!baseMemref)
      return false;
  }

  auto loadIndices = loadOp.getIndices();
  unsigned baseRank = baseMemref.getType().getRank();
  if ((loadOp.getMemref() != baseMemref) || (loadIndices.size() != baseRank))
    return false;

  unsigned writeRank = writeIndices.size();
  if ((!hasSubview && writeRank != baseRank) ||
      (hasSubview && offsets.size() != baseRank) ||
      (vectorDimForWriteDim.size() != writeRank))
    return false;

  auto zeroAttr = IntegerAttr::get(IndexType::get(ctx), 0);
  unsigned writeMemrefDim = 0;
  for (unsigned baseDim : llvm::seq(baseRank)) {
    bool wasDropped = (hasSubview && droppedDims.test(baseDim));
    int64_t vectorDim = !wasDropped ? vectorDimForWriteDim[writeMemrefDim] : -1;
    int64_t extent = 1;
    if (vectorDim >= 0) {
      int64_t dimSize = vecTy.getDimSize(vectorDim);
      if (dimSize == ShapedType::kDynamic)
        return false;
      extent = dimSize;
    }
    Value writeIndex = !wasDropped ? writeIndices[writeMemrefDim] : Value();
    OpFoldResult offset =
        hasSubview ? offsets[baseDim] : OpFoldResult(zeroAttr);
    if (!loadIndexWithinWriteRange(loadIndices[baseDim], offset, writeIndex,
                                   extent, ivsMap))
      return false;
    if (!wasDropped)
      ++writeMemrefDim;
  }

  return true;
}

/// Recognize scalar memref.load of an element produced by a
/// vector.transfer_write
static bool loadMatchesVectorWrite(memref::LoadOp loadOp,
                                   vector::TransferWriteOp writeOp,
                                   const IRMapping &ivsMap) {
  auto vecTy = dyn_cast<VectorType>(writeOp.getVector().getType());
  if (!vecTy)
    return false;

  unsigned writeRank = writeOp.getIndices().size();
  AffineMap permutationMap = writeOp.getPermutationMap();
  if (!permutationMap.isProjectedPermutation() ||
      permutationMap.getNumResults() != vecTy.getRank() ||
      permutationMap.getNumDims() != writeRank)
    return false;

  SmallVector<int64_t> vectorDimForWriteDim(writeRank, -1);
  for (unsigned vecDim = 0; vecDim < permutationMap.getNumResults(); ++vecDim) {
    auto dimExpr = dyn_cast<AffineDimExpr>(permutationMap.getResult(vecDim));
    if (!dimExpr)
      return false;
    unsigned writeDim = dimExpr.getPosition();
    if (writeDim >= writeRank || vectorDimForWriteDim[writeDim] != -1)
      return false;
    vectorDimForWriteDim[writeDim] = vecDim;
  }

  return isLoadOnWrittenVector(loadOp, writeOp.getBase(), writeOp.getIndices(),
                               vecTy, vectorDimForWriteDim, ivsMap);
}

/// Recognize scalar memref.load of an element produced by a vector.store
static bool loadMatchesVectorStore(memref::LoadOp loadOp,
                                   vector::StoreOp storeOp,
                                   const IRMapping &ivsMap) {
  auto vecTy = dyn_cast<VectorType>(storeOp.getValueToStore().getType());
  if (!vecTy)
    return false;

  unsigned writeRank = storeOp.getIndices().size();
  if (vecTy.getRank() > writeRank)
    return false;

  SmallVector<int64_t> vectorDimForWriteDim(writeRank, -1);
  unsigned vecRank = vecTy.getRank();
  for (unsigned i = 0; i < vecRank; ++i) {
    unsigned writeDim = writeRank - vecRank + i;
    vectorDimForWriteDim[writeDim] = i;
  }

  return isLoadOnWrittenVector(loadOp, storeOp.getBase(), storeOp.getIndices(),
                               vecTy, vectorDimForWriteDim, ivsMap);
}

/// Check if both operations access the same positions of the same
/// buffer, but one of the two does it through a rank-reducing full subview of
/// the buffer (the other's base). EXAMPLE:
///  memref.store %a, %buf[%c0, %i, %j] : memref<1x2x2xf32>
///  %alias = memref.subview %buf[0, 0, 0][1, 2, 2][1, 1, 1]: memref<1x2x2xf32>
///                           to memref<2x2xf32>
///  %val = memref.load %alias[%i, %j] : memref<2x2xf32>
template <typename OpTy1, typename OpTy2>
static bool opsAccessSameIndicesViaRankReducingSubview(
    OpTy1 op1, OpTy2 op2, const IRMapping &firstToSecondPloopIVsMap,
    OpBuilder &b) {
  auto base1 = cast<MemrefValue>(getBaseMemref(op1));
  auto base2 = cast<MemrefValue>(getBaseMemref(op2));
  if (!base1 || !base2)
    return false;

  auto accessThroughTrivialSubviewIsSame =
      [&b](memref::SubViewOp subView, ValueRange subViewAccess,
           ValueRange sourceAccess, const IRMapping &ivsMap) -> bool {
    SmallVector<Value> resolvedSubviewAccess;
    LogicalResult resolved = resolveSourceIndicesRankReducingSubview(
        subView.getLoc(), b, subView, subViewAccess, resolvedSubviewAccess);
    if (failed(resolved) ||
        (resolvedSubviewAccess.size() != sourceAccess.size()))
      return false;
    for (auto [dimIdx, resolvedIndex] :
         llvm::enumerate(resolvedSubviewAccess)) {
      if (!matchPattern(resolvedIndex, m_Zero()) &&
          !valsAreEquivalent(resolvedIndex, sourceAccess[dimIdx], ivsMap))
        return false;
    }
    return true;
  };

  // Case 1: op1 uses a subview of op2's base.
  if (auto subView = base1.template getDefiningOp<memref::SubViewOp>();
      subView &&
      memref::isSameViewOrTrivialAlias(
          base2, cast<MemrefValue>(subView.getSource())) &&
      accessThroughTrivialSubviewIsSame(subView, op1.getIndices(),
                                        op2.getIndices(),
                                        firstToSecondPloopIVsMap))
    return true;

  // Case 2: op2 uses a subview of op1's base.
  if (auto subView = base2.template getDefiningOp<memref::SubViewOp>();
      subView &&
      memref::isSameViewOrTrivialAlias(
          base1, cast<MemrefValue>(subView.getSource())) &&
      accessThroughTrivialSubviewIsSame(subView, op2.getIndices(),
                                        op1.getIndices(),
                                        firstToSecondPloopIVsMap))
    return true;

  return false;
}

/// Check if both memory read/write operations access the same indices
/// (considering also the mapping of induction variables from the first to the
/// second parallel loop).
template <typename OpTy1, typename OpTy2>
static bool opsAccessSameIndices(OpTy1 op1, OpTy2 op2,
                                 const IRMapping &loopsIVsMap, OpBuilder &b) {
  auto indices1 = op1.getIndices();
  auto indices2 = op2.getIndices();
  if (indices1.size() != indices2.size())
    return opsAccessSameIndicesViaRankReducingSubview(op1, op2, loopsIVsMap, b);
  for (auto [idx1, idx2] : llvm::zip(indices1, indices2)) {
    if (!valsAreEquivalent(idx1, idx2, loopsIVsMap))
      return false;
  }
  return true;
}

/// Check if the loadOp reads from the same memory location (same buffer,
/// same indices and same properties) as written by the storeOp.
static bool
loadsFromSameMemoryLocationWrittenBy(Operation *loadOp, Operation *storeOp,
                                     const IRMapping &firstToSecondPloopIVsMap,
                                     OpBuilder &b) {
  if (!loadOp || !storeOp)
    return false;
  // Support only these memory-reading ops for now
  if (!isa<memref::LoadOp, vector::TransferReadOp, vector::LoadOp>(loadOp))
    return false;
  bool accessSameMemory =
      llvm::TypeSwitch<Operation *, bool>(loadOp)
          .Case([&](memref::LoadOp memLoadOp) {
            if (auto memStoreOp = dyn_cast<memref::StoreOp>(storeOp))
              return opsAccessSameIndices(memLoadOp, memStoreOp,
                                          firstToSecondPloopIVsMap, b);
            if (auto vecWriteOp = dyn_cast<vector::TransferWriteOp>(storeOp))
              return loadMatchesVectorWrite(memLoadOp, vecWriteOp,
                                            firstToSecondPloopIVsMap);
            if (auto vecStoreOp = dyn_cast<vector::StoreOp>(storeOp))
              return loadMatchesVectorStore(memLoadOp, vecStoreOp,
                                            firstToSecondPloopIVsMap);
            return false;
          })
          .Case([&](vector::TransferReadOp vecReadOp) {
            auto vecWriteOp = dyn_cast<vector::TransferWriteOp>(storeOp);
            if (!vecWriteOp)
              return false;
            return opsAccessSameIndices(vecReadOp, vecWriteOp,
                                        firstToSecondPloopIVsMap, b) &&
                   (vecReadOp.getMask() == vecWriteOp.getMask()) &&
                   (vecReadOp.getInBounds() == vecWriteOp.getInBounds());
          })
          .Case([&](vector::LoadOp vecLoadOp) {
            auto vecStoreOp = dyn_cast<vector::StoreOp>(storeOp);
            if (!vecStoreOp)
              return false;
            return opsAccessSameIndices(vecLoadOp, vecStoreOp,
                                        firstToSecondPloopIVsMap, b) &&
                   (vecLoadOp.getAlignment() == vecStoreOp.getAlignment());
          })
          .Default([](Operation *) { return false; });
  return accessSameMemory;
}

static Value getStoreOpTargetBuffer(Operation *op) {
  return llvm::TypeSwitch<Operation *, Value>(op)
      .Case([&](memref::StoreOp storeOp) { return storeOp.getMemRef(); })
      .Case([&](vector::TransferWriteOp writeOp) { return writeOp.getBase(); })
      .Case([&](vector::StoreOp vecStoreOp) { return vecStoreOp.getBase(); })
      .Default([](Operation *) { return Value(); });
}

/// To be called when `mayAlias(val1, val2)` is true. Check if the potential
/// aliasing between the loadOp and storeOp can be resolved by analyzing their
/// access patterns.
static bool canResolveAlias(Operation *loadOp, Operation *storeOp,
                            const IRMapping &loopsIVsMap) {
  if (auto transfWriteOp = dyn_cast<vector::TransferWriteOp>(storeOp);
      transfWriteOp && isa<memref::LoadOp>(loadOp))
    return loadMatchesVectorWrite(cast<memref::LoadOp>(loadOp), transfWriteOp,
                                  loopsIVsMap);
  if (auto vecStoreOp = dyn_cast<vector::StoreOp>(storeOp);
      vecStoreOp && isa<memref::LoadOp>(loadOp))
    return loadMatchesVectorStore(cast<memref::LoadOp>(loadOp), vecStoreOp,
                                  loopsIVsMap);
  return false;
}

/// Check that the parallel loops have no mixed access to the same buffers.
/// Return `true` if the second parallel loop does not read or write the buffers
/// written by the first loop using different indices.
static bool haveNoDataDependenciesExceptSameIndex(
    ParallelOp firstPloop, ParallelOp secondPloop,
    const IRMapping &firstToSecondPloopIndices,
    llvm::function_ref<bool(Value, Value)> mayAlias, OpBuilder &b) {
  // Map buffers to their store/write ops in the firstPloop
  DenseMap<Value, SmallVector<Operation *>> bufferStoresInFirstPloop;
  // Record all the memory buffers used in store/write ops found in firstPloop
  llvm::SmallSetVector<Value, 4> buffersWrittenInFirstPloop;

  auto collectStoreOpsInWalk = [&](Operation *op) {
    auto memOpInterf = dyn_cast_if_present<MemoryEffectOpInterface>(op);
    // Ignore ops that don't write to memory
    if (!memOpInterf || (!memOpInterf.hasEffect<MemoryEffects::Write>() &&
                         !memOpInterf.hasEffect<MemoryEffects::Free>()))
      return WalkResult::advance();

    // Only these memory-writing ops are supported for now:
    // memref.store, vector.transfer_write, vector.store
    Value storeOpBase = getStoreOpTargetBuffer(op);
    if (!storeOpBase)
      return WalkResult::interrupt();

    // Expect the base operand to be a Memref
    MemrefValue storeOpBaseMemref = dyn_cast<MemrefValue>(storeOpBase);
    if (!storeOpBaseMemref)
      return WalkResult::interrupt();
    // Get the original memref buffer, skipping full view-like ops
    Value buffer = memref::skipFullyAliasingOperations(storeOpBaseMemref);
    bufferStoresInFirstPloop[buffer].push_back(op);
    buffersWrittenInFirstPloop.insert(buffer);
    return WalkResult::advance();
  };

  // Walk the first parallel loop to collect all store/write ops and their
  // target buffers
  if (firstPloop.getBody()->walk(collectStoreOpsInWalk).wasInterrupted())
    return false;

  // Check that this load/read op encountered while walking the second parallel
  // loop does not have incompatible data dependencies with the store/write ops
  // collected from the first parallel loop: the loops can be fused only if in
  // the 2nd loop there are no loads/stores from/to the buffers written in the
  // 1st loop, except when on the same exact memory location (same indices) as
  // written in the 1st loop.
  auto checkLoadInWalkHasNoIncompatibleDataDeps = [&](Operation *loadOp) {
    auto memOpInterf = dyn_cast_if_present<MemoryEffectOpInterface>(loadOp);
    // To be conservative, we should stop on ops that don't advertise their
    // memory effects. However, many ops don't implement MemoryEffectOpInterface
    // yet, so for now we just skip them.
    // TODO: once more ops add MemoryEffectOpInterface, interrupt the walk here.
    if (!memOpInterf &&
        !loadOp->hasTrait<mlir::OpTrait::HasRecursiveMemoryEffects>())
      return WalkResult::advance();
    // Ignore ops that don't read from memory, and wrapping ops that have nested
    // memory effects (e.g. loops, conditionals) as they will be analyzed when
    // visiting their nested ops.
    if ((!memOpInterf &&
         loadOp->hasTrait<mlir::OpTrait::HasRecursiveMemoryEffects>()) ||
        (memOpInterf && !memOpInterf.hasEffect<MemoryEffects::Read>()))
      return WalkResult::advance();
    // Support only these memory-reading ops for now
    if (!isa<memref::LoadOp, vector::TransferReadOp, vector::LoadOp>(loadOp) ||
        !isa<MemrefValue>(loadOp->getOperand(0)))
      return WalkResult::interrupt();

    MemrefValue loadOpBase = cast<MemrefValue>(loadOp->getOperand(0));
    MemrefValue loadedOrigBuf = memref::skipFullyAliasingOperations(loadOpBase);

    for (Value storedMem : buffersWrittenInFirstPloop)
      if ((storedMem != loadedOrigBuf) && mayAlias(storedMem, loadedOrigBuf) &&
          !llvm::all_of(bufferStoresInFirstPloop[storedMem],
                        [&](Operation *storeOp) {
                          return canResolveAlias(loadOp, storeOp,
                                                 firstToSecondPloopIndices);
                        })) {
        return WalkResult::interrupt();
      }

    auto writeOpsIt = bufferStoresInFirstPloop.find(loadedOrigBuf);
    if (writeOpsIt == bufferStoresInFirstPloop.end())
      return WalkResult::advance();
    // Store/write ops to this buffer in the firstPloop
    SmallVector<mlir::Operation *> &writeOps = writeOpsIt->second;

    // If the first loop has no writes to this buffer, continue
    if (writeOps.empty())
      return WalkResult::advance();

    Operation *writeOp = writeOps.front();

    // In the first parallel loop, multiple writes to the same memref are
    // allowed only on the same memory location
    if (!llvm::all_of(writeOps, [&](Operation *otherWriteOp) {
          return opsWriteSameMemLocation(writeOp, otherWriteOp);
        })) {
      return WalkResult::interrupt();
    }

    // Check that the load in secondPloop reads from the same memory location as
    // written by the corresponding store in firstPloop
    if (!loadsFromSameMemoryLocationWrittenBy(loadOp, writeOp,
                                              firstToSecondPloopIndices, b)) {
      return WalkResult::interrupt();
    }

    return WalkResult::advance();
  };

  // Walk the second parallel loop to check load/read ops against the stores
  // collected from the first parallel loop.
  return !secondPloop.getBody()
              ->walk(checkLoadInWalkHasNoIncompatibleDataDeps)
              .wasInterrupted();
}

/// Check that in each loop there are no read ops on the buffers written
/// by the other loop, except when reading from the same exact memory location
/// (same indices) as written in the other loop.
static bool
noIncompatibleDataDependencies(ParallelOp firstPloop, ParallelOp secondPloop,
                               const IRMapping &firstToSecondPloopIndices,
                               llvm::function_ref<bool(Value, Value)> mayAlias,
                               OpBuilder &b) {
  if (!haveNoDataDependenciesExceptSameIndex(
          firstPloop, secondPloop, firstToSecondPloopIndices, mayAlias, b))
    return false;

  IRMapping secondToFirstPloopIndices;
  secondToFirstPloopIndices.map(secondPloop.getBody()->getArguments(),
                                firstPloop.getBody()->getArguments());
  return haveNoDataDependenciesExceptSameIndex(
      secondPloop, firstPloop, secondToFirstPloopIndices, mayAlias, b);
}

/// Check if fusion of the two parallel loops is legal:
/// i.e. no nested parallel loops, equal iteration spaces,
/// and no incompatible data dependencies between the loops.
static bool isFusionLegal(ParallelOp firstPloop, ParallelOp secondPloop,
                          const IRMapping &firstToSecondPloopIndices,
                          llvm::function_ref<bool(Value, Value)> mayAlias,
                          OpBuilder &b) {
  if (hasNestedParallelOp(firstPloop) || hasNestedParallelOp(secondPloop) ||
      !equalIterationSpaces(firstPloop, secondPloop) ||
      !noIncompatibleDataDependencies(firstPloop, secondPloop,
                                      firstToSecondPloopIndices, mayAlias, b))
    return false;

  // We are fusing first loop into second, make sure there are no users of the
  // first loop results between loops.
  DominanceInfo dom;
  for (Operation *user : firstPloop->getUsers()) {
    if (!dom.properlyDominates(secondPloop, user, /*enclosingOpOk*/ false))
      return false;
  }
  return true;
}

// Returns new parallel loop where two loops matching indices param are
// interchanged
static std::optional<ParallelOp>
interchangeLoops(OpBuilder &builder, ParallelOp &loop,
                 const ArrayRef<int64_t> &indices) {
  assert(loop.getNumLoops() == indices.size());
  if (loop.getNumLoops() < 2)
    return std::nullopt;

  // Replace the parallel loop with the same parallel loop.
  builder.setInsertionPoint(loop);
  SmallVector<Value> newLB =
      applyPermutation(SmallVector<Value>(loop.getLowerBound()), indices);
  SmallVector<Value> newUB =
      applyPermutation(SmallVector<Value>(loop.getUpperBound()), indices);
  SmallVector<Value> newStep =
      applyPermutation(SmallVector<Value>(loop.getStep()), indices);
  auto newOp =
      ParallelOp::create(builder, loop.getLoc(), newLB, newUB, newStep,
                         loop.getInitVals(), nullptr, loop.getUnsignedCmp());
  auto ivs = loop.getInductionVars();
  SmallVector<Value> newIvs = applyPermutation(
      newOp.getInductionVars(), invertPermutationVector(indices));
  IRMapping mapping;
  for (auto [iv, riv] : llvm::zip(ivs, newIvs)) {
    mapping.map(iv, riv);
  }

  // Copy parallel loop body
  auto b = OpBuilder::atBlockBegin(newOp.getBody());
  for (auto &o : loop.getNumReductions()
                     ? loop.getBodyRegion().front()
                     : loop.getBodyRegion().front().without_terminator()) {
    b.clone(o, mapping);
  }
  return newOp;
}

struct LoopIV {
  Value lBound, uBound, step;
  bool operator!=(LoopIV const &other) const { return !(*this == other); }
  bool operator==(LoopIV const &other) const {
    return lBound == other.lBound && uBound == other.uBound &&
           step == other.step;
  }
};

template <>
struct llvm::DenseMapInfo<LoopIV> {
  static inline bool isEqual(const LoopIV &lhs, const LoopIV &rhs) {
    return (lhs == rhs);
  }

  static inline unsigned getHashValue(const LoopIV &val) {
    return llvm::hash_combine(
        DenseMapInfo<mlir::Value>::getHashValue(val.lBound),
        DenseMapInfo<mlir::Value>::getHashValue(val.uBound),
        DenseMapInfo<mlir::Value>::getHashValue(val.step));
  }
};

// Returns vector of candidate permutation indices vectors,
// can be empty. Caps the number of extra candidate permutations
// explored to avoid combinatorial explosion. This makes the search
// intentionally incomplete.
static SmallVector<SmallVector<int64_t>>
computeCandidateInterchangePermutations(ParallelOp &firstPloop,
                                        ParallelOp &secondPloop,
                                        int permBudget = 120) {
  // Check preconditions
  if (firstPloop.getNumLoops() < 2 ||
      firstPloop.getNumLoops() != secondPloop.getNumLoops())
    return {};

  SmallVector<LoopIV> firstIVs(firstPloop.getNumLoops());
  SmallVector<LoopIV> secondIVs(secondPloop.getNumLoops());
  llvm::SmallSetVector<LoopIV, 6> unique;
  for (unsigned index : llvm::seq(firstPloop.getNumLoops())) {
    firstIVs[index].lBound = firstPloop.getLowerBound()[index];
    firstIVs[index].uBound = firstPloop.getUpperBound()[index];
    firstIVs[index].step = firstPloop.getStep()[index];
    secondIVs[index].lBound = secondPloop.getLowerBound()[index];
    secondIVs[index].uBound = secondPloop.getUpperBound()[index];
    secondIVs[index].step = secondPloop.getStep()[index];
    unique.insert(firstIVs[index]);
  }

  SmallVector<bool> diffIVs(firstPloop.getNumLoops());
  llvm::transform(
      llvm::zip(firstIVs, secondIVs), diffIVs.begin(),
      [](auto const &pair) { return std::get<0>(pair) != std::get<1>(pair); });

  SmallVector<int64_t> indices;
  for (auto [idx, val] : enumerate(diffIVs))
    if (val)
      indices.push_back(idx);

  // Not a permutation shortcut
  if (indices.size() == 1)
    return {};

  // Initialize with identity permutations
  SmallVector<int64_t> basic(firstIVs.size());
  std::iota(basic.begin(), basic.end(), 0);

  if (indices.empty() && unique.size() == firstIVs.size())
    return {};

  if (indices.size() > 1) {
    // Determine whether the iteration space of the first loop is a permutation
    // of the second and collect remaps.
    SmallVector<int64_t> remaps;
    for (auto fIdx : indices) {
      for (auto sIdx : indices) {
        // can be remapped
        if (fIdx != sIdx && firstIVs[fIdx] == secondIVs[sIdx] &&
            remaps.end() == std::find(remaps.begin(), remaps.end(), sIdx)) {
          remaps.push_back(sIdx);
          break;
        }
      }
    }

    // Not a permutation
    if (indices.size() != remaps.size())
      return {};

    // compose permutation indices
    for (auto [from, to] : zip(indices, remaps)) {
      basic[from] = to;
    }

    LDBG() << "Collected basic permutations: "
           << llvm::interleaved_array(basic);

    // All axes are unique, no further permutatons needed
    if (unique.size() == firstIVs.size()) {
      return {basic};
    }
  }

  //
  // Permute equal axes
  assert(unique.size() != firstIVs.size() &&
         "Expected at least two equal axes");

  // Collect equal axes to groups
  SmallVector<SmallVector<int64_t>> extraResults{basic};
  SmallVector<SmallVector<int64_t>> groups;
  for (auto iv : unique) {
    SmallVector<int64_t> group;
    for (unsigned index : llvm::seq(firstIVs.size())) {
      if (firstIVs[index] == iv)
        group.push_back(index);
    }
    if (group.size() > 1)
      groups.push_back(std::move(group));
  }

  // Permute axes groups
  SmallVector<SmallVector<int64_t>> rmpdGroups(groups);
  bool repeat = true;
  while (repeat && permBudget) {
    repeat = false;
    for (auto const &[group, groupRemaps] : zip(groups, rmpdGroups)) {
      repeat |= std::next_permutation(groupRemaps.begin(), groupRemaps.end());
      if (repeat)
        break;
    }

    if (repeat) {
      SmallVector<int64_t> extra(basic);
      for (auto const &[group, groupRemaps] : zip(groups, rmpdGroups)) {
        for (auto [from, to] : zip(group, groupRemaps))
          extra[from] = basic[to];
      }
      if (basic != extra) {
        LDBG() << "Collected extra permutations: "
               << llvm::interleaved_array(extra);

        extraResults.push_back(std::move(extra));
        permBudget--;
      }
    }
  }

  return extraResults;
}

/// Prepend operations of firstPloop's body into secondPloop's body.
/// Update secondPloop with new loop.
static void applyLoopFusion(ParallelOp &firstPloop, ParallelOp &secondPloop,
                            OpBuilder &builder) {
  Block *block1 = firstPloop.getBody();
  Block *block2 = secondPloop.getBody();
  ValueRange inits1 = firstPloop.getInitVals();
  ValueRange inits2 = secondPloop.getInitVals();

  SmallVector<Value> newInitVars(inits1.begin(), inits1.end());
  newInitVars.append(inits2.begin(), inits2.end());

  IRRewriter b(builder);
  b.setInsertionPoint(secondPloop);
  auto newSecondPloop =
      ParallelOp::create(b, secondPloop.getLoc(), secondPloop.getLowerBound(),
                         secondPloop.getUpperBound(), secondPloop.getStep(),
                         newInitVars, nullptr, secondPloop.getUnsignedCmp());

  Block *newBlock = newSecondPloop.getBody();
  auto term1 = cast<ReduceOp>(block1->getTerminator());
  auto term2 = cast<ReduceOp>(block2->getTerminator());

  b.inlineBlockBefore(block2, newBlock, newBlock->begin(),
                      newBlock->getArguments());
  b.inlineBlockBefore(block1, newBlock, newBlock->begin(),
                      newBlock->getArguments());

  ValueRange results = newSecondPloop.getResults();
  if (!results.empty()) {
    b.setInsertionPointToEnd(newBlock);

    ValueRange reduceArgs1 = term1.getOperands();
    ValueRange reduceArgs2 = term2.getOperands();
    SmallVector<Value> newReduceArgs(reduceArgs1.begin(), reduceArgs1.end());
    newReduceArgs.append(reduceArgs2.begin(), reduceArgs2.end());

    auto newReduceOp = scf::ReduceOp::create(b, term2.getLoc(), newReduceArgs);

    for (auto &&[i, reg] : llvm::enumerate(llvm::concat<Region>(
             term1.getReductions(), term2.getReductions()))) {
      Block &oldRedBlock = reg.front();
      Block &newRedBlock = newReduceOp.getReductions()[i].front();
      b.inlineBlockBefore(&oldRedBlock, &newRedBlock, newRedBlock.begin(),
                          newRedBlock.getArguments());
    }

    firstPloop.replaceAllUsesWith(results.take_front(inits1.size()));
    secondPloop.replaceAllUsesWith(results.take_back(inits2.size()));
  }
  term1->erase();
  term2->erase();
  firstPloop.erase();
  secondPloop.erase();
  secondPloop = newSecondPloop;
}

/// Check fusion pre-conditions and call fusion if it is possible
static void fuseIfLegal(ParallelOp firstPloop, ParallelOp &secondPloop,
                        OpBuilder builder,
                        llvm::function_ref<bool(Value, Value)> mayAlias) {
  Block *block1 = firstPloop.getBody();
  Block *block2 = secondPloop.getBody();
  IRMapping firstToSecondPloopIndices;
  firstToSecondPloopIndices.map(block1->getArguments(), block2->getArguments());

  if (isFusionLegal(firstPloop, secondPloop, firstToSecondPloopIndices,
                    mayAlias, builder)) {
    applyLoopFusion(firstPloop, secondPloop, builder);
    return;
  }

  // If iteration space of the second parallel loop is a permutation of the
  // first one then interchange iteration space of the second parallel loop
  // and re-asses possibility of fusion.
  for (auto &perms :
       computeCandidateInterchangePermutations(firstPloop, secondPloop)) {
    OpBuilder::InsertionGuard guard(builder);
    LDBG() << "Applied permutation: " << llvm::interleaved_array(perms);

    auto newLoop = interchangeLoops(builder, secondPloop, perms);
    firstToSecondPloopIndices.clear();
    firstToSecondPloopIndices.map(block1->getArguments(),
                                  newLoop->getBody()->getArguments());
    if (!isFusionLegal(firstPloop, *newLoop, firstToSecondPloopIndices,
                       mayAlias, builder)) {
      LDBG() << "Rejected: " << newLoop;

      newLoop->erase();
      continue;
    }

    secondPloop.replaceAllUsesWith(newLoop->getResults());
    secondPloop->erase();
    secondPloop = *newLoop;
    applyLoopFusion(firstPloop, secondPloop, builder);
    break;
  }
}

void mlir::scf::naivelyFuseParallelOps(
    Region &region, llvm::function_ref<bool(Value, Value)> mayAlias) {
  OpBuilder b(region);
  // Consider every single block and attempt to fuse adjacent loops.
  SmallVector<SmallVector<ParallelOp>, 1> ploopChains;
  for (auto &block : region) {
    ploopChains.clear();
    ploopChains.push_back({});

    // Not using `walk()` to traverse only top-level parallel loops and also
    // make sure that there are no side-effecting ops between the parallel
    // loops.
    bool noSideEffects = true;
    for (auto &op : block) {
      if (auto ploop = dyn_cast<ParallelOp>(op)) {
        if (noSideEffects) {
          ploopChains.back().push_back(ploop);
        } else {
          ploopChains.push_back({ploop});
          noSideEffects = true;
        }
        continue;
      }
      // TODO: Handle region side effects properly.
      noSideEffects &= isMemoryEffectFree(&op) && op.getNumRegions() == 0;
    }
    for (MutableArrayRef<ParallelOp> ploops : ploopChains) {
      for (int i = 0, e = ploops.size(); i + 1 < e; ++i)
        fuseIfLegal(ploops[i], ploops[i + 1], b, mayAlias);
    }
  }
}

namespace {
struct ParallelLoopFusion
    : public impl::SCFParallelLoopFusionBase<ParallelLoopFusion> {
  void runOnOperation() override {
    auto &aa = getAnalysis<AliasAnalysis>();

    auto mayAlias = [&](Value val1, Value val2) -> bool {
      // If the memref is defined in one of the parallel loops body, careful
      // alias analysis is needed.
      // TODO: check if this is still needed as a separate check.
      auto val1Def = val1.getDefiningOp();
      auto val2Def = val2.getDefiningOp();
      auto val1Loop =
          val1Def ? val1Def->getParentOfType<ParallelOp>() : nullptr;
      auto val2Loop =
          val2Def ? val2Def->getParentOfType<ParallelOp>() : nullptr;
      if (val1Loop != val2Loop)
        return true;

      return !aa.alias(val1, val2).isNo();
    };

    getOperation()->walk([&](Operation *child) {
      for (Region &region : child->getRegions())
        naivelyFuseParallelOps(region, mayAlias);
    });
  }
};
} // namespace

std::unique_ptr<Pass> mlir::createParallelLoopFusionPass() {
  return std::make_unique<ParallelLoopFusion>();
}
