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
AffineValueMap(AffineMap map,ValueRange operands,ValueRange results)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
reset(AffineMap map,ValueRange operands,ValueRange results)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
difference(const AffineValueMap & a,const AffineValueMap & b,AffineValueMap * res)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.
findIndex(Value valueToMatch,ArrayRef<Value> valuesToSearch,unsigned indexStart,unsigned * indexOfMatch)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
isMultipleOf(unsigned idx,int64_t factor) const76 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.
isFunctionOf(unsigned idx,Value value) const82 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: this is better implemented on a flattened representation.
89 // At least for now it is conservative.
90 return expr.isFunctionOfDim(index);
91 }
92
getOperand(unsigned i) const93 Value AffineValueMap::getOperand(unsigned i) const {
94 return static_cast<Value>(operands[i]);
95 }
96
getOperands() const97 ArrayRef<Value> AffineValueMap::getOperands() const {
98 return ArrayRef<Value>(operands);
99 }
100
getAffineMap() const101 AffineMap AffineValueMap::getAffineMap() const { return map.getAffineMap(); }
102
~AffineValueMap()103 AffineValueMap::~AffineValueMap() {}
104