#include "mlir/Interfaces/IndexingMapOpInterface.h"
using namespace mlir;
namespace mlir {
#include "mlir/Interfaces/IndexingMapOpInterface.cpp.inc"
}
LogicalResult mlir::IndexingMapOpInterface::verifyImpl() {
if (static_cast<int64_t>(getIndexingMapsArray().size()) !=
getOperation()->getNumOperands())
return this->emitOpError("expected the number of indexing_map (")
<< getIndexingMapsArray().size()
<< ") to be equal to the number of input/output operands ("
<< getOperation()->getNumOperands() << ")";
AffineMap invertedMap = getShapesToLoopsMap();
if (!invertedMap) {
std::string str;
llvm::raw_string_ostream os(str);
getLoopsToShapesMap().print(os);
return this->emitOpError("invalid indexing maps are non-invertible: ")
<< "(" << str << ")";
}
SmallVector<int64_t> endLoopRangeValues = getStaticLoopRanges();
for (OpOperand &opOperand : getOperation()->getOpOperands()) {
AffineMap indexingMap = getMatchingIndexingMap(&opOperand);
if (indexingMap.getNumSymbols() != 0)
return getOperation()->emitOpError("unexpected symbols in indexing_map #")
<< opOperand.getOperandNumber();
if (indexingMap.getNumDims() != endLoopRangeValues.size())
return getOperation()->emitOpError("expected indexing_map #")
<< opOperand.getOperandNumber() << " to have "
<< endLoopRangeValues.size()
<< " dim(s) to match the number of loops";
SmallVector<int64_t> shape = getStaticOperandShape(&opOperand);
int64_t rank = shape.size();
if (indexingMap.getNumResults() != rank)
return getOperation()->emitOpError("expected operand rank (")
<< rank << ") to match the result rank of indexing_map #"
<< opOperand.getOperandNumber() << " ("
<< indexingMap.getNumResults() << ")";
}
SmallVector<int64_t> startLoopRangeValues(endLoopRangeValues.size(), 0);
if (llvm::none_of(endLoopRangeValues, ShapedType::isDynamic)) {
for (int64_t &range : endLoopRangeValues)
range -= 1;
for (OpOperand &opOperand : getOperation()->getOpOperands()) {
AffineMap indexingMap = getMatchingIndexingMap(&opOperand);
SmallVector<int64_t> startIndices =
indexingMap.compose(startLoopRangeValues);
SmallVector<int64_t> endIndices = indexingMap.compose(endLoopRangeValues);
SmallVector<int64_t> shape = getStaticOperandShape(&opOperand);
for (auto dim : llvm::seq<int64_t>(0, shape.size())) {
if (ShapedType::isDynamic(shape[dim]) || shape[dim] == 0)
continue;
int64_t inferredDimSize =
std::max(startIndices[dim], endIndices[dim]) + 1;
if (std::min(startIndices[dim], endIndices[dim]) < 0) {
std::string mapStr;
{
llvm::raw_string_ostream os(mapStr);
os << indexingMap;
}
return this->emitOpError(
"unexpected result less than 0 at expression #")
<< dim << " in " << mapStr;
}
if (isa<AffineDimExpr>(indexingMap.getResult(dim))) {
if (inferredDimSize != shape[dim]) {
return this->emitOpError("inferred input/output operand #")
<< opOperand.getOperandNumber() << " has shape's dimension #"
<< dim << " to be " << inferredDimSize << ", but found "
<< shape[dim];
}
} else {
if (inferredDimSize > shape[dim]) {
return this->emitOpError("inferred input/output operand #")
<< opOperand.getOperandNumber() << " has shape's dimension #"
<< dim << " to be greater than or equal to "
<< inferredDimSize << ", but found " << shape[dim];
}
}
}
}
}
return success();
}