brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · f3c12ae Raw
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