31 struct StructuredOpInterface
32 :
public RuntimeVerifiableOpInterface::ExternalModel<
33 StructuredOpInterface<T>, T> {
35 generateRuntimeVerification(Operation *op, OpBuilder &builder, Location loc,
37 generateErrorMessage)
const {
38 auto linalgOp = llvm::cast<LinalgOp>(op);
40 SmallVector<Range> loopRanges = linalgOp.createLoopRanges(builder, loc);
47 transform(ends, ends.begin(), [&](OpFoldResult end) {
48 auto endValue = getValueOrCreateConstantIndexOp(builder, loc, end);
49 return builder.createOrFold<index::SubOp>(loc, endValue, one);
52 for (OpOperand &opOperand : linalgOp->getOpOperands()) {
53 AffineMap indexingMap = linalgOp.getMatchingIndexingMap(&opOperand);
55 builder, loc, indexingMap, starts);
57 builder, loc, indexingMap, ends);
59 for (
auto dim : llvm::seq(linalgOp.getRank(&opOperand))) {
72 builder.createOrFold<index::MinSOp>(loc, startIndex, endIndex);
73 auto cmpOp = builder.createOrFold<index::CmpOp>(
74 loc, index::IndexCmpPredicate::SGE,
min, zero);
75 auto msg = generateErrorMessage(
76 linalgOp,
"unexpected negative result on dimension #" +
77 std::to_string(dim) +
" of input/output operand #" +
78 std::to_string(opOperand.getOperandNumber()));
79 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
87 builder.createOrFold<index::MaxSOp>(loc, startIndex, endIndex);
89 auto inferredDimSize =
90 builder.createOrFold<index::AddOp>(loc,
max, one);
99 auto predicate = isa<AffineDimExpr>(indexingMap.getResult(dim))
100 ? index::IndexCmpPredicate::EQ
101 : index::IndexCmpPredicate::SLE;
103 cmpOp = builder.createOrFold<index::CmpOp>(
104 loc, predicate, inferredDimSize, actualDimSize);
105 msg = generateErrorMessage(
106 linalgOp,
"dimension #" + std::to_string(dim) +
107 " of input/output operand #" +
108 std::to_string(opOperand.getOperandNumber()) +
109 " is incompatible with inferred dimension size");
110 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
116 template <
typename... OpTs>
117 void attachInterface(MLIRContext *ctx) {
118 (OpTs::template attachInterface<StructuredOpInterface<OpTs>>(*ctx), ...);
129 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
133 ctx->
loadDialect<affine::AffineDialect, arith::ArithDialect,
134 cf::ControlFlowDialect, index::IndexDialect,
135 tensor::TensorDialect>();
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
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.
MLIRContext is the top-level object for a collection of MLIR operations.
void loadDialect()
Load a dialect in the context.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
SmallVector< OpFoldResult > makeComposedFoldedMultiResultAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands, bool composeAffineMin=false)
Variant of makeComposedFoldedAffineApply suitable for multi-result maps.
void registerRuntimeVerifiableOpInterfaceExternalModels(DialectRegistry ®istry)
Value createOrFoldDimOp(OpBuilder &b, Location loc, Value val, int64_t dim)
Create one memref::DimOp or tensor::DimOp depending on the type of val.
Include the generated interface declarations.
llvm::function_ref< Fn > function_ref
std::tuple< SmallVector< OpFoldResult >, SmallVector< OpFoldResult >, SmallVector< OpFoldResult > > getOffsetsSizesAndStrides(ArrayRef< Range > ranges)
Given an array of Range values, return a tuple of (offset vector, sizes vector, and strides vector) f...
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.