/home/arjun/llvm-project/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | //===- AffineValueMap.cpp - MLIR Affine Value Map Class -------------------===// | 
| 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-exception | 
| 6 |  | // | 
| 7 |  | //===----------------------------------------------------------------------===// | 
| 8 |  |  | 
| 9 |  | #include "mlir/Dialect/Affine/IR/AffineValueMap.h" | 
| 10 |  | #include "mlir/Dialect/Affine/IR/AffineOps.h" | 
| 11 |  |  | 
| 12 |  | using namespace mlir; | 
| 13 |  |  | 
| 14 |  | AffineValueMap::AffineValueMap(AffineMap map, ValueRange operands, | 
| 15 |  |                                ValueRange results) | 
| 16 |  |     : map(map), operands(operands.begin(), operands.end()), | 
| 17 | 0 |       results(results.begin(), results.end()) {} | 
| 18 |  |  | 
| 19 |  | void AffineValueMap::reset(AffineMap map, ValueRange operands, | 
| 20 | 0 |                            ValueRange results) { | 
| 21 | 0 |   this->map.reset(map); | 
| 22 | 0 |   this->operands.assign(operands.begin(), operands.end()); | 
| 23 | 0 |   this->results.assign(results.begin(), results.end()); | 
| 24 | 0 | } | 
| 25 |  |  | 
| 26 |  | void AffineValueMap::difference(const AffineValueMap &a, | 
| 27 |  |                                 const AffineValueMap &b, AffineValueMap *res) { | 
| 28 |  |   assert(a.getNumResults() == b.getNumResults() && "invalid inputs"); | 
| 29 |  |  | 
| 30 |  |   // Fully compose A's map + operands. | 
| 31 |  |   auto aMap = a.getAffineMap(); | 
| 32 |  |   SmallVector<Value, 4> aOperands(a.getOperands().begin(), | 
| 33 |  |                                   a.getOperands().end()); | 
| 34 |  |   fullyComposeAffineMapAndOperands(&aMap, &aOperands); | 
| 35 |  |  | 
| 36 |  |   // Use the affine apply normalizer to get B's map into A's coordinate space. | 
| 37 |  |   AffineApplyNormalizer normalizer(aMap, aOperands); | 
| 38 |  |   SmallVector<Value, 4> bOperands(b.getOperands().begin(), | 
| 39 |  |                                   b.getOperands().end()); | 
| 40 |  |   auto bMap = b.getAffineMap(); | 
| 41 |  |   normalizer.normalize(&bMap, &bOperands); | 
| 42 |  |  | 
| 43 |  |   assert(std::equal(bOperands.begin(), bOperands.end(), | 
| 44 |  |                     normalizer.getOperands().begin()) && | 
| 45 |  |          "operands are expected to be the same after normalization"); | 
| 46 |  |  | 
| 47 |  |   // Construct the difference expressions. | 
| 48 |  |   SmallVector<AffineExpr, 4> diffExprs; | 
| 49 |  |   diffExprs.reserve(a.getNumResults()); | 
| 50 |  |   for (unsigned i = 0, e = bMap.getNumResults(); i < e; ++i) | 
| 51 |  |     diffExprs.push_back(normalizer.getAffineMap().getResult(i) - | 
| 52 |  |                         bMap.getResult(i)); | 
| 53 |  |  | 
| 54 |  |   auto diffMap = | 
| 55 |  |       AffineMap::get(normalizer.getNumDims(), normalizer.getNumSymbols(), | 
| 56 |  |                      diffExprs, aMap.getContext()); | 
| 57 |  |   canonicalizeMapAndOperands(&diffMap, &bOperands); | 
| 58 |  |   diffMap = simplifyAffineMap(diffMap); | 
| 59 |  |   res->reset(diffMap, bOperands); | 
| 60 |  | } | 
| 61 |  |  | 
| 62 |  | // Returns true and sets 'indexOfMatch' if 'valueToMatch' is found in | 
| 63 |  | // 'valuesToSearch' beginning at 'indexStart'. Returns false otherwise. | 
| 64 |  | static bool findIndex(Value valueToMatch, ArrayRef<Value> valuesToSearch, | 
| 65 | 0 |                       unsigned indexStart, unsigned *indexOfMatch) { | 
| 66 | 0 |   unsigned size = valuesToSearch.size(); | 
| 67 | 0 |   for (unsigned i = indexStart; i < size; ++i) { | 
| 68 | 0 |     if (valueToMatch == valuesToSearch[i]) { | 
| 69 | 0 |       *indexOfMatch = i; | 
| 70 | 0 |       return true; | 
| 71 | 0 |     } | 
| 72 | 0 |   } | 
| 73 | 0 |   return false; | 
| 74 | 0 | } | 
| 75 |  |  | 
| 76 | 0 | bool AffineValueMap::isMultipleOf(unsigned idx, int64_t factor) const { | 
| 77 | 0 |   return map.isMultipleOf(idx, factor); | 
| 78 | 0 | } | 
| 79 |  |  | 
| 80 |  | /// This method uses the invariant that operands are always positionally aligned | 
| 81 |  | /// with the AffineDimExpr in the underlying AffineMap. | 
| 82 | 0 | bool AffineValueMap::isFunctionOf(unsigned idx, Value value) const { | 
| 83 | 0 |   unsigned index; | 
| 84 | 0 |   if (!findIndex(value, operands, /*indexStart=*/0, &index)) { | 
| 85 | 0 |     return false; | 
| 86 | 0 |   } | 
| 87 | 0 |   auto expr = const_cast<AffineValueMap *>(this)->getAffineMap().getResult(idx); | 
| 88 | 0 |   // TODO(ntv): this is better implemented on a flattened representation. | 
| 89 | 0 |   // At least for now it is conservative. | 
| 90 | 0 |   return expr.isFunctionOfDim(index); | 
| 91 | 0 | } | 
| 92 |  |  | 
| 93 | 0 | Value AffineValueMap::getOperand(unsigned i) const { | 
| 94 | 0 |   return static_cast<Value>(operands[i]); | 
| 95 | 0 | } | 
| 96 |  |  | 
| 97 | 0 | ArrayRef<Value> AffineValueMap::getOperands() const { | 
| 98 | 0 |   return ArrayRef<Value>(operands); | 
| 99 | 0 | } | 
| 100 |  |  | 
| 101 | 0 | AffineMap AffineValueMap::getAffineMap() const { return map.getAffineMap(); } | 
| 102 |  |  | 
| 103 | 0 | AffineValueMap::~AffineValueMap() {} |