Skip to content

Commit 52d6c5d

Browse files
committed
[MLIR] Generalize Affine dependence analysis using Affine Relations
This patch removes code very specific to affine dependence analysis and refactors it as a FlatAfffineRelation. A FlatAffineRelation represents a set of ordered pairs (domain -> range) where "domain" and "range" are tuples of identifiers. These relations are used to represent an "access relation" for memory access on a memref. An access relation maps elements of an iteration domain to the element(s) of an array domain accessed by that iteration of the associated statement through some array reference. The dependence relation representing the dependence constraints between two memory accesses can be built by composing the access relation of the destination access by the inverse of the access relation of source access. This patch does not change the functionality of the existing dependence analysis in checkMemrefAccessDependence, but refactors it to use FlatAffineRelations to deduplicate code and enable code reuse for future development of features like scheduling, value-based dependence analysis, etc. Reviewed By: bondhugula Differential Revision: https://reviews.llvm.org/D110563
1 parent 9aa6c72 commit 52d6c5d

File tree

4 files changed

+409
-527
lines changed

4 files changed

+409
-527
lines changed

mlir/include/mlir/Analysis/AffineAnalysis.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace mlir {
2525
class AffineApplyOp;
2626
class AffineForOp;
2727
class AffineValueMap;
28+
class FlatAffineRelation;
2829
class FlatAffineValueConstraints;
2930
class Operation;
3031

@@ -89,6 +90,30 @@ struct MemRefAccess {
8990
// Returns true if this access is of a store op.
9091
bool isStore() const;
9192

93+
/// Creates an access relation for the access. An access relation maps
94+
/// elements of an iteration domain to the element(s) of an array domain
95+
/// accessed by that iteration of the associated statement through some array
96+
/// reference. For example, given the MLIR code:
97+
///
98+
/// affine.for %i0 = 0 to 10 {
99+
/// affine.for %i1 = 0 to 10 {
100+
/// %a = affine.load %arr[%i0 + %i1, %i0 + 2 * %i1] : memref<100x100xf32>
101+
/// }
102+
/// }
103+
///
104+
/// The access relation, assuming that the memory locations for %arr are
105+
/// represented as %m0, %m1 would be:
106+
///
107+
/// (%i0, %i1) -> (%m0, %m1)
108+
/// %m0 = %i0 + %i1
109+
/// %m1 = %i0 + 2 * %i1
110+
/// 0 <= %i0 < 10
111+
/// 0 <= %i1 < 10
112+
///
113+
/// Returns failure for yet unimplemented/unsupported cases (see docs of
114+
/// mlir::getIndexSet and mlir::getRelationFromMap for these cases).
115+
LogicalResult getAccessRelation(FlatAffineRelation &accessRel) const;
116+
92117
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
93118
/// 'indices'.
94119
void getAccessMap(AffineValueMap *accessMap) const;

mlir/include/mlir/Analysis/AffineStructures.h

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,10 @@ class FlatAffineConstraints {
426426
/// O(VC) time.
427427
void removeRedundantConstraints();
428428

429+
/// Converts identifiers in the column range [idStart, idLimit) to local
430+
/// variables.
431+
void convertDimToLocal(unsigned dimStart, unsigned dimLimit);
432+
429433
/// Merge local ids of `this` and `other`. This is done by appending local ids
430434
/// of `other` to `this` and inserting local ids of `this` to `other` at start
431435
/// of its local ids.
@@ -581,6 +585,16 @@ class FlatAffineValueConstraints : public FlatAffineConstraints {
581585
numLocals + 1,
582586
numDims, numSymbols, numLocals, valArgs) {}
583587

588+
FlatAffineValueConstraints(const FlatAffineConstraints &fac,
589+
ArrayRef<Optional<Value>> valArgs = {})
590+
: FlatAffineConstraints(fac) {
591+
assert(valArgs.empty() || valArgs.size() == numIds);
592+
if (valArgs.empty())
593+
values.resize(numIds, None);
594+
else
595+
values.append(valArgs.begin(), valArgs.end());
596+
}
597+
584598
/// Create a flat affine constraint system from an AffineValueMap or a list of
585599
/// these. The constructed system will only include equalities.
586600
explicit FlatAffineValueConstraints(const AffineValueMap &avm);
@@ -721,7 +735,8 @@ class FlatAffineValueConstraints : public FlatAffineConstraints {
721735
using FlatAffineConstraints::insertDimId;
722736
unsigned insertSymbolId(unsigned pos, ValueRange vals);
723737
using FlatAffineConstraints::insertSymbolId;
724-
unsigned insertId(IdKind kind, unsigned pos, unsigned num = 1) override;
738+
virtual unsigned insertId(IdKind kind, unsigned pos,
739+
unsigned num = 1) override;
725740
unsigned insertId(IdKind kind, unsigned pos, ValueRange vals);
726741

727742
/// Append identifiers of the specified kind after the last identifier of that
@@ -882,7 +897,7 @@ class FlatAffineValueConstraints : public FlatAffineConstraints {
882897
/// Removes identifiers in the column range [idStart, idLimit), and copies any
883898
/// remaining valid data into place, updates member variables, and resizes
884899
/// arrays as needed.
885-
void removeIdRange(unsigned idStart, unsigned idLimit) override;
900+
virtual void removeIdRange(unsigned idStart, unsigned idLimit) override;
886901

887902
/// Eliminates the identifier at the specified position using Fourier-Motzkin
888903
/// variable elimination, but uses Gaussian elimination if there is an
@@ -901,6 +916,83 @@ class FlatAffineValueConstraints : public FlatAffineConstraints {
901916
SmallVector<Optional<Value>, 8> values;
902917
};
903918

919+
/// A FlatAffineRelation represents a set of ordered pairs (domain -> range)
920+
/// where "domain" and "range" are tuples of identifiers. The relation is
921+
/// represented as a FlatAffineValueConstraints with separation of dimension
922+
/// identifiers into domain and range. The identifiers are stored as:
923+
/// [domainIds, rangeIds, symbolIds, localIds, constant].
924+
class FlatAffineRelation : public FlatAffineValueConstraints {
925+
public:
926+
FlatAffineRelation(unsigned numReservedInequalities,
927+
unsigned numReservedEqualities, unsigned numReservedCols,
928+
unsigned numDomainDims, unsigned numRangeDims,
929+
unsigned numSymbols, unsigned numLocals,
930+
ArrayRef<Optional<Value>> valArgs = {})
931+
: FlatAffineValueConstraints(
932+
numReservedInequalities, numReservedEqualities, numReservedCols,
933+
numDomainDims + numRangeDims, numSymbols, numLocals, valArgs),
934+
numDomainDims(numDomainDims), numRangeDims(numRangeDims) {}
935+
936+
FlatAffineRelation(unsigned numDomainDims = 0, unsigned numRangeDims = 0,
937+
unsigned numSymbols = 0, unsigned numLocals = 0)
938+
: FlatAffineValueConstraints(numDomainDims + numRangeDims, numSymbols,
939+
numLocals),
940+
numDomainDims(numDomainDims), numRangeDims(numRangeDims) {}
941+
942+
FlatAffineRelation(unsigned numDomainDims, unsigned numRangeDims,
943+
FlatAffineValueConstraints &fac)
944+
: FlatAffineValueConstraints(fac), numDomainDims(numDomainDims),
945+
numRangeDims(numRangeDims) {}
946+
947+
FlatAffineRelation(unsigned numDomainDims, unsigned numRangeDims,
948+
FlatAffineConstraints &fac)
949+
: FlatAffineValueConstraints(fac), numDomainDims(numDomainDims),
950+
numRangeDims(numRangeDims) {}
951+
952+
/// Returns a set corresponding to the domain/range of the affine relation.
953+
FlatAffineValueConstraints getDomainSet() const;
954+
FlatAffineValueConstraints getRangeSet() const;
955+
956+
/// Returns the number of identifiers corresponding to domain/range of
957+
/// relation.
958+
inline unsigned getNumDomainDims() const { return numDomainDims; }
959+
inline unsigned getNumRangeDims() const { return numRangeDims; }
960+
961+
/// Given affine relation `other: (domainOther -> rangeOther)`, this operation
962+
/// takes the composition of `other` on `this: (domainThis -> rangeThis)`.
963+
/// The resulting relation represents tuples of the form: `domainOther ->
964+
/// rangeThis`.
965+
void compose(const FlatAffineRelation &other);
966+
967+
/// Swap domain and range of the relation.
968+
/// `(domain -> range)` is converted to `(range -> domain)`.
969+
void inverse();
970+
971+
/// Insert `num` identifiers of the specified kind after the `pos` identifier
972+
/// of that kind. The coefficient columns corresponding to the added
973+
/// identifiers are initialized to zero.
974+
void insertDomainId(unsigned pos, unsigned num = 1);
975+
void insertRangeId(unsigned pos, unsigned num = 1);
976+
977+
/// Append `num` identifiers of the specified kind after the last identifier
978+
/// of that kind. The coefficient columns corresponding to the added
979+
/// identifiers are initialized to zero.
980+
void appendDomainId(unsigned num = 1);
981+
void appendRangeId(unsigned num = 1);
982+
983+
protected:
984+
// Number of dimension identifers corresponding to domain identifers.
985+
unsigned numDomainDims;
986+
987+
// Number of dimension identifers corresponding to range identifers.
988+
unsigned numRangeDims;
989+
990+
/// Removes identifiers in the column range [idStart, idLimit), and copies any
991+
/// remaining valid data into place, updates member variables, and resizes
992+
/// arrays as needed.
993+
void removeIdRange(unsigned idStart, unsigned idLimit) override;
994+
};
995+
904996
/// Flattens 'expr' into 'flattenedExpr', which contains the coefficients of the
905997
/// dimensions, symbols, and additional variables that represent floor divisions
906998
/// of dimensions, symbols, and in turn other floor divisions. Returns failure
@@ -957,6 +1049,26 @@ AffineMap alignAffineMapWithValues(AffineMap map, ValueRange operands,
9571049
ValueRange dims, ValueRange syms,
9581050
SmallVector<Value> *newSyms = nullptr);
9591051

1052+
/// Builds a relation from the given AffineMap/AffineValueMap `map`, containing
1053+
/// all pairs of the form `operands -> result` that satisfy `map`. `rel` is set
1054+
/// to the relation built. For example, give the AffineMap:
1055+
///
1056+
/// (d0, d1)[s0] -> (d0 + s0, d0 - s0)
1057+
///
1058+
/// the resulting relation formed is:
1059+
///
1060+
/// (d0, d1) -> (r1, r2)
1061+
/// [d0 d1 r1 r2 s0 const]
1062+
/// 1 0 -1 0 1 0 = 0
1063+
/// 0 1 0 -1 -1 0 = 0
1064+
///
1065+
/// For AffineValueMap, the domain and symbols have Value set corresponding to
1066+
/// the Value in `map`. Returns failure if the AffineMap could not be flattened
1067+
/// (i.e., semi-affine is not yet handled).
1068+
LogicalResult getRelationFromMap(AffineMap &map, FlatAffineRelation &rel);
1069+
LogicalResult getRelationFromMap(const AffineValueMap &map,
1070+
FlatAffineRelation &rel);
1071+
9601072
} // end namespace mlir.
9611073

9621074
#endif // MLIR_ANALYSIS_AFFINESTRUCTURES_H

0 commit comments

Comments
 (0)