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 results(results.begin(), results.end()) {} 18 19 void AffineValueMap::reset(AffineMap map, ValueRange operands, 20 ValueRange results) { 21 this->map.reset(map); 22 this->operands.assign(operands.begin(), operands.end()); 23 this->results.assign(results.begin(), results.end()); 24 } 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 unsigned indexStart, unsigned *indexOfMatch) { 66 unsigned size = valuesToSearch.size(); 67 for (unsigned i = indexStart; i < size; ++i) { 68 if (valueToMatch == valuesToSearch[i]) { 69 *indexOfMatch = i; 70 return true; 71 } 72 } 73 return false; 74 } 75 76 bool AffineValueMap::isMultipleOf(unsigned idx, int64_t factor) const { 77 return map.isMultipleOf(idx, factor); 78 } 79 80 /// This method uses the invariant that operands are always positionally aligned 81 /// with the AffineDimExpr in the underlying AffineMap. 82 bool AffineValueMap::isFunctionOf(unsigned idx, Value value) const { 83 unsigned index; 84 if (!findIndex(value, operands, /*indexStart=*/0, &index)) { 85 return false; 86 } 87 auto expr = const_cast<AffineValueMap *>(this)->getAffineMap().getResult(idx); 88 // TODO(ntv): this is better implemented on a flattened representation. 89 // At least for now it is conservative. 90 return expr.isFunctionOfDim(index); 91 } 92 93 Value AffineValueMap::getOperand(unsigned i) const { 94 return static_cast<Value>(operands[i]); 95 } 96 97 ArrayRef<Value> AffineValueMap::getOperands() const { 98 return ArrayRef<Value>(operands); 99 } 100 101 AffineMap AffineValueMap::getAffineMap() const { return map.getAffineMap(); } 102 103 AffineValueMap::~AffineValueMap() {} 104