MLIR 24.0.0git
PWMAFunction.h
Go to the documentation of this file.
1//===- PWMAFunction.h - MLIR PWMAFunction Class------------------*- C++ -*-===//
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// Support for piece-wise multi-affine functions. These are functions that are
10// defined on a domain that is a union of IntegerPolyhedrons, and on each domain
11// the value of the function is a tuple of integers, with each value in the
12// tuple being an affine expression in the vars of the IntegerPolyhedron.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef MLIR_ANALYSIS_PRESBURGER_PWMAFUNCTION_H
17#define MLIR_ANALYSIS_PRESBURGER_PWMAFUNCTION_H
18
21#include <optional>
22
23namespace mlir {
24namespace presburger {
25
26/// Enum representing a binary comparison operator: equal, not equal, less than,
27/// less than or equal, greater than, greater than or equal.
28enum class OrderingKind { EQ, NE, LT, LE, GT, GE };
29
30/// This class represents a multi-affine function with the domain as Z^d, where
31/// `d` is the number of domain variables of the function. For example:
32///
33/// (x, y) -> (x + 2, 2*x - 3y + 5, 2*x + y).
34///
35/// The output expressions are represented as a matrix with one row for every
36/// output, one column for each var including division variables, and an extra
37/// column at the end for the constant term.
38///
39/// Checking equality of two such functions is supported, as well as finding the
40/// value of the function at a specified point.
42public:
43 MultiAffineFunction(const PresburgerSpace &space, const IntMatrix &output)
44 : space(space), output(output),
45 divs(space.getNumVars() - space.getNumRangeVars()) {
46 assertIsConsistent();
47 }
48
49 MultiAffineFunction(const PresburgerSpace &space, const IntMatrix &output,
50 const DivisionRepr &divs)
51 : space(space), output(output), divs(divs) {
52 assertIsConsistent();
53 }
54
55 unsigned getNumDomainVars() const { return space.getNumDomainVars(); }
56 unsigned getNumSymbolVars() const { return space.getNumSymbolVars(); }
57 unsigned getNumOutputs() const { return space.getNumRangeVars(); }
58 unsigned getNumDivs() const { return space.getNumLocalVars(); }
59
60 /// Get the space of this function.
61 const PresburgerSpace &getSpace() const { return space; }
62 /// Get the domain/output space of the function. The returned space is a set
63 /// space.
64 PresburgerSpace getDomainSpace() const { return space.getDomainSpace(); }
65 PresburgerSpace getOutputSpace() const { return space.getRangeSpace(); }
66
67 /// Get a matrix with each row representing row^th output expression.
68 const IntMatrix &getOutputMatrix() const { return output; }
69 /// Get the `i^th` output expression.
71 return output.getRow(i);
72 }
73
74 /// Get the divisions used in this function.
75 const DivisionRepr &getDivs() const { return divs; }
76
77 /// Remove the specified range of outputs.
78 void removeOutputs(unsigned start, unsigned end);
79
80 /// Given a MAF `other`, merges division variables such that both functions
81 /// have the union of the division vars that exist in the functions.
82 void mergeDivs(MultiAffineFunction &other);
83
84 //// Return the output of the function at the given point.
89
90 /// Return whether the `this` and `other` are equal when the domain is
91 /// restricted to `domain`. This is the case if they lie in the same space,
92 /// and their outputs are equal for every point in `domain`.
93 bool isEqual(const MultiAffineFunction &other) const;
94 bool isEqual(const MultiAffineFunction &other,
95 const IntegerPolyhedron &domain) const;
96 bool isEqual(const MultiAffineFunction &other,
97 const PresburgerSet &domain) const;
98
99 void subtract(const MultiAffineFunction &other);
100
101 /// Return the set of domain points where the output of `this` and `other`
102 /// are ordered lexicographically according to the given ordering.
103 /// For example, if the given comparison is `LT`, then the returned set
104 /// contains all points where the first output of `this` is lexicographically
105 /// less than `other`.
107 const MultiAffineFunction &other) const;
108
109 /// Get this function as a relation.
111
112 void print(raw_ostream &os) const;
113#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
114 LLVM_DUMP_METHOD void dump() const;
115#endif
116
117private:
118 /// Assert that the MAF is consistent.
119 void assertIsConsistent() const;
120
121 /// The space of this function. The domain variables are considered as the
122 /// input variables of the function. The range variables are considered as
123 /// the outputs. The symbols parametrize the function and locals are used to
124 /// represent divisions. Each local variable has a corressponding division
125 /// representation stored in `divs`.
126 PresburgerSpace space;
127
128 /// The function's output is a tuple of integers, with the ith element of the
129 /// tuple defined by the affine expression given by the ith row of this output
130 /// matrix.
131 IntMatrix output;
132
133 /// Storage for division representation for each local variable in space.
134 DivisionRepr divs;
135};
136
137/// This class represents a piece-wise MultiAffineFunction. This can be thought
138/// of as a list of MultiAffineFunction with disjoint domains, with each having
139/// their own affine expressions for their output tuples. For example, we could
140/// have a function with two input variables (x, y), defined as
141///
142/// f(x, y) = (2*x + y, y - 4) if x >= 0, y >= 0
143/// = (-2*x + y, y + 4) if x < 0, y < 0
144/// = (4, 1) if x < 0, y >= 0
145///
146/// Note that the domains all have to be *disjoint*. Otherwise, the behaviour of
147/// this class is undefined. The domains need not cover all possible points;
148/// this represents a partial function and so could be undefined at some points.
149///
150/// As in PresburgerSets, the input vars are partitioned into dimension vars and
151/// symbolic vars.
152///
153/// Support is provided to compare equality of two such functions as well as
154/// finding the value of the function at a point.
156public:
157 struct Piece {
160
161 bool isConsistent() const {
162 return domain.getSpace().isCompatible(output.getDomainSpace());
163 }
164 };
165
166 PWMAFunction(const PresburgerSpace &space) : space(space) {
167 assert(space.getNumLocalVars() == 0 &&
168 "PWMAFunction cannot have local vars.");
169 }
170
171 // Get the space of this function.
172 const PresburgerSpace &getSpace() const { return space; }
173
174 // Add a piece ([domain, output] pair) to this function.
175 void addPiece(const Piece &piece);
176
177 unsigned getNumPieces() const { return pieces.size(); }
178 unsigned getNumVarKind(VarKind kind) const {
179 return space.getNumVarKind(kind);
180 }
181 unsigned getNumDomainVars() const { return space.getNumDomainVars(); }
182 unsigned getNumOutputs() const { return space.getNumRangeVars(); }
183 unsigned getNumSymbolVars() const { return space.getNumSymbolVars(); }
184
185 /// Remove the specified range of outputs.
186 void removeOutputs(unsigned start, unsigned end);
187
188 /// Get the domain/output space of the function. The returned space is a set
189 /// space.
192
193 /// Return the domain of this piece-wise MultiAffineFunction. This is the
194 /// union of the domains of all the pieces.
195 PresburgerSet getDomain() const;
196
197 /// Return the output of the function at the given point.
198 std::optional<SmallVector<DynamicAPInt, 8>>
199 valueAt(ArrayRef<DynamicAPInt> point) const;
200 std::optional<SmallVector<DynamicAPInt, 8>>
202 return valueAt(getDynamicAPIntVec(point));
203 }
204
205 /// Return all the pieces of this piece-wise function.
206 ArrayRef<Piece> getAllPieces() const { return pieces; }
207
208 /// Return whether `this` and `other` are equal as PWMAFunctions, i.e. whether
209 /// they have the same dimensions, the same domain and they take the same
210 /// value at every point in the domain.
211 bool isEqual(const PWMAFunction &other) const;
212
213 /// Return a function defined on the union of the domains of this and func,
214 /// such that when only one of the functions is defined, it outputs the same
215 /// as that function, and if both are defined, it outputs the lexmax/lexmin of
216 /// the two outputs. On points where neither function is defined, the returned
217 /// function is not defined either.
218 ///
219 /// Currently this does not support PWMAFunctions which have pieces containing
220 /// divisions.
221 /// TODO: Support division in pieces.
224
225 void print(raw_ostream &os) const;
226#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
227 LLVM_DUMP_METHOD void dump() const;
228#endif
229
230private:
231 /// Return a function defined on the union of the domains of `this` and
232 /// `func`, such that when only one of the functions is defined, it outputs
233 /// the same as that function, and if neither is defined, the returned
234 /// function is not defined either.
235 ///
236 /// The provided `tiebreak` function determines which of the two functions'
237 /// output should be used on inputs where both the functions are defined. More
238 /// precisely, given two `MultiAffineFunction`s `mafA` and `mafB`, `tiebreak`
239 /// returns the subset of the intersection of the two functions' domains where
240 /// the output of `mafA` should be used.
241 ///
242 /// The PresburgerSet returned by `tiebreak` should be disjoint.
243 /// TODO: Remove this constraint of returning disjoint set.
244 PWMAFunction unionFunction(
245 const PWMAFunction &func,
246 llvm::function_ref<PresburgerSet(Piece mafA, Piece mafB)> tiebreak) const;
247
248 /// The space of this function. The domain variables are considered as the
249 /// input variables of the function. The range variables are considered as
250 /// the outputs. The symbols paramterize the function.
251 PresburgerSpace space;
252
253 // The pieces of the PWMAFunction.
255};
256
257} // namespace presburger
258} // namespace mlir
259
260#endif // MLIR_ANALYSIS_PRESBURGER_PWMAFUNCTION_H
Class storing division representation of local variables of a constraint system.
Definition Utils.h:117
An IntegerPolyhedron represents the set of points from a PresburgerSpace that satisfy a list of affin...
An IntegerRelation represents the set of points from a PresburgerSpace that satisfy a list of affine ...
This class represents a multi-affine function with the domain as Z^d, where d is the number of domain...
void subtract(const MultiAffineFunction &other)
void removeOutputs(unsigned start, unsigned end)
Remove the specified range of outputs.
const PresburgerSpace & getSpace() const
Get the space of this function.
void print(raw_ostream &os) const
MultiAffineFunction(const PresburgerSpace &space, const IntMatrix &output, const DivisionRepr &divs)
PresburgerSpace getOutputSpace() const
MultiAffineFunction(const PresburgerSpace &space, const IntMatrix &output)
PresburgerSpace getDomainSpace() const
Get the domain/output space of the function.
PresburgerSet getLexSet(OrderingKind comp, const MultiAffineFunction &other) const
Return the set of domain points where the output of this and other are ordered lexicographically acco...
SmallVector< DynamicAPInt, 8 > valueAt(ArrayRef< DynamicAPInt > point) const
const IntMatrix & getOutputMatrix() const
Get a matrix with each row representing row^th output expression.
LLVM_DUMP_METHOD void dump() const
SmallVector< DynamicAPInt, 8 > valueAt(ArrayRef< int64_t > point) const
void mergeDivs(MultiAffineFunction &other)
Given a MAF other, merges division variables such that both functions have the union of the division ...
ArrayRef< DynamicAPInt > getOutputExpr(unsigned i) const
Get the i^th output expression.
IntegerRelation getAsRelation() const
Get this function as a relation.
const DivisionRepr & getDivs() const
Get the divisions used in this function.
bool isEqual(const MultiAffineFunction &other) const
Return whether the this and other are equal when the domain is restricted to domain.
This class represents a piece-wise MultiAffineFunction.
std::optional< SmallVector< DynamicAPInt, 8 > > valueAt(ArrayRef< int64_t > point) const
void addPiece(const Piece &piece)
unsigned getNumDomainVars() const
LLVM_DUMP_METHOD void dump() const
void print(raw_ostream &os) const
PWMAFunction unionLexMax(const PWMAFunction &func)
ArrayRef< Piece > getAllPieces() const
Return all the pieces of this piece-wise function.
void removeOutputs(unsigned start, unsigned end)
Remove the specified range of outputs.
const PresburgerSpace & getSpace() const
unsigned getNumVarKind(VarKind kind) const
PWMAFunction unionLexMin(const PWMAFunction &func)
Return a function defined on the union of the domains of this and func, such that when only one of th...
PWMAFunction(const PresburgerSpace &space)
std::optional< SmallVector< DynamicAPInt, 8 > > valueAt(ArrayRef< DynamicAPInt > point) const
Return the output of the function at the given point.
PresburgerSet getDomain() const
Return the domain of this piece-wise MultiAffineFunction.
PresburgerSpace getDomainSpace() const
Get the domain/output space of the function.
PresburgerSpace getOutputSpace() const
unsigned getNumSymbolVars() const
bool isEqual(const PWMAFunction &other) const
Return whether this and other are equal as PWMAFunctions, i.e.
PresburgerSpace is the space of all possible values of a tuple of integer valued variables/variables.
PresburgerSpace getRangeSpace() const
PresburgerSpace getDomainSpace() const
Get the domain/range space of this space.
VarKind
Kind of variable.
SmallVector< DynamicAPInt, 8 > getDynamicAPIntVec(ArrayRef< int64_t > range)
Check if the pos^th variable can be expressed as a floordiv of an affine function of other variables ...
Definition Utils.cpp:524
OrderingKind
Enum representing a binary comparison operator: equal, not equal, less than, less than or equal,...
Include the generated interface declarations.