30       loc, arith::CmpIPredicate::sge, value, lb);
 
   32       loc, arith::CmpIPredicate::slt, value, ub);
 
   34       builder.
createOrFold<arith::AndIOp>(loc, inBounds1, inBounds2);
 
   38 struct AssumeAlignmentOpInterface
 
   39     : 
public RuntimeVerifiableOpInterface::ExternalModel<
 
   40           AssumeAlignmentOpInterface, AssumeAlignmentOp> {
 
   44                                   generateErrorMessage)
 const {
 
   45     auto assumeOp = cast<AssumeAlignmentOp>(op);
 
   46     Value ptr = ExtractAlignedPointerAsIndexOp::create(builder, loc,
 
   47                                                        assumeOp.getMemref());
 
   48     Value rest = arith::RemUIOp::create(
 
   52         arith::CmpIOp::create(builder, loc, arith::CmpIPredicate::eq, rest,
 
   55         builder, loc, isAligned,
 
   56         generateErrorMessage(op, 
"memref is not aligned to " +
 
   57                                      std::to_string(assumeOp.getAlignment())));
 
   61 struct CastOpInterface
 
   62     : 
public RuntimeVerifiableOpInterface::ExternalModel<CastOpInterface,
 
   67                                   generateErrorMessage)
 const {
 
   68     auto castOp = cast<CastOp>(op);
 
   69     auto srcType = cast<BaseMemRefType>(castOp.getSource().getType());
 
   72     auto resultType = dyn_cast<MemRefType>(castOp.getType());
 
   76     if (isa<UnrankedMemRefType>(srcType)) {
 
   78       Value srcRank = RankOp::create(builder, loc, castOp.getSource());
 
   81       Value isSameRank = arith::CmpIOp::create(
 
   82           builder, loc, arith::CmpIPredicate::eq, srcRank, resultRank);
 
   83       cf::AssertOp::create(builder, loc, isSameRank,
 
   84                            generateErrorMessage(op, 
"rank mismatch"));
 
   91     int64_t dynamicOffset = ShapedType::kDynamic;
 
   93                                       ShapedType::kDynamic);
 
   95                                                 dynamicOffset, dynamicShape);
 
   98                         stridedLayout, resultType.getMemorySpace());
 
  100         CastOp::create(builder, loc, dynStridesType, castOp.getSource());
 
  102         ExtractStridedMetadataOp::create(builder, loc, helperCast);
 
  107       if (
auto rankedSrcType = dyn_cast<MemRefType>(srcType))
 
  108         if (!rankedSrcType.isDynamicDim(it.index()))
 
  112       if (resultType.isDynamicDim(it.index()))
 
  116           DimOp::create(builder, loc, castOp.getSource(), it.index());
 
  119       Value isSameSz = arith::CmpIOp::create(
 
  120           builder, loc, arith::CmpIPredicate::eq, srcDimSz, resultDimSz);
 
  121       cf::AssertOp::create(
 
  122           builder, loc, isSameSz,
 
  123           generateErrorMessage(op, 
"size mismatch of dim " +
 
  124                                        std::to_string(it.index())));
 
  128     int64_t resultOffset;
 
  130     if (
failed(resultType.getStridesAndOffset(resultStrides, resultOffset)))
 
  134     if (resultOffset != ShapedType::kDynamic) {
 
  136       Value srcOffset = metadataOp.getResult(1);
 
  137       Value resultOffsetVal =
 
  139       Value isSameOffset = arith::CmpIOp::create(
 
  140           builder, loc, arith::CmpIPredicate::eq, srcOffset, resultOffsetVal);
 
  141       cf::AssertOp::create(builder, loc, isSameOffset,
 
  142                            generateErrorMessage(op, 
"offset mismatch"));
 
  148       if (it.value() == ShapedType::kDynamic)
 
  152           metadataOp.getResult(2 + resultType.getRank() + it.index());
 
  153       Value resultStrideVal =
 
  155       Value isSameStride = arith::CmpIOp::create(
 
  156           builder, loc, arith::CmpIPredicate::eq, srcStride, resultStrideVal);
 
  157       cf::AssertOp::create(
 
  158           builder, loc, isSameStride,
 
  159           generateErrorMessage(op, 
"stride mismatch of dim " +
 
  160                                        std::to_string(it.index())));
 
  165 struct CopyOpInterface
 
  166     : 
public RuntimeVerifiableOpInterface::ExternalModel<CopyOpInterface,
 
  171                                   generateErrorMessage)
 const {
 
  172     auto copyOp = cast<CopyOp>(op);
 
  175     auto rankedSourceType = dyn_cast<MemRefType>(sourceType);
 
  176     auto rankedTargetType = dyn_cast<MemRefType>(targetType);
 
  179     if (!rankedSourceType || !rankedTargetType)
 
  182     assert(sourceType.getRank() == targetType.getRank() && 
"rank mismatch");
 
  183     for (int64_t i = 0, e = sourceType.getRank(); i < e; ++i) {
 
  186       if (!rankedSourceType.isDynamicDim(i) &&
 
  187           !rankedTargetType.isDynamicDim(i))
 
  189       auto getDimSize = [&](
Value memRef, MemRefType type,
 
  190                             int64_t dim) -> 
Value {
 
  191         return type.isDynamicDim(dim)
 
  192                    ? DimOp::create(builder, loc, memRef, dim).getResult()
 
  194                                                     type.getDimSize(dim))
 
  197       Value sourceDim = getDimSize(copyOp.getSource(), rankedSourceType, i);
 
  198       Value targetDim = getDimSize(copyOp.getTarget(), rankedTargetType, i);
 
  199       Value sameDimSize = arith::CmpIOp::create(
 
  200           builder, loc, arith::CmpIPredicate::eq, sourceDim, targetDim);
 
  201       cf::AssertOp::create(
 
  202           builder, loc, sameDimSize,
 
  203           generateErrorMessage(op, 
"size of " + std::to_string(i) +
 
  204                                        "-th source/target dim does not match"));
 
  209 struct DimOpInterface
 
  210     : 
public RuntimeVerifiableOpInterface::ExternalModel<DimOpInterface,
 
  215                                   generateErrorMessage)
 const {
 
  216     auto dimOp = cast<DimOp>(op);
 
  217     Value rank = RankOp::create(builder, loc, dimOp.getSource());
 
  219     cf::AssertOp::create(
 
  221         generateInBoundsCheck(builder, loc, dimOp.getIndex(), zero, rank),
 
  222         generateErrorMessage(op, 
"index is out of bounds"));
 
  228 template <
typename LoadStoreOp>
 
  229 struct LoadStoreOpInterface
 
  230     : 
public RuntimeVerifiableOpInterface::ExternalModel<
 
  231           LoadStoreOpInterface<LoadStoreOp>, LoadStoreOp> {
 
  235                                   generateErrorMessage)
 const {
 
  236     auto loadStoreOp = cast<LoadStoreOp>(op);
 
  238     auto memref = loadStoreOp.getMemref();
 
  239     auto rank = memref.
getType().getRank();
 
  243     auto indices = loadStoreOp.getIndices();
 
  247     for (
auto i : llvm::seq<int64_t>(0, rank)) {
 
  250           generateInBoundsCheck(builder, loc, indices[i], zero, dimOp);
 
  252           i > 0 ? builder.
createOrFold<arith::AndIOp>(loc, assertCond, inBounds)
 
  255     cf::AssertOp::create(builder, loc, assertCond,
 
  256                          generateErrorMessage(op, 
"out-of-bounds access"));
 
  260 struct SubViewOpInterface
 
  261     : 
public RuntimeVerifiableOpInterface::ExternalModel<SubViewOpInterface,
 
  266                                   generateErrorMessage)
 const {
 
  267     auto subView = cast<SubViewOp>(op);
 
  268     MemRefType sourceType = subView.getSource().getType();
 
  276         ExtractStridedMetadataOp::create(builder, loc, subView.getSource());
 
  277     for (int64_t i : llvm::seq<int64_t>(0, sourceType.getRank())) {
 
  281           builder, loc, subView.getMixedOffsets()[i]);
 
  283                                                    subView.getMixedSizes()[i]);
 
  285           builder, loc, subView.getMixedStrides()[i]);
 
  288       Value dimSize = metadataOp.getSizes()[i];
 
  289       Value offsetInBounds =
 
  290           generateInBoundsCheck(builder, loc, offset, zero, dimSize);
 
  291       cf::AssertOp::create(builder, loc, offsetInBounds,
 
  292                            generateErrorMessage(op, 
"offset " +
 
  294                                                         " is out-of-bounds"));
 
  297       Value sizeIsNonZero = arith::CmpIOp::create(
 
  298           builder, loc, arith::CmpIPredicate::sgt, size, zero);
 
  300       auto ifOp = scf::IfOp::create(builder, loc, builder.
getI1Type(),
 
  301                                     sizeIsNonZero, 
true);
 
  307       Value sizeMinusOne = arith::SubIOp::create(builder, loc, size, one);
 
  308       Value sizeMinusOneTimesStride =
 
  309           arith::MulIOp::create(builder, loc, sizeMinusOne, stride);
 
  311           arith::AddIOp::create(builder, loc, offset, sizeMinusOneTimesStride);
 
  312       Value lastPosInBounds =
 
  313           generateInBoundsCheck(builder, loc, lastPos, zero, dimSize);
 
  315       scf::YieldOp::create(builder, loc, lastPosInBounds);
 
  320           arith::ConstantOp::create(builder, loc, builder.
getBoolAttr(
true));
 
  321       scf::YieldOp::create(builder, loc, trueVal);
 
  324       Value finalCondition = ifOp.getResult(0);
 
  326       cf::AssertOp::create(
 
  327           builder, loc, finalCondition,
 
  328           generateErrorMessage(op,
 
  329                                "subview runs out-of-bounds along dimension " +
 
  335 struct ExpandShapeOpInterface
 
  336     : 
public RuntimeVerifiableOpInterface::ExternalModel<ExpandShapeOpInterface,
 
  341                                   generateErrorMessage)
 const {
 
  342     auto expandShapeOp = cast<ExpandShapeOp>(op);
 
  346     for (
const auto &it :
 
  349           DimOp::create(builder, loc, expandShapeOp.getSrc(), it.index());
 
  351       bool foundDynamicDim = 
false;
 
  352       for (int64_t resultDim : it.value()) {
 
  353         if (expandShapeOp.getResultType().isDynamicDim(resultDim)) {
 
  355           assert(!foundDynamicDim &&
 
  356                  "more than one dynamic dim found in reassoc group");
 
  357           (void)foundDynamicDim;
 
  358           foundDynamicDim = 
true;
 
  361         groupSz *= expandShapeOp.getResultType().getDimSize(resultDim);
 
  363       Value staticResultDimSz =
 
  367           arith::RemSIOp::create(builder, loc, srcDimSz, staticResultDimSz);
 
  368       Value isModZero = arith::CmpIOp::create(
 
  369           builder, loc, arith::CmpIPredicate::eq, mod,
 
  371       cf::AssertOp::create(
 
  372           builder, loc, isModZero,
 
  373           generateErrorMessage(op, 
"static result dims in reassoc group do not " 
  374                                    "divide src dim evenly"));
 
  385     AssumeAlignmentOp::attachInterface<AssumeAlignmentOpInterface>(*ctx);
 
  386     AtomicRMWOp::attachInterface<LoadStoreOpInterface<AtomicRMWOp>>(*ctx);
 
  387     CastOp::attachInterface<CastOpInterface>(*ctx);
 
  388     CopyOp::attachInterface<CopyOpInterface>(*ctx);
 
  389     DimOp::attachInterface<DimOpInterface>(*ctx);
 
  390     ExpandShapeOp::attachInterface<ExpandShapeOpInterface>(*ctx);
 
  391     GenericAtomicRMWOp::attachInterface<
 
  392         LoadStoreOpInterface<GenericAtomicRMWOp>>(*ctx);
 
  393     LoadOp::attachInterface<LoadStoreOpInterface<LoadOp>>(*ctx);
 
  394     StoreOp::attachInterface<LoadStoreOpInterface<StoreOp>>(*ctx);
 
  395     SubViewOp::attachInterface<SubViewOpInterface>(*ctx);
 
  399     ctx->loadDialect<affine::AffineDialect, arith::ArithDialect,
 
  400                      cf::ControlFlowDialect>();
 
This class provides a shared interface for ranked and unranked memref types.
BoolAttr getBoolAttr(bool value)
MLIRContext * getContext() const
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 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.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Operation is the basic unit of execution within MLIR.
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.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
void registerRuntimeVerifiableOpInterfaceExternalModels(DialectRegistry ®istry)
Include the generated interface declarations.
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...