126 lines · cpp
1//===- IndexingMapOpInterface.cpp -- IndexingMapOpInterface impl ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Interfaces/IndexingMapOpInterface.h"10 11using namespace mlir;12 13namespace mlir {14#include "mlir/Interfaces/IndexingMapOpInterface.cpp.inc"15} // namespace mlir16 17LogicalResult mlir::IndexingMapOpInterface::verifyImpl() {18 // All input/output operands must be indexed.19 if (static_cast<int64_t>(getIndexingMapsArray().size()) !=20 getOperation()->getNumOperands())21 return this->emitOpError("expected the number of indexing_map (")22 << getIndexingMapsArray().size()23 << ") to be equal to the number of input/output operands ("24 << getOperation()->getNumOperands() << ")";25 26 AffineMap invertedMap = getShapesToLoopsMap();27 if (!invertedMap) {28 std::string str;29 llvm::raw_string_ostream os(str);30 getLoopsToShapesMap().print(os);31 return this->emitOpError("invalid indexing maps are non-invertible: ")32 << "(" << str << ")";33 }34 35 SmallVector<int64_t> endLoopRangeValues = getStaticLoopRanges();36 37 // Set this flag if this op has user defined maps. This is required to guard38 // the below error condition which assume default indexing maps.39 for (OpOperand &opOperand : getOperation()->getOpOperands()) {40 AffineMap indexingMap = getMatchingIndexingMap(&opOperand);41 42 // Symbols disallowed.43 if (indexingMap.getNumSymbols() != 0)44 return getOperation()->emitOpError("unexpected symbols in indexing_map #")45 << opOperand.getOperandNumber();46 47 // Domain must be consistent.48 if (indexingMap.getNumDims() != endLoopRangeValues.size())49 return getOperation()->emitOpError("expected indexing_map #")50 << opOperand.getOperandNumber() << " to have "51 << endLoopRangeValues.size()52 << " dim(s) to match the number of loops";53 54 SmallVector<int64_t> shape = getStaticOperandShape(&opOperand);55 int64_t rank = shape.size();56 57 if (indexingMap.getNumResults() != rank)58 return getOperation()->emitOpError("expected operand rank (")59 << rank << ") to match the result rank of indexing_map #"60 << opOperand.getOperandNumber() << " ("61 << indexingMap.getNumResults() << ")";62 }63 64 // Check if given shapes match to inferred shapes.65 SmallVector<int64_t> startLoopRangeValues(endLoopRangeValues.size(), 0);66 // Verify only static cases since we can't get exact dimension sizes and67 // loop ranges for dynamic cases in this stage.68 if (llvm::none_of(endLoopRangeValues, ShapedType::isDynamic)) {69 // Exclusive end range.70 for (int64_t &range : endLoopRangeValues)71 range -= 1;72 for (OpOperand &opOperand : getOperation()->getOpOperands()) {73 AffineMap indexingMap = getMatchingIndexingMap(&opOperand);74 SmallVector<int64_t> startIndices =75 indexingMap.compose(startLoopRangeValues);76 SmallVector<int64_t> endIndices = indexingMap.compose(endLoopRangeValues);77 SmallVector<int64_t> shape = getStaticOperandShape(&opOperand);78 for (auto dim : llvm::seq<int64_t>(0, shape.size())) {79 // Ignore dynamic dimension or the case that the dimension size is 080 if (ShapedType::isDynamic(shape[dim]) || shape[dim] == 0)81 continue;82 83 // The first index or last index should be the maximum or the minimum in84 // the inferred index ranges since the range is increasing or85 // decreasing. The size of dimensions of input/output operands and the86 // maximum value + 1 in the inferred range should be the same. But, for87 // now we check if the inferred ranges are in boundary of input/output88 // operands' size or not in case that Affine Expressions are complicated89 // such as d0 * 390 // + d1 since it is not easy to handle the issues.91 // Found the case that this solution can't check, for example, (d0, d1)92 // -> (d1 - d0)93 int64_t inferredDimSize =94 std::max(startIndices[dim], endIndices[dim]) + 1;95 if (std::min(startIndices[dim], endIndices[dim]) < 0) {96 std::string mapStr;97 {98 llvm::raw_string_ostream os(mapStr);99 os << indexingMap;100 }101 return this->emitOpError(102 "unexpected result less than 0 at expression #")103 << dim << " in " << mapStr;104 }105 if (isa<AffineDimExpr>(indexingMap.getResult(dim))) {106 if (inferredDimSize != shape[dim]) {107 return this->emitOpError("inferred input/output operand #")108 << opOperand.getOperandNumber() << " has shape's dimension #"109 << dim << " to be " << inferredDimSize << ", but found "110 << shape[dim];111 }112 } else {113 if (inferredDimSize > shape[dim]) {114 return this->emitOpError("inferred input/output operand #")115 << opOperand.getOperandNumber() << " has shape's dimension #"116 << dim << " to be greater than or equal to "117 << inferredDimSize << ", but found " << shape[dim];118 }119 }120 }121 }122 }123 124 return success();125}126