31 struct StructuredOpInterface
32 :
public RuntimeVerifiableOpInterface::ExternalModel<
33 StructuredOpInterface<T>, T> {
34 void generateRuntimeVerification(Operation *op, OpBuilder &builder,
36 auto linalgOp = llvm::cast<LinalgOp>(op);
38 SmallVector<Range> loopRanges = linalgOp.createLoopRanges(builder, loc);
41 auto zero = builder.create<arith::ConstantIndexOp>(loc, 0);
42 auto one = builder.create<arith::ConstantIndexOp>(loc, 1);
45 transform(ends, ends.begin(), [&](OpFoldResult end) {
46 auto endValue = getValueOrCreateConstantIndexOp(builder, loc, end);
47 return builder.createOrFold<index::SubOp>(loc, endValue, one);
50 for (OpOperand &opOperand : linalgOp->getOpOperands()) {
51 AffineMap indexingMap = linalgOp.getMatchingIndexingMap(&opOperand);
53 builder, loc, indexingMap, starts);
55 builder, loc, indexingMap, ends);
57 for (
auto dim : llvm::seq(linalgOp.getRank(&opOperand))) {
70 builder.createOrFold<index::MinSOp>(loc, startIndex, endIndex);
71 auto cmpOp = builder.createOrFold<index::CmpOp>(
72 loc, index::IndexCmpPredicate::SGE,
min, zero);
73 auto msg = RuntimeVerifiableOpInterface::generateErrorMessage(
74 linalgOp,
"unexpected negative result on dimension #" +
75 std::to_string(dim) +
" of input/output operand #" +
76 std::to_string(opOperand.getOperandNumber()));
77 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
85 builder.createOrFold<index::MaxSOp>(loc, startIndex, endIndex);
87 auto inferredDimSize =
88 builder.createOrFold<index::AddOp>(loc,
max, one);
97 auto predicate = isa<AffineDimExpr>(indexingMap.getResult(dim))
98 ? index::IndexCmpPredicate::EQ
99 : index::IndexCmpPredicate::SLE;
101 cmpOp = builder.createOrFold<index::CmpOp>(
102 loc, predicate, inferredDimSize, actualDimSize);
103 msg = RuntimeVerifiableOpInterface::generateErrorMessage(
104 linalgOp,
"dimension #" + std::to_string(dim) +
105 " of input/output operand #" +
106 std::to_string(opOperand.getOperandNumber()) +
107 " is incompatible with inferred dimension size");
108 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
114 template <
typename... OpTs>
115 void attachInterface(MLIRContext *ctx) {
116 (OpTs::template attachInterface<StructuredOpInterface<OpTs>>(*ctx), ...);
127 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
131 ctx->
loadDialect<affine::AffineDialect, arith::ArithDialect,
132 cf::ControlFlowDialect, index::IndexDialect,
133 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.
SmallVector< OpFoldResult > makeComposedFoldedMultiResultAffineApply(OpBuilder &b, Location loc, AffineMap map, ArrayRef< OpFoldResult > operands)
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.
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.