40 Value v = b.
create<affine::AffineApplyOp>(loc, m, ivs);
50 Block *body = linalgOp.getBlock();
54 if (
auto indexOp = dyn_cast<IndexOp>(&op)) {
55 map.
map(indexOp.getResult(), ivs[indexOp.getDim()]);
65 OpOperand *storeInto = linalgOp.getDpsInitOperand(operand.index());
67 b, loc, linalgOp.getMatchingIndexingMap(storeInto), ivs);
69 loc, toStore, linalgOp.getDpsInitOperand(operand.index())->get(),
85 template <
typename LinalgOpTy>
86 struct LinalgOpTilingInterface
87 :
public TilingInterface::ExternalModel<LinalgOpTilingInterface<LinalgOpTy>,
91 LinalgOpTy concreteOp = cast<LinalgOpTy>(op);
92 return concreteOp.getIteratorTypesArray();
100 LinalgOp linalgOp = cast<LinalgOp>(op);
102 linalgOp.createFlatListOfOperandDims(b, loc);
103 AffineMap map = linalgOp.getShapesToLoopsMap();
105 return llvm::to_vector(
107 OpFoldResult ofr = affine::makeComposedFoldedAffineApply(
108 b, loc, loopExpr, allShapesSizes);
109 return Range{b.getIndexAttr(0), ofr, b.getIndexAttr(1)};
121 LinalgOp linalgOp = cast<LinalgOp>(op);
124 b, loc, linalgOp, valuesToTile, offsets, sizes, {},
true);
129 Operation *tiledOp =
clone(b, linalgOp, resultTensorTypes, tiledOperands);
144 LinalgOp linalgOp = cast<LinalgOp>(op);
149 llvm::to_vector(llvm::map_range(sizes, [&](
OpFoldResult ofr) {
153 OpOperand *outOperand = linalgOp.getDpsInitOperand(resultNumber);
155 b, loc, outOperand->
get(), sizes,
156 linalgOp.getMatchingIndexingMap(outOperand), offsets,
157 {}, subShapeSizes,
true);
158 resultOffsets = sliceParams.
offsets;
159 resultSizes = sliceParams.
sizes;
167 auto linalgOp = cast<LinalgOp>(op);
174 linalgOp.getIndexingMapMatchingResult(op->
getResult(resultNumber));
177 "unhandled tiled implementation generation when result is not "
178 "accessed using a permuted projection");
181 auto numLoops = linalgOp.getNumLoops();
182 auto tilingInterfaceOp = cast<TilingInterface>(op);
184 iterationTileSizes(numLoops);
187 tilingInterfaceOp.getIterationDomain(b);
189 iterationTileOffsets[range.index()] = range.value().offset;
190 iterationTileSizes[range.index()] = range.value().size;
194 unsigned dimPosition =
195 cast<AffineDimExpr>(resultExpr.value()).getPosition();
196 iterationTileOffsets[dimPosition] = offsets[resultExpr.index()];
197 iterationTileSizes[dimPosition] = sizes[resultExpr.index()];
201 tilingInterfaceOp.getTiledImplementation(b, iterationTileOffsets,
203 if (tilingResult->tiledOps.size() != 1)
204 return op->
emitOpError(
"failed to generate tiled implementation");
207 tilingResult->tiledOps,
214 auto linalgOp = cast<LinalgOp>(op);
215 if (!linalgOp.hasBufferSemantics())
216 return op->
emitOpError(
"expected operation to have buffer semantics");
219 indexedValues.reserve(linalgOp->getNumOperands());
223 for (
OpOperand &operand : linalgOp->getOpOperands()) {
224 if (!linalgOp.payloadUsesValueFromOperand(&operand)) {
225 indexedValues.push_back(
nullptr);
228 if (linalgOp.isScalar(&operand)) {
229 indexedValues.push_back(operand.get());
233 builder, linalgOpLoc, linalgOp.getMatchingIndexingMap(&operand), ivs);
235 builder.
create<memref::LoadOp>(linalgOpLoc, operand.get(), indices);
236 indexedValues.push_back(load);
249 template <
typename LinalgOpTy>
250 struct LinalgOpPartialReductionInterface
251 :
public PartialReductionOpInterface::ExternalModel<
252 LinalgOpPartialReductionInterface<LinalgOpTy>, LinalgOpTy> {
256 auto linalgOp = cast<LinalgOp>(op);
259 if (linalgOp.hasBufferSemantics())
260 return op->
emitOpError(
"expected operation to have tensor semantics");
265 if (!
matchReduction(linalgOp.getRegionOutputArgs(), 0, combinerOps) ||
266 combinerOps.size() != 1)
267 return op->
emitOpError(
"Failed to anaysis the reduction operation.");
271 if (!identity.has_value())
273 "Failed to get an identity value for the reduction operation.");
276 linalgOp.getShape(linalgOp.getDpsInitOperand(0));
281 if (tileSizeVector.size() < oldShape.size()) {
282 auto zero = b.
create<arith::ConstantIndexOp>(loc, 0);
283 tileSizeVector.append(oldShape.size() - tileSizeVector.size(), zero);
290 int64_t currReductionDims = 0;
291 DenseSet<int> reductionDimsSet(reductionDims.begin(), reductionDims.end());
293 llvm::seq<int64_t>(0, oldShape.size() + reductionDims.size())) {
294 if (reductionDimsSet.contains(idx)) {
299 int64_t oldIdx = idx - currReductionDims;
300 int64_t dim = oldShape[oldIdx];
301 newOutputShape.push_back(dim);
302 if (ShapedType::isDynamic(dim))
303 dynamicDims.push_back(b.
create<tensor::DimOp>(
304 loc, linalgOp.getDpsInitOperand(0)->get(), oldIdx));
307 loc, newOutputShape, linalgOp.getRegionOutputArgs()[0].getType(),
309 Value constantOp = b.
create<arith::ConstantOp>(loc, *identity);
310 auto identityTensor =
311 b.
create<linalg::FillOp>(loc, constantOp, emptyTensor);
312 return identityTensor.getOperation();
321 auto linalgOp = cast<LinalgOp>(op);
324 linalgOp.getMatchingIndexingMap(linalgOp.getDpsInitOperand(0));
326 reductionDims.size());
328 for (
int idx : reductionDims)
331 for (
int idx : llvm::seq<int>(0, outputExpr.size())) {
334 outputExpr[idx] = oldOutputMap.
getResult(currExpr++);
340 b, loc, linalgOp, valuesToTile, offsets, sizes, {},
true);
346 Value out = b.
create<tensor::ExtractSliceOp>(loc, init[0], outOffsets,
352 linalgOp.getIteratorTypesArray();
353 for (
int dim : reductionDims)
354 newIteratorTypes[dim] = utils::IteratorType::parallel;
356 newMaps.back() =
AffineMap::get(newMaps.back().getNumDims(), 0, outputExpr,
357 linalgOp.getContext());
360 ValueRange({out}), newMaps, newIteratorTypes);
363 genericOp.getRegion().begin(), mapping);
364 return genericOp.getOperation();
370 auto linalgOp = cast<LinalgOp>(op);
372 DenseSet<int> reductionDimsSet(reductionDims.begin(), reductionDims.end());
376 int64_t intermRank = cast<ShapedType>(partialReduce[0].getType()).getRank();
381 for (int64_t i : llvm::seq<int64_t>(0, intermRank)) {
382 if (reductionDimsSet.contains(i)) {
383 reductionIteratorTypes.push_back(utils::IteratorType::reduction);
386 reductionIteratorTypes.push_back(utils::IteratorType::parallel);
398 auto reduction = b.
create<GenericOp>(
400 linalgOp.getDpsInits(), reductionMaps, reductionIteratorTypes,
405 b.create<linalg::YieldOp>(loc, clonedReductionOp->
getResult(0));
407 return reduction.getOperation();
413 template <
typename OpType>
415 OpType::template attachInterface<LinalgOpTilingInterface<OpType>>(*ctx);
416 OpType::template attachInterface<LinalgOpPartialReductionInterface<OpType>>(
421 template <
typename... OpTypes>
423 (registerOne<OpTypes>(ctx), ...);
431 registerOne<linalg::GenericOp>(ctx);
433 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
static SmallVector< Value > getIndicesForAccess(OpBuilder &b, Location loc, AffineMap indexingMap, ValueRange ivs)
Return the SSA values that represent the data point accessed using a given indexingMap for a given po...
static LogicalResult inlinePayload(OpBuilder &b, LinalgOp linalgOp, ValueRange ivs, ValueRange argValues)
Method to inline the payload of a linalgOp given the iteration space point and values for the argumen...
static void registerAll(MLIRContext *ctx)
Variadic helper function.
static void registerOne(MLIRContext *ctx)
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
bool isProjectedPermutation(bool allowZeroInResults=false) const
Returns true if the AffineMap represents a subset (i.e.
unsigned getNumSymbols() const
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
unsigned getNumResults() const
AffineExpr getResult(unsigned idx) const
bool isPermutation() const
Returns true if the AffineMap represents a symbol-less permutation map.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgListType getArguments()
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
IntegerAttr getIndexAttr(int64_t value)
AffineMap getMultiDimIdentityMap(unsigned rank)
AffineExpr getAffineDimExpr(unsigned position)
MLIRContext * getContext() const
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This class provides support for representing a failure result, or a valid value of type T.
This is a utility class for mapping one set of IR entities to another.
auto lookupOrDefault(T from) const
Lookup a mapped value within the map.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
IRValueT get() const
Return the current value being used by this operand.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class represents a single result from folding an operation.
This class represents an operand of an operation.
Operation is the basic unit of execution within MLIR.
void setOperand(unsigned idx, Value value)
Operation * clone(IRMapping &mapper, CloneOptions options=CloneOptions::all())
Create a deep copy of this operation, remapping any operands that use values outside of the operation...
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
MLIRContext * getContext()
Return the context this operation is associated with.
Location getLoc()
The source location the operation was defined or derived from.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
result_range getResults()
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
void cloneInto(Region *dest, IRMapping &mapper)
Clone the internal blocks from this region into dest.
This class provides an abstraction over the various different ranges of value types.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
OpFoldResult makeComposedFoldedAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineApplyOp that applies map to operands after composing the map with the maps of any...
std::optional< TypedAttr > getNeutralElement(Operation *op)
Return the identity numeric value associated to the give op.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
SmallVector< Value > makeTiledShapes(OpBuilder &builder, Location loc, LinalgOp linalgOp, ValueRange valuesToTile, ArrayRef< OpFoldResult > ivs, ArrayRef< OpFoldResult > tileSizes, ArrayRef< OpFoldResult > sizeBounds, bool omitPartialTileCheck)
Creates extract_slice/subview ops for all valuesToTile of the given linalgOp with builder,...
void offsetIndices(OpBuilder &b, LinalgOp linalgOp, ArrayRef< OpFoldResult > offests)
Add the specified offsets to any linalg.index ops contained in the given linalgOp.
void registerTilingInterfaceExternalModels(DialectRegistry ®istry)
SmallVector< Type > getTensorOutputTypes(LinalgOp op, ValueRange operands)
Returns the list of tensor output types produced when the given structured operation op is applied to...
SliceParameters computeSliceParameters(OpBuilder &builder, Location loc, Value valueToTile, ArrayRef< OpFoldResult > tileSizes, AffineMap map, ArrayRef< OpFoldResult > lbs, ArrayRef< OpFoldResult > ubs, ArrayRef< OpFoldResult > subShapeSizes, bool omitPartialTileCheck)
Computes SliceParameters for a single valueToTile assuming that its user is being tiled with the give...
Include the generated interface declarations.
void bindDims(MLIRContext *ctx, AffineExprTy &...exprs)
Bind a list of AffineExpr references to DimExpr at positions: [0 .
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Value matchReduction(ArrayRef< BlockArgument > iterCarriedArgs, unsigned redPos, SmallVectorImpl< Operation * > &combinerOps)
Utility to match a generic reduction given a list of iteration-carried arguments, iterCarriedArgs and...
void dispatchIndexOpFoldResults(ArrayRef< OpFoldResult > ofrs, SmallVectorImpl< Value > &dynamicVec, SmallVectorImpl< int64_t > &staticVec)
Helper function to dispatch multiple OpFoldResults according to the behavior of dispatchIndexOpFoldRe...
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
This class represents an efficient way to signal success or failure.
Container for result values of tiling.
A struct containg offsets-sizes-strides arguments of the tiled shape.
SmallVector< OpFoldResult > sizes
SmallVector< OpFoldResult > offsets