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