MLIR 24.0.0git
Var.cpp
Go to the documentation of this file.
1//===- Var.cpp ------------------------------------------------------------===//
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 "Var.h"
10#include "DimLvlMap.h"
11
12using namespace mlir;
13using namespace mlir::sparse_tensor;
14using namespace mlir::sparse_tensor::ir_detail;
15
16//===----------------------------------------------------------------------===//
17// `VarKind` helpers.
18//===----------------------------------------------------------------------===//
19
20/// For use in foreach loops.
23
24//===----------------------------------------------------------------------===//
25// `Var` implementation.
26//===----------------------------------------------------------------------===//
27
28std::string Var::str() const {
29 std::string str;
30 llvm::raw_string_ostream os(str);
31 print(os);
32 return str;
33}
34
35void Var::print(AsmPrinter &printer) const { print(printer.getStream()); }
36
37void Var::print(llvm::raw_ostream &os) const {
38 os << toChar(getKind()) << getNum();
39}
40
41#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
42void Var::dump() const {
43 print(llvm::errs());
44 llvm::errs() << "\n";
45}
46#endif
47
48//===----------------------------------------------------------------------===//
49// `Ranks` implementation.
50//===----------------------------------------------------------------------===//
51
52bool Ranks::operator==(Ranks const &other) const {
53 for (const auto vk : everyVarKind)
54 if (getRank(vk) != other.getRank(vk))
55 return false;
56 return true;
57}
58
59bool Ranks::isValid(DimLvlExpr expr) const {
60 assert(expr);
61 // Compute the maximum identifiers for symbol-vars and dim/lvl-vars
62 // (each `DimLvlExpr` only allows one kind of non-symbol variable).
63 int64_t maxSym = -1, maxVar = -1;
65 maxVar, maxSym);
66 return maxSym < getSymRank() && maxVar < getRank(expr.getAllowedVarKind());
67}
68
69//===----------------------------------------------------------------------===//
70// `VarSet` implementation.
71//===----------------------------------------------------------------------===//
72
73VarSet::VarSet(Ranks const &ranks) {
74 for (const auto vk : everyVarKind)
75 impl[vk] = llvm::SmallBitVector(ranks.getRank(vk));
76 assert(getRanks() == ranks);
77}
78
79bool VarSet::contains(Var var) const {
80 // NOTE: We make sure to return false on OOB, for consistency with
81 // the `anyCommon` implementation of `VarSet::occursIn(VarSet)`.
82 // However beware that, as always with silencing OOB, this can hide
83 // bugs in client code.
84 const llvm::SmallBitVector &bits = impl[var.getKind()];
85 const auto num = var.getNum();
86 return num < bits.size() && bits[num];
87}
88
89void VarSet::add(Var var) {
90 // NOTE: `SmallBitVector::operator[]` will raise assertion errors for OOB.
91 impl[var.getKind()][var.getNum()] = true;
92}
93
94void VarSet::add(VarSet const &other) {
95 // NOTE: `SmallBitVector::operator&=` will implicitly resize
96 // the bitvector (unlike `BitVector::operator&=`), so we add an
97 // assertion against OOB for consistency with the implementation
98 // of `VarSet::add(Var)`.
99 for (const auto vk : everyVarKind) {
100 assert(impl[vk].size() >= other.impl[vk].size());
101 impl[vk] &= other.impl[vk];
102 }
103}
104
106 if (!expr)
107 return;
108 switch (expr.getAffineKind()) {
110 return;
112 add(expr.castSymVar());
113 return;
115 add(expr.castDimLvlVar());
116 return;
122 const auto [lhs, op, rhs] = expr.unpackBinop();
123 (void)op;
124 add(lhs);
125 add(rhs);
126 return;
127 }
128 }
129 llvm_unreachable("unknown AffineExprKind");
130}
131
132//===----------------------------------------------------------------------===//
133// `VarInfo` implementation.
134//===----------------------------------------------------------------------===//
135
137 assert(!hasNum() && "Var::Num is already set");
138 assert(Var::isWF_Num(n) && "Var::Num is too large");
139 num = n;
140}
141
142//===----------------------------------------------------------------------===//
143// `VarEnv` implementation.
144//===----------------------------------------------------------------------===//
145
146/// Helper function for `assertUsageConsistency` to better handle SMLoc
147/// mismatches.
148[[maybe_unused]] static llvm::SMLoc minSMLoc(AsmParser &parser, llvm::SMLoc sm1,
149 llvm::SMLoc sm2) {
150 const auto loc1 = dyn_cast<FileLineColLoc>(parser.getEncodedSourceLoc(sm1));
151 assert(loc1 && "Could not get `FileLineColLoc` for first `SMLoc`");
152 const auto loc2 = dyn_cast<FileLineColLoc>(parser.getEncodedSourceLoc(sm2));
153 assert(loc2 && "Could not get `FileLineColLoc` for second `SMLoc`");
154 if (loc1.getFilename() != loc2.getFilename())
155 return SMLoc();
156 const auto pair1 = std::make_pair(loc1.getLine(), loc1.getColumn());
157 const auto pair2 = std::make_pair(loc2.getLine(), loc2.getColumn());
158 return pair1 <= pair2 ? sm1 : sm2;
159}
160
161static bool isInternalConsistent(VarEnv const &env, VarInfo::ID id,
162 StringRef name) {
163 const auto &var = env.access(id);
164 return (var.getName() == name && var.getID() == id);
165}
166
167static bool isUsageConsistent(VarEnv const &env, VarInfo::ID id,
168 llvm::SMLoc loc, VarKind vk) {
169 const auto &var = env.access(id);
170 return var.getKind() == vk;
171}
172
173std::optional<VarInfo::ID> VarEnv::lookup(StringRef name) const {
174 const auto iter = ids.find(name);
175 if (iter == ids.end())
176 return std::nullopt;
177 const auto id = iter->second;
178 if (!isInternalConsistent(*this, id, name))
179 return std::nullopt;
180 return id;
181}
182
183std::optional<std::pair<VarInfo::ID, bool>>
184VarEnv::create(StringRef name, llvm::SMLoc loc, VarKind vk, bool verifyUsage) {
185 const auto &[iter, didInsert] = ids.try_emplace(name, nextID());
186 const auto id = iter->second;
187 if (didInsert) {
188 vars.emplace_back(id, name, loc, vk);
189 } else {
190 if (!isInternalConsistent(*this, id, name))
191 return std::nullopt;
192 if (verifyUsage)
193 if (!isUsageConsistent(*this, id, loc, vk))
194 return std::nullopt;
195 }
196 return std::make_pair(id, didInsert);
197}
198
199std::optional<std::pair<VarInfo::ID, bool>>
200VarEnv::lookupOrCreate(Policy creationPolicy, StringRef name, llvm::SMLoc loc,
201 VarKind vk) {
202 switch (creationPolicy) {
203 case Policy::MustNot: {
204 const auto oid = lookup(name);
205 if (!oid)
206 return std::nullopt; // Doesn't exist, but must not create.
207 if (!isUsageConsistent(*this, *oid, loc, vk))
208 return std::nullopt;
209 return std::make_pair(*oid, false);
210 }
211 case Policy::May:
212 return create(name, loc, vk, /*verifyUsage=*/true);
213 case Policy::Must: {
214 const auto res = create(name, loc, vk, /*verifyUsage=*/false);
215 const auto didCreate = res->second;
216 if (!didCreate)
217 return std::nullopt; // Already exists, but must create.
218 return res;
219 }
220 }
221 llvm_unreachable("unknown Policy");
222}
223
224Var VarEnv::bindUnusedVar(VarKind vk) { return Var(vk, nextNum[vk]++); }
226 auto &info = access(id);
227 const auto var = bindUnusedVar(info.getKind());
228 info.setNum(var.getNum());
229 return var;
230}
231
233 for (const auto &var : vars)
234 if (!var.hasNum())
235 return parser.emitError(var.getLoc(),
236 "Unbound variable: " + var.getName());
237 return {};
238}
239
240//===----------------------------------------------------------------------===//
static constexpr const VarKind everyVarKind[]
For use in foreach loops.
Definition Var.cpp:21
static llvm::SMLoc minSMLoc(AsmParser &parser, llvm::SMLoc sm1, llvm::SMLoc sm2)
Helper function for assertUsageConsistency to better handle SMLoc mismatches.
Definition Var.cpp:148
static bool isInternalConsistent(VarEnv const &env, VarInfo::ID id, StringRef name)
Definition Var.cpp:161
static bool isUsageConsistent(VarEnv const &env, VarInfo::ID id, llvm::SMLoc loc, VarKind vk)
Definition Var.cpp:167
#define add(a, b)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual Location getEncodedSourceLoc(SMLoc loc)=0
Re-encode the given source location as an MLIR location and return it.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
This class represents a diagnostic that is inflight and set to be reported.
constexpr AffineExpr getAffineExpr() const
Definition DimLvlMap.h:68
std::tuple< DimLvlExpr, AffineExprKind, DimLvlExpr > unpackBinop() const
Definition DimLvlMap.cpp:40
constexpr VarKind getAllowedVarKind() const
Definition DimLvlMap.h:65
constexpr unsigned getRank(VarKind vk) const
Definition Var.h:230
bool operator==(Ranks const &other) const
Definition Var.cpp:52
constexpr unsigned getSymRank() const
Definition Var.h:231
constexpr Ranks(unsigned symRank, unsigned dimRank, unsigned lvlRank)
Definition Var.h:217
constexpr bool isValid(Var var) const
Definition Var.h:235
Var bindUnusedVar(VarKind vk)
Creates a new variable of the given kind and immediately binds it.
Definition Var.cpp:224
InFlightDiagnostic emitErrorIfAnyUnbound(AsmParser &parser) const
Definition Var.cpp:232
std::optional< std::pair< VarInfo::ID, bool > > lookupOrCreate(Policy creationPolicy, StringRef name, llvm::SMLoc loc, VarKind vk)
Looks up or creates a variable according to the given Policy.
Definition Var.cpp:200
std::optional< VarInfo::ID > lookup(StringRef name) const
Looks up the variable with the given name.
Definition Var.cpp:173
std::optional< std::pair< VarInfo::ID, bool > > create(StringRef name, llvm::SMLoc loc, VarKind vk, bool verifyUsage=false)
Creates a new currently-unbound variable.
Definition Var.cpp:184
Var bindVar(VarInfo::ID id)
Binds the given variable to the next free Var::Num for its VarKind.
Definition Var.cpp:225
VarInfo const & access(VarInfo::ID id) const
Gets the underlying storage for the VarInfo identified by the VarInfo::ID.
Definition Var.h:340
constexpr VarKind getKind() const
Definition Var.h:306
ID
Newtype for unique identifiers of VarInfo records, to ensure they aren't confused with Var::Num.
Definition Var.h:281
constexpr bool hasNum() const
Definition Var.h:308
bool contains(Var var) const
For the contains method: if variables occurring in the method parameter are OOB for the VarSet,...
Definition Var.cpp:79
void add(Var var)
For the add methods: OOB parameters cause undefined behavior.
Definition Var.cpp:89
A concrete variable, to be used in our variant of AffineExpr.
Definition Var.h:61
constexpr Num getNum() const
Definition Var.h:125
LLVM_DUMP_METHOD void dump() const
Definition Var.cpp:42
constexpr VarKind getKind() const
Definition Var.h:124
void print(llvm::raw_ostream &os) const
Definition Var.cpp:37
std::string str() const
Definition Var.cpp:28
static constexpr bool isWF_Num(Num n)
Checks whether the number would be accepted by Var(VarKind,Var::Num).
Definition Var.h:83
unsigned Num
Typedef for the type of variable numbers.
Definition Var.h:64
VarKind
The three kinds of variables that Var can be.
Definition Var.h:32
constexpr char toChar(VarKind vk)
Gets the ASCII character used as the prefix when printing Var.
Definition Var.h:40
Include the generated interface declarations.
void getMaxDimAndSymbol(ArrayRef< AffineExprContainer > exprsList, int64_t &maxDim, int64_t &maxSym)
Calculates maximum dimension and symbol positions from the expressions in exprsLists and stores them ...
Definition AffineMap.h:699
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
Definition AffineExpr.h:50
@ Mul
RHS of mul is always a constant or a symbolic expression.
Definition AffineExpr.h:43
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
Definition AffineExpr.h:46
@ DimId
Dimensional identifier.
Definition AffineExpr.h:59
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
Definition AffineExpr.h:48
@ Constant
Constant integer.
Definition AffineExpr.h:57
@ SymbolId
Symbolic identifier.
Definition AffineExpr.h:61