MLIR 22.0.0git
X86VectorUtils.cpp
Go to the documentation of this file.
1//===- X86VectorUtils.cpp - MLIR Utilities for X86VectorOps -------------===//
2//
3// Part of the MLIR Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
16#include "mlir/IR/Types.h"
17
18namespace mlir {
19namespace x86vector {
20
21static FailureOr<SmallVector<mlir::utils::IteratorType>>
23 if (!map.isProjectedPermutation())
24 return failure();
26 map.getNumDims(), mlir::utils::IteratorType::reduction);
27 for (auto expr : map.getResults())
28 if (auto dim = dyn_cast<AffineDimExpr>(expr))
29 iterators[dim.getPosition()] = mlir::utils::IteratorType::parallel;
30 return iterators;
31}
32
33// Returns true if the operation is in VNNI layout.
34// Optionally, the check can be constrained to a specific VNNI blocking factor.
36 std::optional<unsigned> blockingFactor) {
37 // Narrow down type operations - VNNI only applies to contractions.
38 FailureOr<linalg::ContractionDimensions> dims =
39 linalg::inferContractionDims(indexingMaps);
40 if (failed(dims))
41 return false;
42
43 auto matA = op->getOperand(0);
44 auto matB = op->getOperand(1);
45 auto typeA = dyn_cast<ShapedType>(matA.getType());
46 auto typeB = dyn_cast<ShapedType>(matB.getType());
47 unsigned rankA = typeA.getRank();
48 unsigned rankB = typeB.getRank();
49 // VNNI format requires at least 1 parallel and 2 reduction dimensions.
50 if (rankA < 3 || rankB < 3)
51 return false;
52
53 // At least two reduction dimensions are expected:
54 // one for the VNNI factor and one for the K dimension
55 if (dims->k.size() < 2)
56 return false;
57
58 // Validate affine maps - VNNI computation should be defined by the two
59 // innermost reduction iterators.
60 // The input matrix dimensions layout must match the following:
61 // - matrix A - [...][K/vnniFactor][vnniFactor]
62 // - matrix B - [...][K/vnniFactor][N][vnniFactor]
63 auto maybeIters = inferIteratorsFromOutMap(indexingMaps[2] /* outs */);
64 if (failed(maybeIters))
65 return false;
66 SmallVector<mlir::utils::IteratorType> iteratorTypes = *maybeIters;
67 AffineMap mapA = indexingMaps[0];
68 AffineMap mapB = indexingMaps[1];
69
70 auto vnniDimA = dyn_cast<AffineDimExpr>(mapA.getResult(rankA - 1));
71 auto vnniDimB = dyn_cast<AffineDimExpr>(mapB.getResult(rankB - 1));
72 if (!vnniDimA || !vnniDimB || vnniDimA != vnniDimB ||
73 iteratorTypes[vnniDimA.getPosition()] !=
74 mlir::utils::IteratorType::reduction)
75 return false;
76 auto redDimA = dyn_cast<AffineDimExpr>(mapA.getResult(rankA - 2));
77 auto redDimB = dyn_cast<AffineDimExpr>(mapB.getResult(rankB - 3));
78 if (!redDimA || !redDimB || redDimA != redDimB ||
79 iteratorTypes[redDimA.getPosition()] !=
80 mlir::utils::IteratorType::reduction)
81 return false;
82 auto parallelDimB = dyn_cast<AffineDimExpr>(mapB.getResult(rankB - 2));
83 if (!parallelDimB || iteratorTypes[parallelDimB.getPosition()] !=
84 mlir::utils::IteratorType::parallel)
85 return false;
86
87 // VNNI factor must be:
88 // - the innermost inputs' dimension
89 // - statically known
90 // - multiple of 2 or equal to the specified factor
91 auto vnniDimSize = typeB.getShape().back();
92 if (vnniDimSize == ShapedType::kDynamic || vnniDimSize == 0 ||
93 vnniDimSize % 2 != 0)
94 return false;
95 if (typeA.getShape().back() != vnniDimSize)
96 return false;
97 if (blockingFactor && vnniDimSize != *blockingFactor)
98 return false;
99
100 // The split reduction dimension size should also match.
101 if (typeA.getShape().end()[-2] != typeB.getShape().end()[-3])
102 return false;
103
104 return true;
105}
106
107} // namespace x86vector
108} // namespace mlir
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
bool isProjectedPermutation(bool allowZeroInResults=false) const
Returns true if the AffineMap represents a subset (i.e.
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
AffineExpr getResult(unsigned idx) const
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
Value getOperand(unsigned idx)
Definition Operation.h:350
FailureOr< ContractionDimensions > inferContractionDims(LinalgOp linalgOp)
Find at least 2 parallel (m and n) and 1 reduction (k) dimension candidates that form a matmul subcom...
static FailureOr< SmallVector< mlir::utils::IteratorType > > inferIteratorsFromOutMap(AffineMap map)
bool isInVnniLayout(Operation *op, llvm::ArrayRef< AffineMap > indexingMaps, std::optional< unsigned > blockingFactor=std::nullopt)
Include the generated interface declarations.