32 struct StructuredOpInterface
33 :
public RuntimeVerifiableOpInterface::ExternalModel<
34 StructuredOpInterface<T>, T> {
36 generateRuntimeVerification(Operation *op, OpBuilder &builder, Location loc,
38 generateErrorMessage)
const {
39 auto linalgOp = llvm::cast<LinalgOp>(op);
41 SmallVector<Range> loopRanges = linalgOp.createLoopRanges(builder, loc);
47 Value iterationDomainIsNonDegenerate;
48 for (
auto [start, end] : llvm::zip(starts, ends)) {
53 Value dimensionHasNonZeroTripCount = index::CmpOp::create(
54 builder, loc, index::IndexCmpPredicate::SLT, startValue, endValue);
56 if (!iterationDomainIsNonDegenerate) {
57 iterationDomainIsNonDegenerate = dimensionHasNonZeroTripCount;
61 iterationDomainIsNonDegenerate =
62 arith::AndIOp::create(builder, loc, iterationDomainIsNonDegenerate,
63 dimensionHasNonZeroTripCount);
67 if (!iterationDomainIsNonDegenerate)
70 auto ifOp = scf::IfOp::create(builder, loc, iterationDomainIsNonDegenerate,
72 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
75 transform(ends, ends.begin(), [&](OpFoldResult end) {
76 auto endValue = getValueOrCreateConstantIndexOp(builder, loc, end);
77 return builder.createOrFold<index::SubOp>(loc, endValue, one);
80 for (OpOperand &opOperand : linalgOp->getOpOperands()) {
81 AffineMap indexingMap = linalgOp.getMatchingIndexingMap(&opOperand);
83 builder, loc, indexingMap, starts);
85 builder, loc, indexingMap, ends);
87 for (
auto dim : llvm::seq(linalgOp.getRank(&opOperand))) {
100 builder.createOrFold<index::MinSOp>(loc, startIndex, endIndex);
101 auto cmpOp = builder.createOrFold<index::CmpOp>(
102 loc, index::IndexCmpPredicate::SGE,
min, zero);
103 auto msg = generateErrorMessage(
104 linalgOp,
"unexpected negative result on dimension #" +
105 std::to_string(dim) +
" of input/output operand #" +
106 std::to_string(opOperand.getOperandNumber()));
107 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
115 builder.createOrFold<index::MaxSOp>(loc, startIndex, endIndex);
117 auto inferredDimSize =
118 builder.createOrFold<index::AddOp>(loc,
max, one);
127 auto predicate = isa<AffineDimExpr>(indexingMap.getResult(dim))
128 ? index::IndexCmpPredicate::EQ
129 : index::IndexCmpPredicate::SLE;
131 cmpOp = builder.createOrFold<index::CmpOp>(
132 loc, predicate, inferredDimSize, actualDimSize);
133 msg = generateErrorMessage(
134 linalgOp,
"dimension #" + std::to_string(dim) +
135 " of input/output operand #" +
136 std::to_string(opOperand.getOperandNumber()) +
137 " is incompatible with inferred dimension size");
138 builder.createOrFold<cf::AssertOp>(loc, cmpOp, msg);
141 builder.setInsertionPointAfter(ifOp);
145 template <
typename... OpTs>
146 void attachInterface(MLIRContext *ctx) {
147 (OpTs::template attachInterface<StructuredOpInterface<OpTs>>(*ctx), ...);
158 #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc"
162 ctx->
loadDialect<affine::AffineDialect, arith::ArithDialect,
163 cf::ControlFlowDialect, index::IndexDialect,
164 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.