//===- MatmulOptimizer.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "polly/MatmulOptimizer.h"
#include "polly/DependenceInfo.h"
#include "polly/Options.h"
#include "polly/ScheduleTreeTransform.h"
#include "polly/ScopInfo.h"
#include "polly/Simplify.h"
#include "polly/Support/GICHelper.h"
#include "polly/Support/ISLTools.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
#include "isl/ctx.h"
#include "isl/schedule_node.h"
#include "isl/schedule_type.h"
#include "isl/union_map.h"
#include "isl/union_set.h"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <string>
#include <vector>

#include "polly/Support/PollyDebug.h"
#define DEBUG_TYPE "polly-opt-isl"

using namespace llvm;
using namespace polly;

namespace llvm {
class Value;
}

static cl::opt<int> LatencyVectorFma(
    "polly-target-latency-vector-fma",
    cl::desc("The minimal number of cycles between issuing two "
             "dependent consecutive vector fused multiply-add "
             "instructions."),
    cl::Hidden, cl::init(8), cl::cat(PollyCategory));

static cl::opt<int> ThroughputVectorFma(
    "polly-target-throughput-vector-fma",
    cl::desc("A throughput of the processor floating-point arithmetic units "
             "expressed in the number of vector fused multiply-add "
             "instructions per clock cycle."),
    cl::Hidden, cl::init(1), cl::cat(PollyCategory));

static cl::opt<int> FirstCacheLevelSize(
    "polly-target-1st-cache-level-size",
    cl::desc("The size of the first cache level specified in bytes."),
    cl::Hidden, cl::init(-1), cl::cat(PollyCategory));

static cl::opt<int> FirstCacheLevelDefaultSize(
    "polly-target-1st-cache-level-default-size",
    cl::desc("The default size of the first cache level specified in bytes"
             " (if not enough were provided by the TargetTransformInfo)."),
    cl::Hidden, cl::init(32768), cl::cat(PollyCategory));

static cl::opt<int> SecondCacheLevelSize(
    "polly-target-2nd-cache-level-size",
    cl::desc("The size of the second level specified in bytes."), cl::Hidden,
    cl::init(-1), cl::cat(PollyCategory));

static cl::opt<int> SecondCacheLevelDefaultSize(
    "polly-target-2nd-cache-level-default-size",
    cl::desc("The default size of the second cache level specified in bytes"
             " (if not enough were provided by the TargetTransformInfo)."),
    cl::Hidden, cl::init(262144), cl::cat(PollyCategory));

// This option, along with --polly-target-2nd-cache-level-associativity,
// --polly-target-1st-cache-level-size, and --polly-target-2st-cache-level-size
// represent the parameters of the target cache, which do not have typical
// values that can be used by default. However, to apply the pattern matching
// optimizations, we use the values of the parameters of Intel Core i7-3820
// SandyBridge in case the parameters are not specified or not provided by the
// TargetTransformInfo.
static cl::opt<int> FirstCacheLevelAssociativity(
    "polly-target-1st-cache-level-associativity",
    cl::desc("The associativity of the first cache level."), cl::Hidden,
    cl::init(-1), cl::cat(PollyCategory));

static cl::opt<int> FirstCacheLevelDefaultAssociativity(
    "polly-target-1st-cache-level-default-associativity",
    cl::desc("The default associativity of the first cache level"
             " (if not enough were provided by the TargetTransformInfo)."),
    cl::Hidden, cl::init(8), cl::cat(PollyCategory));

static cl::opt<int> SecondCacheLevelAssociativity(
    "polly-target-2nd-cache-level-associativity",
    cl::desc("The associativity of the second cache level."), cl::Hidden,
    cl::init(-1), cl::cat(PollyCategory));

static cl::opt<int> SecondCacheLevelDefaultAssociativity(
    "polly-target-2nd-cache-level-default-associativity",
    cl::desc("The default associativity of the second cache level"
             " (if not enough were provided by the TargetTransformInfo)."),
    cl::Hidden, cl::init(8), cl::cat(PollyCategory));

static cl::opt<int> VectorRegisterBitwidth(
    "polly-target-vector-register-bitwidth",
    cl::desc("The size in bits of a vector register (if not set, this "
             "information is taken from LLVM's target information."),
    cl::Hidden, cl::init(-1), cl::cat(PollyCategory));

static cl::opt<int> PollyPatternMatchingNcQuotient(
    "polly-pattern-matching-nc-quotient",
    cl::desc("Quotient that is obtained by dividing Nc, the parameter of the"
             "macro-kernel, by Nr, the parameter of the micro-kernel"),
    cl::Hidden, cl::init(256), cl::cat(PollyCategory));

static cl::opt<bool>
    PMBasedTCOpts("polly-tc-opt",
                  cl::desc("Perform optimizations of tensor contractions based "
                           "on pattern matching"),
                  cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<bool>
    PMBasedMMMOpts("polly-matmul-opt",
                   cl::desc("Perform optimizations of matrix multiplications "
                            "based on pattern matching"),
                   cl::init(true), cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<int> OptComputeOut(
    "polly-tc-dependences-computeout",
    cl::desc("Bound the dependence analysis by a maximal amount of "
             "computational steps (0 means no bound)"),
    cl::Hidden, cl::init(500000), cl::ZeroOrMore, cl::cat(PollyCategory));

namespace {
/// Parameters of the micro kernel.
///
/// Parameters, which determine sizes of rank-1 (i.e., outer product) update
/// used in the optimized matrix multiplication.
struct MicroKernelParamsTy {
  int Mr;
  int Nr;
};

/// Parameters of the macro kernel.
///
/// Parameters, which determine sizes of blocks of partitioned matrices
/// used in the optimized matrix multiplication.
struct MacroKernelParamsTy {
  int Mc;
  int Nc;
  int Kc;
};

/// Parameters of the matrix multiplication operands.
///
/// Parameters, which describe access relations that represent operands of the
/// matrix multiplication.
struct MatMulInfoTy {
  MemoryAccess *A = nullptr;
  MemoryAccess *B = nullptr;
  MemoryAccess *ReadFromC = nullptr;
  MemoryAccess *WriteToC = nullptr;
  int i = -1;
  int j = -1;
  int k = -1;
};

/// Parameters of the tensor contraction operands.
///
/// A general d-dimensional tensor T ∈ R ^ Nu0 x ... x Nud−1 can be defined
/// as the set of scalar elements indexed by the set of indices u0 ... ud,
///
/// T ≡ {Anu0...nud−1 ∈ R | (u0,...,ud−1) ∈ Nu0 x ... x Nud−1}.
///
/// Let A, B, and C be dA, dB, and dC-dimensional tensors, respectively.
/// Let the free and the contracted indices of the tensor A be grouped into
/// two bundles I = i0...ir−1 and P = p0...pt−1, respectively. Similarly,
/// the free and the contracted indices of B are grouped into bundles
/// J = j0..js−1 and P and the free indices of C are grouped into
/// bundles I and J.
///
/// Tensor contraction (TC) of tensors A, B into tensor C can be represented as
/// C(shuffle(I,J))=∑α·A(shuffle(I,P))·B(shuffle(P,J))+β·C(shuffle(I,J)),
/// where ∑ is a summation over all contracted indices of P,
/// α, β ∈ R, Npi is the length of the tensor dimension that corresponds
/// to the index pi, A(shuffle(I, P)), B(shuffle(P, J)), C(shuffle(I, J)) are
/// accesses to tensors A, B, C, respectively,
/// shuffle(I, J), shuffle(I, P), and shuffle(P, J) are permutations of
/// the enclosed indices.
///
/// Multiplication of C(shuffle(I,J)) by β can be moved into a different SCoP
/// statement by loop distribution, which is done by the isl scheduler.
//  If β is not equal to one, the optimization of TC of Polly requires
/// such a transformation.
///
/// TCInfoTy contains parameters, which describe access relations that represent
/// operands of the tensor contraction.
struct TCInfoTy {
  /// @{
  /// Memory accesses that represent reading from tensors, which are operands of
  /// the tensor contraction.
  MemoryAccess *A = nullptr;
  MemoryAccess *B = nullptr;
  /// @}

  /// @{
  /// Memory accesses that represent reading from and writing into the tensor,
  /// which contains the result of the tensor contraction.
  MemoryAccess *ReadFromC = nullptr;
  MemoryAccess *WriteToC = nullptr;
  /// @}

  /// @{
  /// Input dimensions of the schedule space, which represent free
  /// indices of tensors.
  SmallDenseSet<int> I;
  SmallDenseSet<int> J;
  /// @}

  /// Input dimension of the schedule space, which represents contracted
  /// indices of tensors.
  SmallDenseSet<int> P;

  /// @{
  /// Sizes of tensor dimensions for corresponding input dimensions of
  /// the schedule space. The size of the tensor dimension can be larger than
  /// the size of the corresponding input dimension of the schedule space.
  /// This does not correspond to a tensor contraction. However, such a pattern
  /// will be optimized by the transformation.
  SmallVector<int> DimensionSizes;
  SmallVector<int> ADimensions;
  SmallVector<int> BDimensions;
  SmallVector<int> CDimensions;
  /// @}

  /// @{
  /// Permutations of indices of I, J, and P, which describe operands of
  /// the tensor contraction and its result.
  SmallVector<int> OrderedI;
  SmallVector<int> OrderedJ;
  SmallVector<int> OrderedP;
  /// @}
};

/// Create an isl::union_set, which describes the option of the form
/// [isolate[] -> unroll[x]].
///
/// @param Ctx An isl::ctx, which is used to create the isl::union_set.
static isl::union_set getUnrollIsolatedSetOptions(isl::ctx Ctx) {
  isl::space Space = isl::space(Ctx, 0, 0, 1);
  isl::map UnrollIsolatedSetOption = isl::map::universe(Space);
  isl::id DimInId = isl::id::alloc(Ctx, "isolate", nullptr);
  isl::id DimOutId = isl::id::alloc(Ctx, "unroll", nullptr);
  UnrollIsolatedSetOption =
      UnrollIsolatedSetOption.set_tuple_id(isl::dim::in, DimInId);
  UnrollIsolatedSetOption =
      UnrollIsolatedSetOption.set_tuple_id(isl::dim::out, DimOutId);
  return UnrollIsolatedSetOption.wrap();
}

/// Permute the two dimensions of the isl map.
///
/// Permute @p DstPos and @p SrcPos dimensions of the isl map @p Map that
/// have type @p DimType.
///
/// @param Map     The isl map to be modified.
/// @param DimType The type of the dimensions.
/// @param DstPos  The first dimension.
/// @param SrcPos  The second dimension.
/// @return        The modified map.
static isl::map permuteDimensions(isl::map Map, isl::dim DimType,
                                  unsigned DstPos, unsigned SrcPos) {
  assert(DstPos < unsignedFromIslSize(Map.dim(DimType)) &&
         SrcPos < unsignedFromIslSize(Map.dim(DimType)));
  if (DstPos == SrcPos)
    return Map;
  isl::id DimId;
  if (Map.has_tuple_id(DimType))
    DimId = Map.get_tuple_id(DimType);
  auto FreeDim = DimType == isl::dim::in ? isl::dim::out : isl::dim::in;
  isl::id FreeDimId;
  if (Map.has_tuple_id(FreeDim))
    FreeDimId = Map.get_tuple_id(FreeDim);
  auto MaxDim = std::max(DstPos, SrcPos);
  auto MinDim = std::min(DstPos, SrcPos);
  Map = Map.move_dims(FreeDim, 0, DimType, MaxDim, 1);
  Map = Map.move_dims(FreeDim, 0, DimType, MinDim, 1);
  Map = Map.move_dims(DimType, MinDim, FreeDim, 1, 1);
  Map = Map.move_dims(DimType, MaxDim, FreeDim, 0, 1);
  if (!DimId.is_null())
    Map = Map.set_tuple_id(DimType, DimId);
  if (!FreeDimId.is_null())
    Map = Map.set_tuple_id(FreeDim, FreeDimId);
  return Map;
}

/// Check the form of the access relation.
///
/// Check that the access relation @p AccMap has the form M[i][j], where i
/// is a @p FirstPos and j is a @p SecondPos.
///
/// @param AccMap    The access relation to be checked.
/// @param FirstPos  The index of the input dimension that is mapped to
///                  the first output dimension.
/// @param SecondPos The index of the input dimension that is mapped to the
///                  second output dimension.
/// @return          True in case @p AccMap has the expected form and false,
///                  otherwise.
static bool isMatMulOperandAcc(isl::set Domain, isl::map AccMap, int &FirstPos,
                               int &SecondPos) {
  isl::space Space = AccMap.get_space();
  isl::map Universe = isl::map::universe(Space);

  if (unsignedFromIslSize(Space.dim(isl::dim::out)) != 2)
    return false;

  // MatMul has the form:
  // for (i = 0; i < N; i++)
  //   for (j = 0; j < M; j++)
  //     for (k = 0; k < P; k++)
  //       C[i, j] += A[i, k] * B[k, j]
  //
  // Permutation of three outer loops: 3! = 6 possibilities.
  int FirstDims[] = {0, 0, 1, 1, 2, 2};
  int SecondDims[] = {1, 2, 2, 0, 0, 1};
  for (int i = 0; i < 6; i += 1) {
    auto PossibleMatMul =
        Universe.equate(isl::dim::in, FirstDims[i], isl::dim::out, 0)
            .equate(isl::dim::in, SecondDims[i], isl::dim::out, 1);

    AccMap = AccMap.intersect_domain(Domain);
    PossibleMatMul = PossibleMatMul.intersect_domain(Domain);

    // If AccMap spans entire domain (Non-partial write),
    // compute FirstPos and SecondPos.
    // If AccMap != PossibleMatMul here (the two maps have been gisted at
    // this point), it means that the writes are not complete, or in other
    // words, it is a Partial write and Partial writes must be rejected.
    if (AccMap.is_equal(PossibleMatMul)) {
      if (FirstPos != -1 && FirstPos != FirstDims[i])
        continue;
      FirstPos = FirstDims[i];
      if (SecondPos != -1 && SecondPos != SecondDims[i])
        continue;
      SecondPos = SecondDims[i];
      return true;
    }
  }

  return false;
}

/// Does the memory access represent a non-scalar operand of the matrix
/// multiplication.
///
/// Check that the memory access @p MemAccess is the read access to a non-scalar
/// operand of the matrix multiplication or its result.
///
/// @param MemAccess The memory access to be checked.
/// @param MMI       Parameters of the matrix multiplication operands.
/// @return          True in case the memory access represents the read access
///                  to a non-scalar operand of the matrix multiplication and
///                  false, otherwise.
static bool isMatMulNonScalarReadAccess(MemoryAccess *MemAccess,
                                        MatMulInfoTy &MMI) {
  if (!MemAccess->isLatestArrayKind() || !MemAccess->isRead())
    return false;
  auto AccMap = MemAccess->getLatestAccessRelation();
  isl::set StmtDomain = MemAccess->getStatement()->getDomain();
  if (isMatMulOperandAcc(StmtDomain, AccMap, MMI.i, MMI.j) && !MMI.ReadFromC) {
    MMI.ReadFromC = MemAccess;
    return true;
  }
  if (isMatMulOperandAcc(StmtDomain, AccMap, MMI.i, MMI.k) && !MMI.A) {
    MMI.A = MemAccess;
    return true;
  }
  if (isMatMulOperandAcc(StmtDomain, AccMap, MMI.k, MMI.j) && !MMI.B) {
    MMI.B = MemAccess;
    return true;
  }
  return false;
}

/// Check accesses to operands of the matrix multiplication.
///
/// Check that accesses of the SCoP statement, which corresponds to
/// the partial schedule @p PartialSchedule, are scalar in terms of loops
/// containing the matrix multiplication, in case they do not represent
/// accesses to the non-scalar operands of the matrix multiplication or
/// its result.
///
/// @param  PartialSchedule The partial schedule of the SCoP statement.
/// @param  MMI             Parameters of the matrix multiplication operands.
/// @return                 True in case the corresponding SCoP statement
///                         represents matrix multiplication and false,
///                         otherwise.
static bool containsOnlyMatrMultAcc(isl::map PartialSchedule,
                                    MatMulInfoTy &MMI) {
  auto InputDimId = PartialSchedule.get_tuple_id(isl::dim::in);
  auto *Stmt = static_cast<ScopStmt *>(InputDimId.get_user());
  unsigned OutDimNum = unsignedFromIslSize(PartialSchedule.range_tuple_dim());
  assert(OutDimNum > 2 && "In case of the matrix multiplication the loop nest "
                          "and, consequently, the corresponding scheduling "
                          "functions have at least three dimensions.");
  auto MapI =
      permuteDimensions(PartialSchedule, isl::dim::out, MMI.i, OutDimNum - 1);
  auto MapJ =
      permuteDimensions(PartialSchedule, isl::dim::out, MMI.j, OutDimNum - 1);
  auto MapK =
      permuteDimensions(PartialSchedule, isl::dim::out, MMI.k, OutDimNum - 1);

  auto Accesses = getAccessesInOrder(*Stmt);
  for (auto *MemA = Accesses.begin(); MemA != Accesses.end() - 1; MemA++) {
    auto *MemAccessPtr = *MemA;
    if (MemAccessPtr->isLatestArrayKind() && MemAccessPtr != MMI.WriteToC &&
        !isMatMulNonScalarReadAccess(MemAccessPtr, MMI) &&
        !(MemAccessPtr->isStrideZero(MapI) &&
          MemAccessPtr->isStrideZero(MapJ) && MemAccessPtr->isStrideZero(MapK)))
      return false;
  }
  return true;
}

/// Check for dependencies corresponding to the matrix multiplication.
///
/// Check that there is only true dependence of the form
/// S(..., k, ...) -> S(..., k + 1, …), where S is the SCoP statement
/// represented by @p Schedule and k is @p Pos. Such a dependence corresponds
/// to the dependency produced by the matrix multiplication.
///
/// @param  Schedule The schedule of the SCoP statement.
/// @param  D The SCoP dependencies.
/// @param  Pos The parameter to describe an acceptable true dependence.
///             In case it has a negative value, try to determine its
///             acceptable value.
/// @return True in case dependencies correspond to the matrix multiplication
///         and false, otherwise.
static bool containsOnlyMatMulDep(isl::map Schedule, const Dependences *D,
                                  int &Pos) {
  isl::union_map Dep = D->getDependences(Dependences::TYPE_RAW);
  isl::union_map Red = D->getDependences(Dependences::TYPE_RED);
  if (!Red.is_null())
    Dep = Dep.unite(Red);
  auto DomainSpace = Schedule.get_space().domain();
  auto Space = DomainSpace.map_from_domain_and_range(DomainSpace);
  auto Deltas = Dep.extract_map(Space).deltas();
  int DeltasDimNum = unsignedFromIslSize(Deltas.dim(isl::dim::set));
  for (int i = 0; i < DeltasDimNum; i++) {
    auto Val = Deltas.plain_get_val_if_fixed(isl::dim::set, i);
    Pos = Pos < 0 && Val.is_one() ? i : Pos;
    if (Val.is_nan() || !(Val.is_zero() || (i == Pos && Val.is_one())))
      return false;
  }
  if (DeltasDimNum == 0 || Pos < 0)
    return false;
  return true;
}

/// Check if the SCoP statement could probably be optimized with analytical
/// modeling.
///
/// containsMatrMult tries to determine whether the following conditions
/// are true:
/// 1. The last memory access modeling an array, MA1, represents writing to
///    memory and has the form S(..., i1, ..., i2, ...) -> M(i1, i2) or
///    S(..., i2, ..., i1, ...) -> M(i1, i2), where S is the SCoP statement
///    under consideration.
/// 2. There is only one loop-carried true dependency, and it has the
///    form S(..., i3, ...) -> S(..., i3 + 1, ...), and there are no
///    loop-carried or anti dependencies.
/// 3. SCoP contains three access relations, MA2, MA3, and MA4 that represent
///    reading from memory and have the form S(..., i3, ...) -> M(i1, i3),
///    S(..., i3, ...) -> M(i3, i2), S(...) -> M(i1, i2), respectively,
///    and all memory accesses of the SCoP that are different from MA1, MA2,
///    MA3, and MA4 have stride 0, if the innermost loop is exchanged with any
///    of loops i1, i2 and i3.
///
/// @param PartialSchedule The PartialSchedule that contains a SCoP statement
///        to check.
/// @D     The SCoP dependencies.
/// @MMI   Parameters of the matrix multiplication operands.
static bool containsMatrMult(isl::map PartialSchedule, const Dependences *D,
                             MatMulInfoTy &MMI) {
  auto InputDimsId = PartialSchedule.get_tuple_id(isl::dim::in);
  auto *Stmt = static_cast<ScopStmt *>(InputDimsId.get_user());
  if (Stmt->size() <= 1)
    return false;

  auto Accesses = getAccessesInOrder(*Stmt);
  for (auto *MemA = Accesses.end() - 1; MemA != Accesses.begin(); MemA--) {
    auto *MemAccessPtr = *MemA;
    if (!MemAccessPtr->isLatestArrayKind())
      continue;
    if (!MemAccessPtr->isWrite())
      return false;
    auto AccMap = MemAccessPtr->getLatestAccessRelation();
    if (!isMatMulOperandAcc(Stmt->getDomain(), AccMap, MMI.i, MMI.j))
      return false;
    MMI.WriteToC = MemAccessPtr;
    break;
  }

  if (!containsOnlyMatMulDep(PartialSchedule, D, MMI.k))
    return false;

  if (!MMI.WriteToC || !containsOnlyMatrMultAcc(PartialSchedule, MMI))
    return false;

  if (!MMI.A || !MMI.B || !MMI.ReadFromC)
    return false;
  return true;
}

/// Permute two dimensions of the band node.
///
/// Permute FirstDim and SecondDim dimensions of the Node.
///
/// @param Node The band node to be modified.
/// @param FirstDim The first dimension to be permuted.
/// @param SecondDim The second dimension to be permuted.
static isl::schedule_node permuteBandNodeDimensions(isl::schedule_node Node,
                                                    unsigned FirstDim,
                                                    unsigned SecondDim) {
  assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band &&
         (unsigned)isl_schedule_node_band_n_member(Node.get()) >
             std::max(FirstDim, SecondDim));
  auto PartialSchedule =
      isl::manage(isl_schedule_node_band_get_partial_schedule(Node.get()));
  auto PartialScheduleFirstDim = PartialSchedule.at(FirstDim);
  auto PartialScheduleSecondDim = PartialSchedule.at(SecondDim);
  PartialSchedule =
      PartialSchedule.set_union_pw_aff(SecondDim, PartialScheduleFirstDim);
  PartialSchedule =
      PartialSchedule.set_union_pw_aff(FirstDim, PartialScheduleSecondDim);
  Node = isl::manage(isl_schedule_node_delete(Node.release()));
  return Node.insert_partial_schedule(PartialSchedule);
}

static isl::schedule_node
createMicroKernel(isl::schedule_node Node,
                  MicroKernelParamsTy MicroKernelParams) {
  Node = applyRegisterTiling(Node, {MicroKernelParams.Mr, MicroKernelParams.Nr},
                             1);
  Node = Node.parent().parent();
  return permuteBandNodeDimensions(Node, 0, 1).child(0).child(0);
}

/// Create the BLIS macro-kernel.
///
/// We create the BLIS macro-kernel by applying a combination of tiling
/// of dimensions of the band node and interchanging of two innermost
/// modified dimensions. The values of MacroKernelParams's fields are used
/// as tile sizes.
///
/// @param Node The schedule node to be modified.
/// @param MacroKernelParams Parameters of the macro kernel
///                          to be used as tile sizes.
static isl::schedule_node
createMacroKernel(isl::schedule_node Node,
                  MacroKernelParamsTy MacroKernelParams) {
  assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
  if (MacroKernelParams.Mc == 1 && MacroKernelParams.Nc == 1 &&
      MacroKernelParams.Kc == 1)
    return Node;
  int DimOutNum = isl_schedule_node_band_n_member(Node.get());
  std::vector<int> TileSizes(DimOutNum, 1);
  TileSizes[DimOutNum - 3] = MacroKernelParams.Mc;
  TileSizes[DimOutNum - 2] = MacroKernelParams.Nc;
  TileSizes[DimOutNum - 1] = MacroKernelParams.Kc;
  Node = tileNode(Node, "1st level tiling", TileSizes, 1);
  Node = Node.parent().parent();
  Node = permuteBandNodeDimensions(Node, DimOutNum - 2, DimOutNum - 1);
  Node = permuteBandNodeDimensions(Node, DimOutNum - 3, DimOutNum - 1);

  return Node.child(0).child(0);
}

/// Get the size of the widest type of the matrix multiplication operands
/// in bytes, including alignment padding.
///
/// @param MMI Parameters of the matrix multiplication operands.
/// @return The size of the widest type of the matrix multiplication operands
///         in bytes, including alignment padding.
static uint64_t getMatMulAlignTypeSize(const MatMulInfoTy &MMI) {
  auto *S = MMI.A->getStatement()->getParent();
  auto &DL = S->getFunction().getParent()->getDataLayout();
  auto ElementSizeA = DL.getTypeAllocSize(MMI.A->getElementType());
  auto ElementSizeB = DL.getTypeAllocSize(MMI.B->getElementType());
  auto ElementSizeC = DL.getTypeAllocSize(MMI.WriteToC->getElementType());
  return std::max({ElementSizeA, ElementSizeB, ElementSizeC});
}

/// Get the size of the widest type of the matrix multiplication operands
/// in bits.
///
/// @param MMI Parameters of the matrix multiplication operands.
/// @return The size of the widest type of the matrix multiplication operands
///         in bits.
static uint64_t getMatMulTypeSize(const MatMulInfoTy &MMI) {
  auto *S = MMI.A->getStatement()->getParent();
  auto &DL = S->getFunction().getParent()->getDataLayout();
  auto ElementSizeA = DL.getTypeSizeInBits(MMI.A->getElementType());
  auto ElementSizeB = DL.getTypeSizeInBits(MMI.B->getElementType());
  auto ElementSizeC = DL.getTypeSizeInBits(MMI.WriteToC->getElementType());
  return std::max({ElementSizeA, ElementSizeB, ElementSizeC});
}

/// Get parameters of the BLIS micro kernel.
///
/// We choose the Mr and Nr parameters of the micro kernel to be large enough
/// such that no stalls caused by the combination of latencies and dependencies
/// are introduced during the updates of the resulting matrix of the matrix
/// multiplication. However, they should also be as small as possible to
/// release more registers for entries of multiplied matrices.
///
/// @param TTI Target Transform Info.
/// @param MMI Parameters of the matrix multiplication operands.
/// @return The structure of type MicroKernelParamsTy.
/// @see MicroKernelParamsTy
static MicroKernelParamsTy getMicroKernelParams(const TargetTransformInfo *TTI,
                                                const MatMulInfoTy &MMI) {
  assert(TTI && "The target transform info should be provided.");

  // Nvec - Number of double-precision floating-point numbers that can be hold
  // by a vector register. Use 2 by default.
  long RegisterBitwidth = VectorRegisterBitwidth;

  if (RegisterBitwidth == -1)
    RegisterBitwidth =
        TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector);
  auto ElementSize = getMatMulTypeSize(MMI);
  assert(ElementSize > 0 && "The element size of the matrix multiplication "
                            "operands should be greater than zero.");
  auto Nvec = RegisterBitwidth / ElementSize;
  if (Nvec == 0)
    Nvec = 2;
  int Nr = ceil(sqrt((double)(Nvec * LatencyVectorFma * ThroughputVectorFma)) /
                Nvec) *
           Nvec;
  int Mr = ceil((double)(Nvec * LatencyVectorFma * ThroughputVectorFma / Nr));
  return {Mr, Nr};
}

/// Determine parameters of the target cache.
///
/// @param TTI Target Transform Info.
static void getTargetCacheParameters(const llvm::TargetTransformInfo *TTI) {
  auto L1DCache = llvm::TargetTransformInfo::CacheLevel::L1D;
  auto L2DCache = llvm::TargetTransformInfo::CacheLevel::L2D;
  if (FirstCacheLevelSize == -1) {
    if (TTI->getCacheSize(L1DCache))
      FirstCacheLevelSize = TTI->getCacheSize(L1DCache).value();
    else
      FirstCacheLevelSize = static_cast<int>(FirstCacheLevelDefaultSize);
  }
  if (SecondCacheLevelSize == -1) {
    if (TTI->getCacheSize(L2DCache))
      SecondCacheLevelSize = TTI->getCacheSize(L2DCache).value();
    else
      SecondCacheLevelSize = static_cast<int>(SecondCacheLevelDefaultSize);
  }
  if (FirstCacheLevelAssociativity == -1) {
    if (TTI->getCacheAssociativity(L1DCache))
      FirstCacheLevelAssociativity =
          TTI->getCacheAssociativity(L1DCache).value();
    else
      FirstCacheLevelAssociativity =
          static_cast<int>(FirstCacheLevelDefaultAssociativity);
  }
  if (SecondCacheLevelAssociativity == -1) {
    if (TTI->getCacheAssociativity(L2DCache))
      SecondCacheLevelAssociativity =
          TTI->getCacheAssociativity(L2DCache).value();
    else
      SecondCacheLevelAssociativity =
          static_cast<int>(SecondCacheLevelDefaultAssociativity);
  }
}

/// Get parameters of the BLIS macro kernel.
///
/// During the computation of matrix multiplication, blocks of partitioned
/// matrices are mapped to different layers of the memory hierarchy.
/// To optimize data reuse, blocks should be ideally kept in cache between
/// iterations. Since parameters of the macro kernel determine sizes of these
/// blocks, there are upper and lower bounds on these parameters.
///
/// @param TTI Target Transform Info.
/// @param MicroKernelParams Parameters of the micro-kernel
///                          to be taken into account.
/// @param MMI Parameters of the matrix multiplication operands.
/// @return The structure of type MacroKernelParamsTy.
/// @see MacroKernelParamsTy
/// @see MicroKernelParamsTy
static MacroKernelParamsTy
getMacroKernelParams(const llvm::TargetTransformInfo *TTI,
                     const MicroKernelParamsTy &MicroKernelParams,
                     const MatMulInfoTy &MMI) {
  getTargetCacheParameters(TTI);
  // According to www.cs.utexas.edu/users/flame/pubs/TOMS-BLIS-Analytical.pdf,
  // it requires information about the first two levels of a cache to determine
  // all the parameters of a macro-kernel. It also checks that an associativity
  // degree of a cache level is greater than two. Otherwise, another algorithm
  // for determination of the parameters should be used.
  if (!(MicroKernelParams.Mr > 0 && MicroKernelParams.Nr > 0 &&
        FirstCacheLevelSize > 0 && SecondCacheLevelSize > 0 &&
        FirstCacheLevelAssociativity > 2 && SecondCacheLevelAssociativity > 2))
    return {1, 1, 1};
  // The quotient should be greater than zero.
  if (PollyPatternMatchingNcQuotient <= 0)
    return {1, 1, 1};
  int Car = floor(
      (FirstCacheLevelAssociativity - 1) /
      (1 + static_cast<double>(MicroKernelParams.Nr) / MicroKernelParams.Mr));

  // Car can be computed to be zero since it is floor to int.
  // On Mac OS, division by 0 does not raise a signal. This causes negative
  // tile sizes to be computed. Prevent division by Cac==0 by early returning
  // if this happens.
  if (Car == 0)
    return {1, 1, 1};

  auto ElementSize = getMatMulAlignTypeSize(MMI);
  assert(ElementSize > 0 && "The element size of the matrix multiplication "
                            "operands should be greater than zero.");
  int Kc = (Car * FirstCacheLevelSize) /
           (MicroKernelParams.Mr * FirstCacheLevelAssociativity * ElementSize);
  double Cac =
      static_cast<double>(Kc * ElementSize * SecondCacheLevelAssociativity) /
      SecondCacheLevelSize;
  int Mc = floor((SecondCacheLevelAssociativity - 2) / Cac);
  int Nc = PollyPatternMatchingNcQuotient * MicroKernelParams.Nr;

  assert(Mc > 0 && Nc > 0 && Kc > 0 &&
         "Matrix block sizes should be  greater than zero");
  return {Mc, Nc, Kc};
}

/// Create an access relation that is specific to
///        the matrix multiplication pattern.
///
/// Create an access relation of the following form:
/// [O0, O1, O2, O3, O4, O5, O6, O7, O8] -> [OI, O5, OJ]
/// where I is @p FirstDim, J is @p SecondDim.
///
/// It can be used, for example, to create relations that helps to consequently
/// access elements of operands of a matrix multiplication after creation of
/// the BLIS micro and macro kernels.
///
/// @see ScheduleTreeOptimizer::createMicroKernel
/// @see ScheduleTreeOptimizer::createMacroKernel
///
/// Subsequently, the described access relation is applied to the range of
/// @p MapOldIndVar, that is used to map original induction variables to
/// the ones, which are produced by schedule transformations. It helps to
/// define relations using a new space and, at the same time, keep them
/// in the original one.
///
/// @param MapOldIndVar The relation, which maps original induction variables
///                     to the ones, which are produced by schedule
///                     transformations.
/// @param FirstDim, SecondDim The input dimensions that are used to define
///        the specified access relation.
/// @return The specified access relation.
static isl::map getMatMulAccRel(isl::map MapOldIndVar, unsigned FirstDim,
                                unsigned SecondDim) {
  auto AccessRelSpace = isl::space(MapOldIndVar.ctx(), 0, 9, 3);
  auto AccessRel = isl::map::universe(AccessRelSpace);
  AccessRel = AccessRel.equate(isl::dim::in, FirstDim, isl::dim::out, 0);
  AccessRel = AccessRel.equate(isl::dim::in, 5, isl::dim::out, 1);
  AccessRel = AccessRel.equate(isl::dim::in, SecondDim, isl::dim::out, 2);
  return MapOldIndVar.apply_range(AccessRel);
}

static isl::schedule_node createExtensionNode(isl::schedule_node Node,
                                              isl::map ExtensionMap) {
  auto Extension = isl::union_map(ExtensionMap);
  auto NewNode = isl::schedule_node::from_extension(Extension);
  return Node.graft_before(NewNode);
}

static isl::schedule_node optimizePackedB(isl::schedule_node Node,
                                          ScopStmt *Stmt, isl::map MapOldIndVar,
                                          MicroKernelParamsTy MicroParams,
                                          MacroKernelParamsTy MacroParams,
                                          MatMulInfoTy &MMI) {
  Scop *S = Stmt->getParent();
  isl::set Domain = Stmt->getDomain();

  // Create packed array.
  unsigned FirstDimSize = MacroParams.Nc / MicroParams.Nr;
  unsigned SecondDimSize = MacroParams.Kc;
  unsigned ThirdDimSize = MicroParams.Nr;
  ScopArrayInfo *PackedB =
      S->createScopArrayInfo(MMI.B->getElementType(), "Packed_B",
                             {FirstDimSize, SecondDimSize, ThirdDimSize});

  // Compute the access relation for copying from B to PackedB.
  isl::map AccRelB = MMI.B->getLatestAccessRelation();
  isl::map AccRelPackedB = getMatMulAccRel(MapOldIndVar, 3, 7);
  AccRelPackedB =
      AccRelPackedB.set_tuple_id(isl::dim::out, PackedB->getBasePtrId());

  // Create the copy statement and redirect access.
  ScopStmt *CopyStmt = S->addScopStmt(AccRelB, AccRelPackedB, Domain);
  MMI.B->setNewAccessRelation(AccRelPackedB);

  unsigned Dim = unsignedFromIslSize(MapOldIndVar.range_tuple_dim());
  assert(Dim >= 2);
  // Insert into the schedule tree.
  isl::map ExtMap = MapOldIndVar.project_out(isl::dim::out, 2, Dim - 2);
  ExtMap = ExtMap.reverse();
  ExtMap = ExtMap.fix_si(isl::dim::out, MMI.i, 0);
  ExtMap = ExtMap.intersect_range(Domain);
  ExtMap = ExtMap.set_tuple_id(isl::dim::out, CopyStmt->getDomainId());
  return createExtensionNode(Node, ExtMap);
}

static isl::schedule_node optimizePackedA(isl::schedule_node Node, ScopStmt *,
                                          isl::map MapOldIndVar,
                                          MicroKernelParamsTy MicroParams,
                                          MacroKernelParamsTy MacroParams,
                                          MatMulInfoTy &MMI) {
  isl::id InputDimsId = MapOldIndVar.get_tuple_id(isl::dim::in);
  ScopStmt *Stmt = static_cast<ScopStmt *>(InputDimsId.get_user());
  isl::set Domain = Stmt->getDomain();
  isl::id DomainId = Domain.get_tuple_id();

  // Create the packed array.
  unsigned FirstDimSize = MacroParams.Mc / MicroParams.Mr;
  unsigned SecondDimSize = MacroParams.Kc;
  unsigned ThirdDimSize = MicroParams.Mr;
  ScopArrayInfo *PackedA = Stmt->getParent()->createScopArrayInfo(
      MMI.A->getElementType(), "Packed_A",
      {FirstDimSize, SecondDimSize, ThirdDimSize});

  // Compute the access relation for copying from A to PackedA.
  isl::map AccRelA = MMI.A->getLatestAccessRelation();
  isl::map AccRelPackedA = getMatMulAccRel(MapOldIndVar, 4, 6);
  AccRelPackedA =
      AccRelPackedA.set_tuple_id(isl::dim::out, PackedA->getBasePtrId());
  // { MemrefA[] -> PackedA[] }
  isl::map PackedATranslator = AccRelPackedA.apply_domain(AccRelA);

  // Compute the domain for the copy statement.
  // Construct the copy statement domain out of the 3 outermost scatter
  // dimensions (to match the 3 band nodes surrounding the extension node) and
  // the array elements to copy (one statement instance per array element).
  // { Scatter[] }
  isl::set ScatterDomain = MapOldIndVar.intersect_domain(Domain).range();
  // { Scatter[] -> OutermostScatter[] }
  isl::map OuterDomainMap =
      makeIdentityMap(ScatterDomain, true).project_out(isl::dim::out, 3, 6);
  // { Scatter[] -> MemrefA[] }
  isl::map CopyFrom = MapOldIndVar.reverse().apply_range(AccRelA);
  // { Scatter[] -> CopyStmt[] }
  isl::map DomainTranslator = OuterDomainMap.range_product(CopyFrom);
  // { CopyStmt[] }
  isl::set CopyDomain = DomainTranslator.range();

  // Translate the access relations to the new domain.
  // { CopyStmt[] -> MemrefA[] }
  CopyFrom = CopyFrom.apply_domain(DomainTranslator);
  // { CopyStmt[] -> PackedA[] }
  isl::map CopyTo = CopyFrom.apply_range(PackedATranslator);

  // Create the copy statement and redirect access.
  ScopStmt *CopyStmt =
      Stmt->getParent()->addScopStmt(CopyFrom, CopyTo, CopyDomain);
  MMI.A->setNewAccessRelation(AccRelPackedA);

  // Insert into the schedule tree.
  // { Scatter[] -> CopyStmt[] }
  isl::map ExtScatterCopy = makeIdentityMap(CopyStmt->getDomain(), true);
  ExtScatterCopy = ExtScatterCopy.project_out(isl::dim::in, 3, 2);
  return createExtensionNode(Node, ExtScatterCopy);
}

/// Apply the packing transformation.
///
/// The packing transformation can be described as a data-layout
/// transformation that requires to introduce a new array, copy data
/// to the array, and change memory access locations to reference the array.
/// It can be used to ensure that elements of the new array are read in-stride
/// access, aligned to cache lines boundaries, and preloaded into certain cache
/// levels.
///
/// As an example let us consider the packing of the array A that would help
/// to read its elements with in-stride access. An access to the array A
/// is represented by an access relation that has the form
/// S[i, j, k] -> A[i, k]. The scheduling function of the SCoP statement S has
/// the form S[i,j, k] -> [floor((j mod Nc) / Nr), floor((i mod Mc) / Mr),
/// k mod Kc, j mod Nr, i mod Mr].
///
/// To ensure that elements of the array A are read in-stride access, we add
/// a new array Packed_A[Mc/Mr][Kc][Mr] to the SCoP, using
/// Scop::createScopArrayInfo, change the access relation
/// S[i, j, k] -> A[i, k] to
/// S[i, j, k] -> Packed_A[floor((i mod Mc) / Mr), k mod Kc, i mod Mr], using
/// MemoryAccess::setNewAccessRelation, and copy the data to the array, using
/// the copy statement created by Scop::addScopStmt.
///
/// @param Node The schedule node to be optimized.
/// @param MapOldIndVar The relation, which maps original induction variables
///                     to the ones, which are produced by schedule
///                     transformations.
/// @param MicroParams, MacroParams Parameters of the BLIS kernel
///                                 to be taken into account.
/// @param MMI Parameters of the matrix multiplication operands.
/// @return The optimized schedule node.
static isl::schedule_node
optimizeDataLayoutMatrMulPattern(isl::schedule_node Node, isl::map MapOldIndVar,
                                 MicroKernelParamsTy MicroParams,
                                 MacroKernelParamsTy MacroParams,
                                 MatMulInfoTy &MMI) {
  isl::id InputDimsId = MapOldIndVar.get_tuple_id(isl::dim::in);
  ScopStmt *Stmt = static_cast<ScopStmt *>(InputDimsId.get_user());

  Node = Node.parent().parent().parent().parent().parent().parent();
  Node = isl::manage(isl_schedule_node_band_split(Node.release(), 2));

  Node = Node.child(0);
  Node =
      optimizePackedB(Node, Stmt, MapOldIndVar, MicroParams, MacroParams, MMI);

  Node = Node.child(0);
  Node =
      optimizePackedA(Node, Stmt, MapOldIndVar, MicroParams, MacroParams, MMI);

  return Node.child(0).child(0).child(0).child(0).child(0);
}

/// Get a relation mapping induction variables produced by schedule
/// transformations to the original ones.
///
/// @param Node The schedule node produced as the result of creation
///        of the BLIS kernels.
/// @param MicroKernelParams, MacroKernelParams Parameters of the BLIS kernel
///                                             to be taken into account.
/// @return  The relation mapping original induction variables to the ones
///          produced by schedule transformation.
/// @see ScheduleTreeOptimizer::createMicroKernel
/// @see ScheduleTreeOptimizer::createMacroKernel
/// @see getMacroKernelParams
static isl::map
getInductionVariablesSubstitution(isl::schedule_node Node,
                                  MicroKernelParamsTy MicroKernelParams,
                                  MacroKernelParamsTy MacroKernelParams) {
  auto Child = Node.child(0);
  auto UnMapOldIndVar = Child.get_prefix_schedule_union_map();
  auto MapOldIndVar = isl::map::from_union_map(UnMapOldIndVar);
  unsigned Dim = unsignedFromIslSize(MapOldIndVar.range_tuple_dim());
  if (Dim > 9u)
    return MapOldIndVar.project_out(isl::dim::out, 0, Dim - 9);
  return MapOldIndVar;
}

/// Isolate a set of partial tile prefixes and unroll the isolated part.
///
/// The set should ensure that it contains only partial tile prefixes that have
/// exactly Mr x Nr iterations of the two innermost loops produced by
/// the optimization of the matrix multiplication. Mr and Nr are parameters of
/// the micro-kernel.
///
/// In case of parametric bounds, this helps to auto-vectorize the unrolled
/// innermost loops, using the SLP vectorizer.
///
/// @param Node              The schedule node to be modified.
/// @param MicroKernelParams Parameters of the micro-kernel
///                          to be taken into account.
/// @return The modified isl_schedule_node.
static isl::schedule_node
isolateAndUnrollMatMulInnerLoops(isl::schedule_node Node,
                                 MicroKernelParamsTy MicroKernelParams) {
  isl::schedule_node Child = Node.child(0);
  isl::union_map UnMapOldIndVar = Child.get_prefix_schedule_relation();
  isl::set Prefix = isl::map::from_union_map(UnMapOldIndVar).range();
  unsigned Dims = unsignedFromIslSize(Prefix.tuple_dim());
  assert(Dims >= 1);
  Prefix = Prefix.project_out(isl::dim::set, Dims - 1, 1);
  Prefix = getPartialTilePrefixes(Prefix, MicroKernelParams.Nr);
  Prefix = getPartialTilePrefixes(Prefix, MicroKernelParams.Mr);

  isl::union_set IsolateOption =
      getIsolateOptions(Prefix.add_dims(isl::dim::set, 3), 3);
  isl::ctx Ctx = Node.ctx();
  auto Options = IsolateOption.unite(getDimOptions(Ctx, "unroll"));
  Options = Options.unite(getUnrollIsolatedSetOptions(Ctx));
  Node = Node.as<isl::schedule_node_band>().set_ast_build_options(Options);
  Node = Node.parent().parent().parent();
  IsolateOption = getIsolateOptions(Prefix, 3);
  Options = IsolateOption.unite(getDimOptions(Ctx, "separate"));
  Node = Node.as<isl::schedule_node_band>().set_ast_build_options(Options);
  Node = Node.child(0).child(0).child(0);
  return Node;
}

/// Insert "Loop Vectorizer Disabled" mark node.
///
/// @param Node The child of the mark node to be inserted.
/// @return The modified isl_schedule_node.
static isl::schedule_node markLoopVectorizerDisabled(isl::schedule_node Node) {
  auto Id = isl::id::alloc(Node.ctx(), "Loop Vectorizer Disabled", nullptr);
  return Node.insert_mark(Id).child(0);
}

/// Restore the initial ordering of dimensions of the band node
///
/// In case the band node represents all the dimensions of the iteration
/// domain, recreate the band node to restore the initial ordering of the
/// dimensions.
///
/// @param Node The band node to be modified.
/// @return The modified schedule node.
static isl::schedule_node
getBandNodeWithOriginDimOrder(isl::schedule_node Node) {
  assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
  if (isl_schedule_node_get_type(Node.child(0).get()) != isl_schedule_node_leaf)
    return Node;
  auto Domain = Node.get_universe_domain();
  assert(isl_union_set_n_set(Domain.get()) == 1);
  if (Node.get_schedule_depth().release() != 0 ||
      (unsignedFromIslSize(isl::set(Domain).tuple_dim()) !=
       unsignedFromIslSize(Node.as<isl::schedule_node_band>().n_member())))
    return Node;
  Node = isl::manage(isl_schedule_node_delete(Node.copy()));
  auto PartialSchedulePwAff = Domain.identity_union_pw_multi_aff();
  auto PartialScheduleMultiPwAff =
      isl::multi_union_pw_aff(PartialSchedulePwAff);
  PartialScheduleMultiPwAff =
      PartialScheduleMultiPwAff.reset_tuple_id(isl::dim::set);
  return Node.insert_partial_schedule(PartialScheduleMultiPwAff);
}

static isl::schedule_node optimizeMatMulPattern(isl::schedule_node Node,
                                                const TargetTransformInfo *TTI,
                                                MatMulInfoTy &MMI) {
  assert(TTI && "The target transform info should be provided.");
  int DimOutNum = isl_schedule_node_band_n_member(Node.get());
  assert(DimOutNum > 2 && "In case of the matrix multiplication the loop nest "
                          "and, consequently, the corresponding scheduling "
                          "functions have at least three dimensions.");
  Node = getBandNodeWithOriginDimOrder(Node);
  Node = permuteBandNodeDimensions(Node, MMI.i, DimOutNum - 3);
  int NewJ = MMI.j == DimOutNum - 3 ? MMI.i : MMI.j;
  int NewK = MMI.k == DimOutNum - 3 ? MMI.i : MMI.k;
  Node = permuteBandNodeDimensions(Node, NewJ, DimOutNum - 2);
  NewK = NewK == DimOutNum - 2 ? NewJ : NewK;
  Node = permuteBandNodeDimensions(Node, NewK, DimOutNum - 1);
  auto MicroKernelParams = getMicroKernelParams(TTI, MMI);
  auto MacroKernelParams = getMacroKernelParams(TTI, MicroKernelParams, MMI);
  Node = createMacroKernel(Node, MacroKernelParams);
  Node = createMicroKernel(Node, MicroKernelParams);
  if (MacroKernelParams.Mc == 1 || MacroKernelParams.Nc == 1 ||
      MacroKernelParams.Kc == 1)
    return Node;
  auto MapOldIndVar = getInductionVariablesSubstitution(Node, MicroKernelParams,
                                                        MacroKernelParams);
  if (MapOldIndVar.is_null())
    return Node;
  Node = markLoopVectorizerDisabled(Node.parent()).child(0);
  Node = isolateAndUnrollMatMulInnerLoops(Node, MicroKernelParams);
  return optimizeDataLayoutMatrMulPattern(Node, MapOldIndVar, MicroKernelParams,
                                          MacroKernelParams, MMI);
}

/// Check if this node contains a partial schedule that could
///        probably be optimized with analytical modeling.
///
/// isMatrMultPattern tries to determine whether the following conditions
/// are true:
/// 1. the partial schedule contains only one statement.
/// 2. there are exactly three input dimensions.
/// 3. all memory accesses of the statement will have stride 0 or 1, if we
///    interchange loops (switch the variable used in the inner loop to
///    the outer loop).
/// 4. all memory accesses of the statement except from the last one, are
///    read memory access and the last one is write memory access.
/// 5. all subscripts of the last memory access of the statement don't
///    contain the variable used in the inner loop.
/// If this is the case, we could try to use an approach that is similar to
/// the one used to get close-to-peak performance of matrix multiplications.
///
/// @param Node The node to check.
/// @param D    The SCoP dependencies.
/// @param MMI  Parameters of the matrix multiplication operands.
static bool isMatrMultPattern(isl::schedule_node Node, const Dependences *D,
                              MatMulInfoTy &MMI) {
  auto PartialSchedule = isl::manage(
      isl_schedule_node_band_get_partial_schedule_union_map(Node.get()));
  if (isl_schedule_node_band_n_member(Node.get()) < 3 ||
      Node.get_schedule_depth().release() != 0 ||
      isl_union_map_n_map(PartialSchedule.get()) != 1)
    return false;
  auto NewPartialSchedule = isl::map::from_union_map(PartialSchedule);
  if (containsMatrMult(NewPartialSchedule, D, MMI))
    return true;
  return false;
}

/// Get the dimension size.
///
/// Return the size of the dimension @p Pos, which is obtained from @p SAI.
/// Return -1 in the case of the first dimension of a multi-dimensional array,
/// since the ScopArrayInfo class does not carry size information.
///
/// @param SAI The information about the array.
/// @param Pos The position of the dimension.
/// @return The size of the dimension.
static int getDimSize(const ScopArrayInfo *SAI, unsigned Pos) {
  if (Pos == 0)
    return -1;
  const llvm::SCEV *SCEVDimSize = SAI->getDimensionSize(Pos);
  assert(SCEVDimSize);
  auto *ConstantDimSize = dyn_cast<const SCEVConstant>(SCEVDimSize);
  assert(ConstantDimSize);
  auto *IntDimSize = dyn_cast<ConstantInt>(ConstantDimSize->getValue());
  assert(IntDimSize);
  return IntDimSize->getSExtValue();
}

/// Check whether the access relation has the specified form.
///
/// Check that the access relation @p AccMap has the form T[I0, …, In], where
/// indexes I0, …, In are specified by @p Dimensions.
///
/// @param Domain     The domain of the access relation.
/// @param AccMap     The access relation to be checked.
/// @param Dimensions The permutation of the subset of the input dimensions.
/// @return True if @p AccMap has the expected form and false,
///         otherwise.
static bool isCorrectAccessMap(isl::set Domain, isl::map AccMap,
                               ArrayRef<int> Dimensions) {
  isl::space Space = AccMap.get_space();
  if (unsignedFromIslSize(Space.dim(isl::dim::out)) != Dimensions.size())
    return false;

  // Create an access relation of the following form:
  // [I0, …, Im] -> [Il, …, In], where indexes
  // Il, …, In are specified by @p Dimensions.
  isl::map PossibleTensor = isl::map::universe(Space);
  unsigned DimInSize = unsignedFromIslSize(Space.dim(isl::dim::in));
  for (unsigned i = 0; i < Dimensions.size(); i++) {
    const int InPos = Dimensions[i];
    if ((InPos >= static_cast<int>(DimInSize)) || (InPos < 0))
      return false;
    PossibleTensor =
        PossibleTensor.equate(isl::dim::in, InPos, isl::dim::out, i);
  }

  AccMap = AccMap.intersect_domain(Domain);
  PossibleTensor = PossibleTensor.intersect_domain(Domain);

  // If AccMap != PossibleTensor here (the two maps have been gisted at
  // this point), it means that the writes are not complete, or in other
  // words, it is a Partial write and Partial writes must be rejected.
  return AccMap.is_equal(PossibleTensor);
}

/// Check whether the access represents the tensor contraction operand.
///
/// Check that the access relation @p AccMap has the form T[i1, …, in].
/// Obtained indexes i1, …, in, their sizes and their permutation are stored
/// into @p IndexSet, @p DimensionSizes, and @p Dimensions, respectively.
///
/// @param Domain         The domain of the access relation.
/// @param AccMap         The access relation to be checked.
/// @param IndexSet       The subset of the input dimensions.
/// @param DimensionSizes Sizes of the input dimensions of @p Dimensions.
/// @param Dimensions     The permutation of the subset of the input dimensions.
/// @return True if @p AccMap has the expected form and false,
///         otherwise.
static bool isTCOperandAcc(isl::set Domain, isl::map AccMap,
                           SmallDenseSet<int> &IndexSet,
                           SmallVectorImpl<int> &DimensionSizes,
                           SmallVectorImpl<int> &Dimensions) {
  isl::id Id = AccMap.get_tuple_id(isl::dim::out);
  const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(Id);
  assert(SAI && "AccMap should represent memory access");

  // Fix values of output dimensions with respect to their positions.
  // In the case of the tensor contraction, values of output dimensions are
  // fixed and form a permutation of a subset of values of input dimensions.
  //
  // For example, in the case of Stmt[i][j][k] -> A[k][i], which represents
  // the operand of the tensor contraction, we get the following map by fixing
  // the output dimensions Stmt[1][j][0] -> A[0][1].
  //
  // We store the permutation of the subset of the input dimensions {2, 0} into
  // @p Dimensions.
  //
  // The obtained permutation and the isCorrectAccessMap function are used to
  // check whether the access relation @p AccMap represents the tensor
  // contraction operand. For example, in the case of
  // Stmt[i][j][k] -> A[i-1][j+1], we get Stmt[1][0][k] -> A[0][1] and,
  // consequently, {1, 0}, which is rejected by isCorrectAccessMap,
  // since it corresponds to Stmt[i][j][k] -> A[j][i].
  isl::map CheckMap = isl::manage(AccMap.copy());
  unsigned OutDimNum = unsignedFromIslSize(CheckMap.dim(isl::dim::out));
  for (unsigned i = 0; i < OutDimNum; i++)
    CheckMap = CheckMap.fix_si(isl::dim::out, i, i);

  // Try to obtain the permutation and sizes of corresponding input dimensions.
  Dimensions.assign(OutDimNum, -1);
  for (unsigned i : rangeIslSize(0, CheckMap.dim(isl::dim::in))) {
    isl::val Val = getConstant(CheckMap, isl::dim::in, i);
    if (!Val.is_int())
      continue;
    int OutPos = -1;
    llvm::APInt ValAPInt = APIntFromVal(Val);
    if (ValAPInt.isSignedIntN(32))
      OutPos = ValAPInt.getSExtValue();
    if ((OutPos < 0) || (OutPos >= static_cast<int>(OutDimNum)) ||
        IndexSet.count(i))
      return false;
    IndexSet.insert(i);
    Dimensions[OutPos] = i;
    if (DimensionSizes[i] <= 0)
      DimensionSizes[i] = getDimSize(SAI, OutPos);
  }

  return isCorrectAccessMap(Domain, AccMap, Dimensions);
}

/// Find the intersection of two sets.
///
/// Find the intersection of the set @p A and the set @p B.
///
/// @param A, B Sets to intersect.
/// @return The set intersection.
static SmallDenseSet<int> intersect(const SmallDenseSet<int> &A,
                                    const SmallDenseSet<int> &B) {
  SmallDenseSet<int> Intersection = A;
  set_intersect(Intersection, B);
  return Intersection;
}

/// Check whether the set is a superset.
///
/// Check that the set @p A is a superset of @p B.
///
/// @param A, B Sets to be checked.
/// @return True if the set A is a superset of B.
static bool isSuperset(const SmallDenseSet<int> &A,
                       const SmallDenseSet<int> &B) {
  return intersect(A, B).size() == B.size();
}

/// Find the union of two sets.
///
/// Find the union of the set @p A and the set @p B.
///
/// @param A, B Sets to unite.
/// @return The set union.
static SmallDenseSet<int> unite(const SmallDenseSet<int> &A,
                                const SmallDenseSet<int> &B) {
  SmallDenseSet<int> Union = A;
  set_union(Union, B);
  return Union;
}

/// Determine the access that writes to the tensor, which contains
/// the result of the tensor contraction.
///
/// @param Domain        The domain of the statement.
/// @param Stmt          The statement, which writes to memory.
/// @param TCI           The information about the tensor contraction.
/// @param IandJIndexSet The set, which contains free indexes of tensors.
/// @return The determined MemoryAccess, or nullptr if there is no necessary
///         access within the SCoP.
static MemoryAccess *getWriteAccess(isl::set Domain, ScopStmt *Stmt,
                                    TCInfoTy &TCI,
                                    SmallDenseSet<int> &IandJIndexSet) {
  TCI.WriteToC = nullptr;
  SmallVector<MemoryAccess *, 32> Accesses = getAccessesInOrder(*Stmt);
  for (MemoryAccess *MemA : reverse(Accesses)) {
    // A TC-like does not contain write scalar memory accesses
    if (!MemA->isLatestArrayKind())
      return nullptr;
    // The last memory access should be a write memory access.
    if (!MemA->isWrite())
      return nullptr;

    isl::map AccMap = MemA->getLatestAccessRelation();
    if (!isTCOperandAcc(Domain, AccMap, IandJIndexSet, TCI.DimensionSizes,
                        TCI.CDimensions))
      return nullptr;

    return MemA;
  }
  return nullptr;
}

/// Determine an access, which reads elements of an operand of the tensor
/// contraction
///
/// @param MemAccessPtr  The access, which reads elements of the tensor.
/// @param IndexSet      The set, which contains indexes of the tensors.
/// @param IandJIndexSet The set, which contains free indexes of tensors.
/// @param Dimensions    The permutation of the subset of the input dimensions.
/// @param TCI           The information about the tensor contraction.
/// @return True if the memory access @p MemAccessPtr corresponds
///         to the tensor contraction.
static bool setReadAccess(MemoryAccess *MemAccessPtr,
                          const SmallDenseSet<int> &IndexSet,
                          const SmallDenseSet<int> &IandJIndexSet,
                          ArrayRef<int> Dimensions, TCInfoTy &TCI) {
  if (!TCI.A) {
    // Probably IndexSet is a union of I and P sets.
    if (!isSuperset(IndexSet, TCI.P))
      return false;

    // Obtain the set I.
    TCI.I = set_difference(IndexSet, TCI.P);
    if (!isSuperset(IandJIndexSet, TCI.I))
      return false;

    // Obtain the set J.
    TCI.J = set_difference(IandJIndexSet, TCI.I);

    // Set the first operand of the tensor contraction.
    TCI.A = MemAccessPtr;
    llvm::replace(TCI.ADimensions, TCI.ADimensions.begin(),
                  TCI.ADimensions.end(), Dimensions.begin(), Dimensions.end());
    return true;
  }

  if (!TCI.B) {
    // IndexSet should be a union of J and P sets.
    if (unite(TCI.P, TCI.J) != IndexSet)
      return false;

    // Set the second operand of the tensor contraction.
    TCI.B = MemAccessPtr;
    llvm::replace(TCI.BDimensions, TCI.BDimensions.begin(),
                  TCI.BDimensions.end(), Dimensions.begin(), Dimensions.end());
    return true;
  }

  return false;
}

/// Check that all memory accesses of the statement, except from the last
/// one, are read memory accesses, which read elements of operands of the tensor
/// contraction and its result.
///
/// @param Domain        The domain of the statement.
/// @param Stmt          The statement, which writes to memory.
/// @param TCI           The information about the tensor contraction.
/// @param IandJIndexSet The set, which contains free indexes of tensors.
/// @return True if all read memory accesses of the statement @p Stmt correspond
///         to the tensor contraction.
static bool setReadAccesses(isl::set Domain, ScopStmt *Stmt, TCInfoTy &TCI,
                            SmallDenseSet<int> &IandJIndexSet) {
  TCI.A = nullptr;
  TCI.B = nullptr;
  TCI.ReadFromC = nullptr;
  SmallVector<MemoryAccess *, 32> Accesses = getAccessesInOrder(*Stmt);
  for (auto *MemA = Accesses.begin(); *MemA != TCI.WriteToC; MemA++) {
    MemoryAccess *MemAccessPtr = *MemA;

    // All memory accesses, except from the last one, should be read memory
    // accesses.
    if (MemAccessPtr->isWrite())
      return false;

    isl::map AccMap = MemAccessPtr->getLatestAccessRelation();

    if (!MemAccessPtr->isLatestArrayKind()) {
      // Check whether the scalar read memory access is not partial.
      if (!Domain.is_subset(AccMap.domain()))
        return false;
      continue;
      return false;
    }

    // There is only one memory access, which reads elements of the result of
    // the tensor contraction.
    if (AccMap.is_equal(TCI.WriteToC->getLatestAccessRelation())) {
      if (TCI.ReadFromC)
        return false;
      TCI.ReadFromC = MemAccessPtr;
      continue;
    }

    SmallVector<int> Dimensions;
    SmallDenseSet<int> IndexSet;
    if (!isTCOperandAcc(Domain, AccMap, IndexSet, TCI.DimensionSizes,
                        Dimensions))
      return false;

    if (!setReadAccess(MemAccessPtr, IndexSet, IandJIndexSet, Dimensions, TCI))
      return false;
  }

  // Check that there are read memory accesses, which read elements of operands
  // of the tensor contraction and its result.
  return TCI.ReadFromC && TCI.A && TCI.B;
}

/// Check accesses to operands of the tensor contraction.
///
/// Check that accesses of the SCoP statement, which corresponds to
/// the partial schedule @p PartialSchedule, represent accesses
/// to the non-scalar operands of the tensor contraction.
///
/// @param  Domain          The domain of the SCoP statement.
/// @param  PartialSchedule The partial schedule of the SCoP statement.
/// @param  TCI             Parameters of the tensor contraction operands.
/// @return                 True if the corresponding SCoP statement
///                         represents tensor contraction and false,
///                         otherwise.
static bool containsOnlyTCAcc(isl::set Domain, isl::map PartialSchedule,
                              TCInfoTy &TCI) {
  isl::id InputDimsId = PartialSchedule.get_tuple_id(isl::dim::in);
  ScopStmt *Stmt = static_cast<ScopStmt *>(InputDimsId.get_user());

  // In region statements, the order of memory accesses execution is not
  // predictable at compile-time.
  if ((Stmt->size() <= 1) || Stmt->isRegionStmt())
    return false;

  unsigned DimNum = unsignedFromIslSize(PartialSchedule.dim(isl::dim::in));
  TCI.DimensionSizes.resize(DimNum);
  SmallDenseSet<int> IandJIndexSet;

  TCI.WriteToC = getWriteAccess(Domain, Stmt, TCI, IandJIndexSet);
  if (!TCI.WriteToC)
    return false;

  if (intersect(IandJIndexSet, TCI.P).size() != 0)
    return false;

  if (!setReadAccesses(Domain, Stmt, TCI, IandJIndexSet))
    return false;

  return true;
}

/// Check that dependency corresponds to the tensor contraction carried over
/// loop dimension @p Dim.
///
/// Check that the dependency has the form
/// S(..., ki, max(k(i + 1)), ..., max(kn), ...) ->
/// S(..., ki + 1, min(k(i + 1)), ..., min(kn), ...), where S is the SCoP
/// statement. For this purpose, we analyze the set @p DepDelta, which
/// represents the differences between image elements and domain elements of
/// the corresponding map.
///
/// @param  DepDelta    The set contains the differences between image elements
///                     and corresponding domain elements of the map, which
///                     represents the dependency.
/// @param  Dim         The position of the index ki.
/// @param  BoundDeltas In the case of indexes of ki, the difference between
///                     image elements and corresponding domain elements
///                     corresponds to the difference between lexicographic
///                     minimum and lexicographic maximum of the corresponding
///                     dimension of the domain of the statement.
/// @param  IndexSet    Obtained indexes ki, which describe the dependency.
/// @return True if dependencies correspond to the tensor contraction
///         and false, otherwise.
static bool isReductionCarriedOverDim(isl::set DepDelta, unsigned Dim,
                                      isl::pw_multi_aff BoundDeltas,
                                      const SmallDenseSet<int> &IndexSet) {
  isl::space Space = DepDelta.get_space();
  isl::set Superset = isl::set::universe(Space);
  for (unsigned i = 0; i < Dim; i += 1)
    Superset = Superset.fix_si(isl::dim::set, i, 0);
  Superset = Superset.fix_si(isl::dim::set, Dim, 1);

  // Check that the difference between the image element and the domain element
  // is equal to one in the case of the index ki. Image elements and
  // corresponding domain elements should be equal in the case of positions,
  // which are lower than the specified position.
  if (!DepDelta.is_subset(Superset))
    return false;

  // Compute a set, which is used to analyze how values of
  // the domain are related to the map that describes the dependency.
  isl_pw_multi_aff *DepDeltaPW = isl_pw_multi_aff_from_set(DepDelta.copy());
  BoundDeltas = BoundDeltas.add(isl::manage(DepDeltaPW));
  isl_set *ComplementRawSet = isl_set_from_pw_multi_aff(BoundDeltas.release());
  isl::set Complement = isl::manage(ComplementRawSet);

  for (unsigned i : rangeIslSize(Dim + 1, DepDelta.dim(isl::dim::set))) {
    if (!IndexSet.count(i)) {
      // Check the difference between the image element and the domain element
      // in the case of indexes, which do not describe the dependency.
      if (DepDelta.plain_get_val_if_fixed(isl::dim::set, i).is_zero())
        continue;
      return false;
    }

    // In the case of other indexes, which describe the dependency,
    // the difference between the image element and the domain element
    // should be equal to the difference between lexicographic minimum and
    // lexicographic maximum of the domain of the statement.
    if (!Complement.plain_get_val_if_fixed(isl::dim::set, i).is_zero())
      return false;
  }

  return true;
}

/// Check whether dependencies are over the complete domain.
///
/// In the case of the tensor contraction RAW, WAW, WAR dependencies
/// have the form
/// S(..., ki, max(k(i + 1)), ..., max(kn), ...) ->
/// S(..., ki + 1, min(k(i + 1)), ..., min(kn), ...), where S is the SCoP
/// statement. Consequently, the domain of the dependencies
/// can be described as
/// Domain / Domain ∩ S(…, max(kn),…) ∩ S(…, max(k(i + 1)),…),
/// where Domain is the domain of the statement S.
///
/// For example, in the case of the following tensor contraction,
/// corresponding domains will have the following form.
///
/// An example of the tensor contraction:
/// for (i = 0; i < 1024; i++)
///   for (j = 0; j < 1024; j++)
///     for (l = 0; l < 64; ++l)
///       for (w = 0; w < 64; ++w)
///         C[i][j] += A[i][l][w] * B[w][j][l];
///
/// The domain of the statement:
/// { S[i0, i1, i2, i3] : i0 >= 0 and i0 <= 1023 and
///                       i1 >= 0 and i1 <= 1023 and
///                       i2 >= 0 and i2 <= 63 and
///                       i3 >= 0 and i3 <= 63 }
///
/// The domain of the dependencies:
/// { S[i0, i1, i2, i3] : (i0 >= 0 and i0 <= 1023 and
///                        i1 >= 0 and i1 <= 1023 and
///                        i2 >= 0 and i2 <= 63 and
///                        i3 >= 0 and i3 <= 62) or
///                       (i3 = 63 and i0 >= 0 and i0 <= 1023 and
///                        i1 >= 0 and i1 <= 1023 and
///                        i2 >= 0 and i2 <= 62) }
///
/// @param  Domain       The domain of the statement.
/// @param  DepsForStmt  RAW and RED dependencies for the statement.
/// @param  UpperBound   The lexicographic maximum of the elements in
///                      the @p Domain.
/// @param  IndexSet     Obtained indexes ki, which describe the dependencies.
/// @return True if dependencies are over the complete domain
///         and false, otherwise.
static bool areDepsOverCompleteDomain(isl::set Domain, isl::map DepsForStmt,
                                      isl::pw_multi_aff UpperBound,
                                      SmallDenseSet<int> &IndexSet) {
  isl_set *UpperBoundRawSet = isl_set_from_pw_multi_aff(UpperBound.copy());
  isl::set UpperBoundSet = isl::manage(UpperBoundRawSet);

  isl::set DomainRed = isl::manage(Domain.copy());
  for (const auto It : IndexSet) {
    isl::val FixedVal = UpperBoundSet.plain_get_val_if_fixed(isl::dim::set, It);
    if (FixedVal.is_nan())
      return false;
    DomainRed = isl::manage(
        isl_set_fix_val(DomainRed.copy(), isl_dim_set, It, FixedVal.release()));
  }
  return DepsForStmt.domain().intersect(Domain).is_equal(
      Domain.subtract(DomainRed));
}

/// Check that dependencies correspond to the tensor contraction.
///
/// Check that there are only true dependencies of the form
/// S(..., ki, max(k(i + 1)), ..., max(kn), ...) ->
/// S(..., ki + 1, min(k(i + 1)), ..., min(kn), ...), where S is the SCoP
/// statement represented by @p Schedule. Such dependencies are produced by
/// the tensor contraction. Obtained indexes ki are stored into @p IndexSet.
///
/// The form of anti and output dependencies is specified implicitly by
/// the form the SCoP statement, which is checked by subsequent analysis.
///
/// @param  Schedule The schedule of the SCoP statement.
/// @param  D        The SCoP dependencies.
/// @param  Domain   The domain of the statement.
/// @param  IndexSet Obtained indexes ki, which describe the dependencies.
/// @return True if dependencies correspond to the tensor contraction
///         and false, otherwise.
static bool containsOnlyTcDeps(isl::map Schedule, const Dependences *D,
                               SmallDenseSet<int> &IndexSet, isl::set Domain) {
  IslMaxOperationsGuard MaxOpGuard(Schedule.ctx().get(), OptComputeOut);

  isl::union_map Dep =
      D->getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);

  isl::space DomainSpace = Schedule.get_space().domain();
  isl::space Space = DomainSpace.map_from_domain_and_range(DomainSpace);
  isl::map DepsForStmt = Dep.extract_map(Space);
  isl::set DepDeltas = DepsForStmt.deltas();
  isl::size DeltasDimNum = DepDeltas.dim(isl::dim::set);
  isl::pw_multi_aff LowerBound = Domain.lexmin_pw_multi_aff();
  isl::pw_multi_aff UpperBound = Domain.lexmax_pw_multi_aff();
  isl::pw_multi_aff BoundDeltas = UpperBound.sub(LowerBound);

  for (int i : reverse(rangeIslSize(0, DeltasDimNum))) {
    // In the case of the tensor contraction, the difference between image
    // elements and domain elements lies on a hyperplane where a dimension
    // has the fixed value one.
    isl::set Intersection = DepDeltas.fix_si(isl::dim::set, i, 1);
    if (Intersection.is_empty())
      continue;

    if (!isReductionCarriedOverDim(Intersection, i, BoundDeltas, IndexSet))
      return false;

    IndexSet.insert(i);
    DepDeltas = DepDeltas.subtract(Intersection);
  }

  // In the case of the tensor contraction, all dependencies should have
  // the previously described form.
  if ((unsignedFromIslSize(DeltasDimNum) == 0) || !DepDeltas.is_empty())
    return false;

  return areDepsOverCompleteDomain(Domain, DepsForStmt, UpperBound, IndexSet);
}

/// Check if the SCoP statement could probably be optimized with analytical
/// modeling.
///
/// containsTCInfoTy tries to determine whether the following conditions
/// are true:
///
/// 1. The last memory access modeling an array, MA1, represents writing to
///    memory and has the form S(..., I, ..., J, ...) -> M(shuffle(I, J)),
///    where S is the SCoP statement under consideration and shuffle(I, J)
///    is a permutation of indexes of sets I and J.
/// 2. There are only true dependencies of the form
///    S(..., ki, max(k(i + 1)), ..., max(kn), ...) ->
///    S(..., ki + 1, min(k(i + 1)), ..., min(kn), ...), where S is the SCoP
///    statement represented by @p Schedule and ki are indexes of the set P.
/// 3. SCoP contains an arbitrary number of reads from constants and only three
///    access relations, MA2, MA3, and MA4 that represent reading from memory
///    and have the form
///    S(..., I, ..., P, ...) -> M(shuffle(I, P)),
///    S(..., P, ..., J, ...) -> M(shuffle(J, P)),
///    S(...) -> M(shuffle(I, J)), respectively.
///
/// @param  PartialSchedule The PartialSchedule that contains a SCoP statement
///                         to check.
/// @param  D               The SCoP dependencies.
/// @param  TCI             Parameters of the tensor contraction operands.
/// @param  Domain          The domain of the statement.
/// @return True if dependencies and memory accesses correspond to the tensor
///              contraction and false, otherwise.
static bool containsTCInfoTy(isl::map PartialSchedule, const Dependences *D,
                             TCInfoTy &TCI, isl::set Domain) {
  if (!containsOnlyTcDeps(PartialSchedule, D, TCI.P, Domain))
    return false;

  // TODO: handle cases of scalar multiplication if needed.
  if (TCI.P.size() == 0)
    return false;

  if (!containsOnlyTCAcc(Domain, PartialSchedule, TCI))
    return false;

  // TODO: handle cases of GEMV if needed.
  if ((TCI.I.size() == 0) || (TCI.J.size() == 0))
    return false;

  return true;
}

/// Check if this node contains a partial schedule that could
/// probably be optimized with analytical modeling.
///
/// isTCPattern is used to determine whether the SCoP represents a TC-like
/// kernel [1], which is a perfectly nested set of loops, with a data usage
/// pattern that is similar to that produced by the tensor contraction.
///
/// A TC-like kernel can be defined as follows:
///
/// 1. It satisfies the requirements of the polyhedral model.
/// 2. Without loss of generality, it contains three nonempty bundles of
///    one-dimensional for-loops with induction variables that are grouped into
///    bundles I = i0...i(r-1), J = j0..j(s-1), and P = p0...p(t-1), and they
///    are incremented by one.
/// 3. The innermost loop body can be represented as a statement of the form
///    C(shuffle(I, J)) = E(A(shuffle(I, P)), B(shuffle(P, J)),
///    C(shuffle(I, J))), where A(shuffle(I, P)), B(shuffle(P, J)),
///    C(shuffle(I, J)) are accesses to tensors A, B, C, respectively,
///    shuffle(I, J), shuffle(I, P), and shuffle(P, J) are permutations of the
///    enclosed indices, and E is an expression that contains reads from
///    the tensors A, B, C, and an arbitrary number of reads from constants
///    with respect to bundles I, J, and P.
///
/// TC can be considered as a particular case of a TC-like kernel.
///
/// The order of loops with indexes from P should be preserved. Otherwise,
/// isTCPattern should check if a commutative operation is used.
///
/// isTCPattern performs the following steps to check whether the SCoP
/// corresponds to a definition of a TC-like kernel:
///
/// 1. Checks that the node is the innermost band node.
/// 2. Checks that the partial schedule contains only one statement.
/// 3. Check that all ancestors of the node contain all band nodes for
///    the statement and only mark nodes interleave such band nodes. This
///    corresponds to a straightforward implementation of TC.
/// 4. Analyses the dependencies to determine contraction dimensions.
/// 5. Check that the last memory access modeling an array, represents writing
///    to the result of the TC-like kernel.
/// 6. Check that SCoP contains only three access relations that represent
///    reading of the operands of the TC-like kernel and an arbitrary number of
///    reads from constants.
///
/// [1] - Gareev R., Grosser T., Kruse M. High-Performance Generalized Tensor
///       Operations: A Compiler-Oriented Approach // ACM Transactions
///       Architecture and Code Optimization (TACO). 2018.
///       Vol. 15, no. 3. P. 34:1–34:27. DOI: 10.1145/3235029.
///
/// If this is the case, we could logically represent tensors as matrices and
/// apply algorithms, which are used to get close-to-peak performance of
/// matrix multiplications in manually tuned BLAS libraries (e.g., BLIS).
///
/// @param Node The node to check.
/// @param D    The SCoP dependencies.
/// @param TCI  Parameters of the tensor contraction operands.
static bool isTCPattern(isl::schedule_node Node, const Dependences *D,
                        TCInfoTy &TCI) {
  Node = Node.child(0);
  isl::union_map PartialSchedule = Node.get_prefix_schedule_union_map();
  isl::union_set Domain = Node.domain();
  Node = Node.parent();

  // The partial schedule should contain only one statement.
  // TODO: This constraint should not be intrinsic to the algorithm.
  if (isl_union_set_n_set(Domain.get()) != 1)
    return false;

  isl_schedule_node_type NodeType = isl_schedule_node_get_type(Node.get());

  // Check that all ancestors of the node contain all band nodes for
  // the statement, which represents the TC-like kernel, and only mark nodes
  // interleave such band nodes. This corresponds to a straightforward
  // implementation of TC with/without DeLICM applied.
  //
  // For example, this covers the matrix multiplication pattern after a full
  // run of -polly-optree and -polly-delicm, where the write access is not
  // through the original memory access, but through a PHI node that was
  // delicmed. Subsequently, such band nodes will be replaced by a single band
  // node.
  //
  // The corresponding schedule can be the following, where Stmt_for_body8
  // contains the matrix multiplication:
  //
  // domain: "{ Stmt_for_body8[i0, i1, i2]  : 0 <= i0 <= 1599 and
  //                                          0 <= i1 <= 1799 and
  //                                          0 <= i2 <= 2199;
  //            Stmt_for_body3[i0, i1] :      0 <= i0 <= 1599 and
  //                                          0 <= i1 <= 1799;
  //            Stmt_for_body3_last[i0, i1] : 0 <= i0 <= 1599 and
  //                                          0 <= i1 <= 1799 }"
  // child:
  //  sequence:
  //  - filter: "{ Stmt_for_body3[i0, i1] }"
  //    child:
  //      schedule: "[{ Stmt_for_body3[i0, i1] -> [(i0)] },
  //                  { Stmt_for_body3[i0, i1] -> [(i1)] }]"
  //      permutable: 1
  //      coincident: [ 1, 1 ]
  //  - filter: "{ Stmt_for_body3_last[i0, i1] }"
  //    child:
  //      schedule: "[{ Stmt_for_body3_last[i0, i1] -> [(i0)] },
  //                  { Stmt_for_body3_last[i0, i1] -> [(i1)] }]"
  //      permutable: 1
  //      coincident: [ 1, 1 ]
  //  - filter: "{ Stmt_for_body8[i0, i1, i2] }"
  //    child:
  //      schedule: "[{ Stmt_for_body8[i0, i1, i2] -> [(i0)] },
  //                  { Stmt_for_body8[i0, i1, i2] -> [(i1)] },
  //                  { Stmt_for_body8[i0, i1, i2] -> [(i2)] }]"
  //      permutable: 1
  //      coincident: [ 1, 1, 0 ]
  //
  while (NodeType != isl_schedule_node_domain) {
    if (NodeType == isl_schedule_node_filter) {
      if (!Node.parent().isa<isl::schedule_node_sequence>() ||
          !Node.parent().parent().isa<isl::schedule_node_domain>())
        return false;
      break;
    }

    if ((NodeType != isl_schedule_node_band) &&
        (NodeType != isl_schedule_node_mark))
      return false;

    Node = Node.parent();
    NodeType = isl_schedule_node_get_type(Node.get());
  }

  isl::map PartialScheduleMap = isl::map::from_union_map(PartialSchedule);
  if (containsTCInfoTy(PartialScheduleMap, D, TCI, isl::set(Domain)))
    return true;

  return false;
}

} // namespace

isl::schedule_node
polly::tryOptimizeMatMulPattern(isl::schedule_node Node,
                                const llvm::TargetTransformInfo *TTI,
                                const Dependences *D) {
  TCInfoTy TCI;
  if (PMBasedTCOpts && isTCPattern(Node, D, TCI))
    POLLY_DEBUG(dbgs() << "The tensor contraction pattern was detected\n");
  MatMulInfoTy MMI;
  if (PMBasedMMMOpts && isMatrMultPattern(Node, D, MMI)) {
    POLLY_DEBUG(dbgs() << "The matrix multiplication pattern was detected\n");
    return optimizeMatMulPattern(Node, TTI, MMI);
  }
  return {};
}
