24struct PadOpTiling :
public TilingInterface::ExternalModel<PadOpTiling, PadOp> {
25 using Base = TilingInterface::ExternalModel<PadOpTiling, PadOp>;
28 using Base::generateResultTileValue;
29 using Base::getTiledImplementation;
31 SmallVector<utils::IteratorType> getLoopIteratorTypes(Operation *op)
const {
32 auto padOp = cast<PadOp>(op);
33 SmallVector<utils::IteratorType> iteratorTypes(
34 padOp.getResultType().getRank(), utils::IteratorType::parallel);
38 SmallVector<Range> getIterationDomain(Operation *op, OpBuilder &
b)
const {
41 OpFoldResult zero =
b.getIndexAttr(0);
42 OpFoldResult one =
b.getIndexAttr(1);
45 SmallVector<Range> loopRanges(reifiedShapes[0].size(), {zero, one, one});
46 for (
const auto &ub :
enumerate(reifiedShapes[0]))
47 loopRanges[ub.index()].size = ub.value();
51 FailureOr<TilingResult>
53 ArrayRef<OpFoldResult> offsets,
54 ArrayRef<OpFoldResult> sizes)
const {
55 FailureOr<TilingResult>
result =
64 ArrayRef<OpFoldResult> offsets,
65 ArrayRef<OpFoldResult> sizes,
66 SmallVector<OpFoldResult> &resultOffsets,
67 SmallVector<OpFoldResult> &resultSizes)
const {
68 resultOffsets.assign(offsets.begin(), offsets.end());
69 resultSizes.assign(sizes.begin(), sizes.end());
73 LogicalResult getIterationDomainTileFromResultTile(
74 Operation *op, OpBuilder &
b,
unsigned resultNumber,
75 ArrayRef<OpFoldResult> offsets, ArrayRef<OpFoldResult> sizes,
76 SmallVectorImpl<OpFoldResult> &iterDomainOffsets,
77 SmallVectorImpl<OpFoldResult> &iterDomainSizes)
const {
78 iterDomainOffsets.assign(offsets.begin(), offsets.end());
79 iterDomainSizes.assign(sizes.begin(), sizes.end());
83 FailureOr<TilingResult>
84 generateResultTileValue(Operation *op, OpBuilder &
b,
unsigned resultNumber,
85 ArrayRef<OpFoldResult> offsets,
86 ArrayRef<OpFoldResult> sizes)
const {
97 bool generateZeroSliceGuard) {
99 Value padValue = padOp.getConstantPaddingValue();
129 bool hasZeroLen =
false;
132 Value dynHasZeroLenCond;
134 int64_t rank = padOp.getSourceType().getRank();
137 for (
unsigned dim = 0; dim < rank; ++dim) {
138 auto low = padOp.getMixedLowPad()[dim];
140 auto high = padOp.getMixedHighPad()[dim];
142 auto offset = offsets[dim];
143 auto length = sizes[dim];
146 if (!hasLowPad && !hasHighPad) {
147 newOffsets.push_back(offset);
148 newLengths.push_back(length);
149 newLows.push_back(low);
150 newHighs.push_back(high);
162 newLows.push_back(newLow);
177 ?
min(
max(sub(offset, low), zero), srcSize)
178 :
min(offset, srcSize);
179 newOffsets.push_back(newOffset);
203 OpFoldResult newLength =
min(sub(srcSize, newOffset), sub(length, newLow));
207 newLength =
max(newLength, zero);
208 newLengths.push_back(newLength);
214 }
else if (!hasZeroLen) {
215 Value check = arith::CmpIOp::create(
216 b, loc, arith::CmpIPredicate::eq,
221 ? arith::OrIOp::create(
b, loc, check, dynHasZeroLenCond)
230 hasHighPad ? sub(sub(length, newLength), newLow) : zero;
231 newHighs.push_back(newHigh);
238 RankedTensorType resultType =
239 RankedTensorType::get(
shape, padOp.getResultType().getElementType());
243 if (resultType == val.getType())
245 return tensor::CastOp::create(
b, loc, resultType, val);
251 auto createGenerateOp = [&]() {
253 auto generateOp = tensor::GenerateOp::create(
254 b, loc, resultType, dynDims,
256 tensor::YieldOp::create(builder, gLoc, padValue);
263 auto createPadOfExtractSlice = [&]() {
265 auto newSliceOp = tensor::ExtractSliceOp::create(
266 b, loc, padOp.getSource(), newOffsets, newLengths, newStrides);
267 auto newPadOp = PadOp::create(
268 b, loc,
Type(), newSliceOp, newLows, newHighs,
274 padOp.getRegion().cloneInto(&newPadOp.getRegion(), bvm);
277 return std::make_tuple(newPadOp, newSliceOp);
283 Operation *generateOp = createGenerateOp();
291 if (generateZeroSliceGuard && dynHasZeroLenCond) {
295 auto result = scf::IfOp::create(
296 b, loc, dynHasZeroLenCond,
299 thenOp = createGenerateOp();
300 scf::YieldOp::create(
b, loc, castResult(thenOp->
getResult(0)));
304 std::tie(elseOp, sliceOp) = createPadOfExtractSlice();
305 scf::YieldOp::create(
b, loc, castResult(elseOp->
getResult(0)));
311 auto [newPadOp, sliceOp] = createPadOfExtractSlice();
313 {newPadOp}, {castResult(newPadOp->getResult(0))}, {sliceOp}};
319 tensor::PadOp::attachInterface<PadOpTiling>(*ctx);
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static LogicalResult getResultTilePosition(RewriterBase &rewriter, ReductionTilingStrategy reductionStrategy, int64_t index, Value tiledResult, TilingInterface op, ArrayRef< OpFoldResult > offsets, ArrayRef< OpFoldResult > sizes, ValueRange ivs, ArrayRef< OpFoldResult > numThreads, ArrayRef< OpFoldResult > givenTileSizes, const SetVector< unsigned > &reductionDims, SmallVector< OpFoldResult > &resultOffset, SmallVector< OpFoldResult > &resultSize)
static FailureOr< TilingResult > getTiledImplementation(RewriterBase &rewriter, TilingInterface op, ReductionTilingStrategy reductionStrategy, ValueRange regionIterArg, ArrayRef< OpFoldResult > offsets, ArrayRef< OpFoldResult > sizes, ValueRange ivs, ArrayRef< OpFoldResult > numThreads, ArrayRef< OpFoldResult > givenTileSizes, ArrayRef< InnerTileAlignment > innerTileAlignments, const SetVector< unsigned > &reductionDims)
Base type for affine expression.
static AffineMap getMultiDimIdentityMap(unsigned numDims, MLIRContext *context)
Returns an AffineMap with 'numDims' identity result dim exprs.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This is a utility class for mapping one set of IR entities to another.
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.
This class helps build Operations.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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...
OpFoldResult makeComposedFoldedAffineMax(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineMinOp that computes a maximum across the results of applying map to operands,...
OpFoldResult makeComposedFoldedAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands, bool composeAffineMin=false)
Constructs an AffineApplyOp that applies map to operands after composing the map with the maps of any...
OpFoldResult makeComposedFoldedAffineMin(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
Constructs an AffineMinOp that computes a minimum across the results of applying map to operands,...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
FailureOr< TilingResult > bubbleUpPadSlice(OpBuilder &b, tensor::PadOp padOp, ArrayRef< OpFoldResult > offsets, ArrayRef< OpFoldResult > sizes, bool generateZeroSliceGuard=true)
Bubbles up a slice of this pad by taking the slice first and then performing the padding.
void registerTilingInterfaceExternalModels(mlir::DialectRegistry ®istry)
Registers external models for Tiling interface for tensor ops.
OpFoldResult getMixedSize(OpBuilder &builder, Location loc, Value value, int64_t dim)
Return the dimension of the given tensor value.
Include the generated interface declarations.
LogicalResult reifyResultShapes(OpBuilder &b, Operation *op, ReifiedRankedShapedTypeDims &reifiedReturnShapes)
Reify the shape of the result of an operation (typically in terms of the shape of its operands).
void bindDims(MLIRContext *ctx, AffineExprTy &...exprs)
Bind a list of AffineExpr references to DimExpr at positions: [0 .
SmallVector< SmallVector< OpFoldResult > > ReifiedRankedShapedTypeDims
bool isZeroInteger(OpFoldResult v)
Return "true" if v is an integer value/attribute with constant value 0.
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.
SmallVector< NamedAttribute > getPrunedAttributeList(Operation *op, ArrayRef< StringRef > elidedAttrs)
Container for result values of tiling.