23 #include "llvm/ADT/STLExtras.h" 
   24 #include "llvm/Support/Casting.h" 
   26 #define DEBUG_TYPE "pad-tiling-interface" 
   32 #define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE << "]: ")
 
   33 #define DBGSNL() (llvm::dbgs() << "\n")
 
   41   for (
size_t idx = 0, e = indexingSizes.size(); idx != e; ++idx) {
 
   43     paddingSizes.push_back(
options.paddingSizes.size() > idx
 
   53     LLVM_DEBUG(
DBGS() << 
"----idx: " << idx << 
" : " << paddingSizes[idx]
 
   64   if (
auto binOp = dyn_cast<AffineBinaryOpExpr>(expr)) {
 
   66       auto lhsD = dyn_cast<AffineDimExpr>(binOp.getLHS());
 
   67       auto rhsC = dyn_cast<AffineConstantExpr>(binOp.getRHS());
 
   69         return rhsC.getValue();
 
   71       auto lhsC = dyn_cast<AffineConstantExpr>(binOp.getLHS());
 
   72       auto rhsD = dyn_cast<AffineDimExpr>(binOp.getRHS());
 
   74         return lhsC.getValue();
 
  105   auto tensorType = cast<RankedTensorType>(v.getType());
 
  106   paddedShape.resize_for_overwrite(tensorType.getRank());
 
  107   assert(tensorType.getRank() == indexingMap.
getNumResults() &&
 
  108          "expect the number of results of the affine map to match the tensor " 
  118     int64_t resultIndex = enResults.index();
 
  122     LLVM_DEBUG(
DBGS() << 
"----resultIndex: " << resultIndex
 
  123                       << 
" with partialIndexingMap: " << partialIndexingMap
 
  129     for (
size_t paddingDim = 0, e = paddingSizes.size(); paddingDim != e;
 
  132       LLVM_DEBUG(
DBGS() << 
"------try apply padding of dim: " << paddingDim
 
  133                         << 
" to: " << paddingSize << 
"\n");
 
  134       if (!enResults.value().isFunctionOfDim(paddingDim))
 
  137       LLVM_DEBUG(
DBGS() << 
"------apply padding of dim: " << paddingDim
 
  138                         << 
" to: " << paddingSize << 
"\n");
 
  141       llvm::SmallBitVector projectedDims(partialIndexingMap.
getNumDims(), 
true);
 
  142       projectedDims.flip(paddingDim);
 
  156             builder, loc, composedMap, {indexingSizes[paddingDim], paddingSize},
 
  161             builder, loc, projectedMap, paddingSize);
 
  171           builder, loc, subtractMap, {paddingDimOfr});
 
  172       terms.push_back(maxAccessIdx);
 
  174       LLVM_DEBUG(
DBGS() << 
"------new term: " << terms.back() << 
"\n");
 
  179       paddedShape[resultIndex] =
 
  188     for (
unsigned i = 1; i < dims.size(); ++i)
 
  189       sumExpr = sumExpr + dims[i];
 
  193     paddedShape[resultIndex] = paddedDimOfr;
 
  199 FailureOr<SmallVector<OpFoldResult>>
 
  204       llvm::dyn_cast<IndexingMapOpInterface>(operandToPad.
getOwner());
 
  209   assert(llvm::all_of(iterationDomain, [&builder](
Range r) {
 
  212   }) && 
"expected 0-offset 1-stride loop ranges");
 
  215   loopUpperBounds.reserve(iterationDomain.size());
 
  216   for (
const Range &range : iterationDomain)
 
  217     loopUpperBounds.push_back(range.size);
 
  219   AffineMap indexingMap = transferOp.getMatchingIndexingMap(&operandToPad);
 
  222       indexingMap, loopUpperBounds, 
options);
 
  234     if (
auto complexAttr = dyn_cast<ArrayAttr>(paddingValueAttr)) {
 
  235       paddingValue = complex::ConstantOp::create(builder, opToPad.getLoc(),
 
  236                                                  complexTy, complexAttr);
 
  238   } 
else if (isa<ub::PoisonAttr>(paddingValueAttr)) {
 
  239     paddingValue = ub::PoisonOp::create(builder, opToPad.getLoc(),
 
  241   } 
else if (
auto typedAttr = dyn_cast<TypedAttr>(paddingValueAttr)) {
 
  243         arith::ConstantOp::create(builder, opToPad.getLoc(), typedAttr);
 
  245   assert(paddingValue && 
"failed to create value from padding attribute");
 
  252     tensorShape.push_back(cst.has_value() ? *cst : ShapedType::kDynamic);
 
  253     if (!cst.has_value())
 
  254       dynDims.push_back(ofr.dyn_cast<
Value>());
 
  258   auto paddedTensorType =
 
  260   LLVM_DEBUG(
DBGS() << 
"--SUCCESS, makeComposedPadHighOp with type: " 
  261                     << paddedTensorType);
 
  263                                paddingValue, 
false, dynDims);
 
  267     OpBuilder &builder, TilingInterface toPad,
 
  270   LLVM_DEBUG(
DBGS() << 
"Start rewriteAsPaddedOp : " << toPad << 
"\n");
 
  276   if (
options.paddingValues.empty()) {
 
  278     llvm::append_range(types, toPad->getResultTypes());
 
  279     for (
Type t : types) {
 
  280       options.paddingValues.push_back(
 
  285   if (llvm::any_of(toPad->getOperands(),
 
  286                    [](
Value v) { return isa<MemRefType>(v.getType()); })) {
 
  287     LLVM_DEBUG(
DBGS() << 
"Not an operation on tensors: FAIL\n");
 
  296   newOperands.reserve(toPad->getNumOperands());
 
  297   for (
OpOperand &opOperand : toPad->getOpOperands()) {
 
  298     Value operand = opOperand.get();
 
  299     LLVM_DEBUG(
DBGS() << 
"--start padding operand: " << operand << 
"\n");
 
  303     if (!isa<RankedTensorType>(operandType)) {
 
  304       assert((!isa<ShapedType>(operandType) || isa<VectorType>(operandType)) &&
 
  305              "Unexpected non-vector ShapedType");
 
  306       newOperands.push_back(operand);
 
  311     FailureOr<SmallVector<OpFoldResult>> maybePaddedShape =
 
  312         computePaddingSizeFun(builder, opOperand, iterationDomain, 
options);
 
  313     if (
failed(maybePaddedShape)) {
 
  314       LLVM_DEBUG(
DBGS() << 
"Could not get padded shape of operand: FAIL\n");
 
  321     if (opOperand.getOperandNumber() >= 
options.paddingValues.size()) {
 
  322       LLVM_DEBUG(
DBGS() << 
"Too few padding values specified: FAIL\n");
 
  326         options.paddingValues[opOperand.getOperandNumber()];
 
  329     Value paddedOperand =
 
  331                    *maybePaddedShape, paddingValueAttr);
 
  332     LLVM_DEBUG(
DBGS() << 
"--done padding operand: " << paddedOperand << 
"\n");
 
  334     newOperands.push_back(paddedOperand);
 
  335     if (
auto padOp = paddedOperand.
getDefiningOp<tensor::PadOp>())
 
  336       padOps.push_back(padOp);
 
  342     LLVM_DEBUG(
DBGS() << 
"Failed to reify result shapes: FAIL\n");
 
  345   assert(reifiedResultShapes.size() == toPad->getNumResults() &&
 
  346          "expected same number of results");
 
  349   auto resultTensorTypes =
 
  352   TilingInterface paddedOp =
 
  353       clone(builder, toPad, resultTensorTypes, newOperands);
 
  354   LLVM_DEBUG(
DBGS() << 
"--cloned padded op: " << paddedOp << 
"\n");
 
  358   paddedSubtensorResults.reserve(toPad->getNumResults());
 
  360     Value paddedResult = en.value();
 
  361     int64_t resultNumber = en.index();
 
  362     int64_t rank = cast<RankedTensorType>(paddedResult.
getType()).getRank();
 
  365     paddedSubtensorResults.push_back(tensor::ExtractSliceOp::create(
 
  366         builder, loc, paddedResult, offsets, reifiedResultShapes[resultNumber],
 
static int64_t extractConstantMultiplier(AffineExpr expr)
Extracts the constant multiplier from an affine expression of the form d * c or c * d,...
static SmallVector< OpFoldResult > getFullRankPaddingSizes(Builder &b, ArrayRef< OpFoldResult > indexingSizes, const PadTilingInterfaceOptions &options)
Form a "full-rank" padding specification so that the application is easy.
static Value padOperand(OpBuilder &builder, TilingInterface opToPad, TypedValue< RankedTensorType > v, ArrayRef< OpFoldResult > paddedShape, Attribute paddingValueAttr)
Pad a single operand to paddedShape using paddingValueAttr as padding Value.
static llvm::ManagedStatic< PassManagerOptions > options
Base type for affine expression.
AffineExpr ceilDiv(uint64_t v) const
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: () -> ().
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
unsigned getNumResults() const
AffineExpr getResult(unsigned idx) const
AffineMap getSubMap(ArrayRef< unsigned > resultPos) const
Returns the map consisting of the resultPos subset.
AffineMap compose(AffineMap map) const
Returns the AffineMap resulting from composing this with map.
Attributes are known-constant values of operations.
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getIndexAttr(int64_t value)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
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...
This class helps build Operations.
This class represents a single result from folding an operation.
This class represents an operand of an 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.
type_range getTypes() const
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.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Operation * getOwner() const
Return the owner of this operand.
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...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
LogicalResult rewriteAsPaddedOp(RewriterBase &rewriter, LinalgOp opToPad, const LinalgPaddingOptions &options, LinalgOp &paddedOp, SmallVector< Value > &replacements, SmallVector< tensor::PadOp > &padOps)
Pad the iterator dimensions options.paddingDimensions of all opToPad operands to a static bounding bo...
SmallVector< OpFoldResult > computePaddedShape(OpBuilder &, TypedValue< RankedTensorType > v, AffineMap indexingMap, ArrayRef< OpFoldResult > indexingSizes, const PadTilingInterfaceOptions &options)
Helper function to compute the padded shape of the given value v of RankedTensorType given:
OpFoldResult createFoldedDimOp(OpBuilder &b, Location loc, Value val, int64_t dim)
Create one memref::DimOp or tensor::DimOp depending on the type of val.
std::function< FailureOr< SmallVector< OpFoldResult > >(OpBuilder &, OpOperand &, ArrayRef< Range >, const PadTilingInterfaceOptions &)> PadSizeComputationFunction
FailureOr< SmallVector< OpFoldResult > > computeIndexingMapOpInterfacePaddedShape(OpBuilder &, OpOperand &operandToPad, ArrayRef< Range > iterationDomain, const PadTilingInterfaceOptions &)
Specific helper for Linalg ops.
Value makeComposedPadHighOp(OpBuilder &b, Location loc, RankedTensorType type, Value source, Value padding, bool nofold, ValueRange typeDynDims={})
Create a tensor::PadOp that pads source to the shape of type whose sizes are assumed to be greater th...
Include the generated interface declarations.
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
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 bindDimsList(MLIRContext *ctx, MutableArrayRef< AffineExprTy > exprs)
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
void bindDims(MLIRContext *ctx, AffineExprTy &...exprs)
Bind a list of AffineExpr references to DimExpr at positions: [0 .
@ Mul
RHS of mul is always a constant or a symbolic expression.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
bool isZeroInteger(OpFoldResult v)
Return true if v is an IntegerAttr with value 0.
void bindSymbols(MLIRContext *ctx, AffineExprTy &...exprs)
Bind a list of AffineExpr references to SymbolExpr at positions: [0 .
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
AffineMap projectDims(AffineMap map, const llvm::SmallBitVector &projectedDimensions, bool compressDimsFlag=false)
Returns the map that results from projecting out the dimensions specified in projectedDimensions.
Represents a range (offset, size, and stride) where each element of the triple may be dynamic or stat...
Operations and values created in the process of padding a TilingInterface operation.