Polly 19.0.0git
MaximalStaticExpansion.cpp
Go to the documentation of this file.
1//===- MaximalStaticExpansion.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// This pass fully expand the memory accesses of a Scop to get rid of
10// dependencies.
11//
12//===----------------------------------------------------------------------===//
13
16#include "polly/LinkAllPasses.h"
17#include "polly/ScopInfo.h"
18#include "polly/ScopPass.h"
20#include "llvm/ADT/SmallPtrSet.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Analysis/OptimizationRemarkEmitter.h"
23#include "llvm/InitializePasses.h"
25#include "isl/union_map.h"
26#include <cassert>
27#include <limits>
28#include <string>
29#include <vector>
30
31using namespace llvm;
32using namespace polly;
33
34#define DEBUG_TYPE "polly-mse"
35
36namespace {
37
38class MaximalStaticExpanderWrapperPass final : public ScopPass {
39public:
40 static char ID;
41
42 explicit MaximalStaticExpanderWrapperPass() : ScopPass(ID) {}
43
44 ~MaximalStaticExpanderWrapperPass() override = default;
45
46 /// Expand the accesses of the SCoP.
47 ///
48 /// @param S The SCoP that must be expanded.
49 bool runOnScop(Scop &S) override;
50
51 /// Print the SCoP.
52 ///
53 /// @param OS The stream where to print.
54 /// @param S The SCop that must be printed.
55 void printScop(raw_ostream &OS, Scop &S) const override;
56
57 /// Register all analyses and transformations required.
58 void getAnalysisUsage(AnalysisUsage &AU) const override;
59};
60
61#ifndef NDEBUG
62/// Whether a dimension of a set is bounded (lower and upper) by a constant,
63/// i.e. there are two constants Min and Max, such that every value x of the
64/// chosen dimensions is Min <= x <= Max.
65static bool isDimBoundedByConstant(isl::set Set, unsigned dim) {
66 auto ParamDims = unsignedFromIslSize(Set.dim(isl::dim::param));
67 Set = Set.project_out(isl::dim::param, 0, ParamDims);
68 Set = Set.project_out(isl::dim::set, 0, dim);
69 auto SetDims = unsignedFromIslSize(Set.tuple_dim());
70 assert(SetDims >= 1);
71 Set = Set.project_out(isl::dim::set, 1, SetDims - 1);
72 return bool(Set.is_bounded());
73}
74#endif
75
76class MaximalStaticExpansionImpl {
77 OptimizationRemarkEmitter &ORE;
78 Scop &S;
80
81 /// Emit remark
82 void emitRemark(StringRef Msg, Instruction *Inst) {
83 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ExpansionRejection", Inst)
84 << Msg);
85 }
86
87 /// Filter the dependences to have only one related to current memory access.
88 ///
89 /// @param S The SCop in which the memory access appears in.
90 /// @param MapDependences The dependences to filter.
91 /// @param MA The memory access that need to be expanded.
92 isl::union_map filterDependences(const isl::union_map &Dependences,
93 MemoryAccess *MA) {
94 auto SAI = MA->getLatestScopArrayInfo();
95
96 auto AccessDomainSet = MA->getAccessRelation().domain();
97 auto AccessDomainId = AccessDomainSet.get_tuple_id();
98
99 isl::union_map MapDependences = isl::union_map::empty(S.getIslCtx());
100
101 for (isl::map Map : Dependences.get_map_list()) {
102 // Filter out Statement to Statement dependences.
103 if (!Map.can_curry())
104 continue;
105
106 // Intersect with the relevant SAI.
107 auto TmpMapDomainId =
108 Map.get_space().domain().unwrap().range().get_tuple_id(isl::dim::set);
109
110 ScopArrayInfo *UserSAI =
111 static_cast<ScopArrayInfo *>(TmpMapDomainId.get_user());
112
113 if (SAI != UserSAI)
114 continue;
115
116 // Get the correct S1[] -> S2[] dependence.
117 auto NewMap = Map.factor_domain();
118 auto NewMapDomainId = NewMap.domain().get_tuple_id();
119
120 if (AccessDomainId.get() != NewMapDomainId.get())
121 continue;
122
123 // Add the corresponding map to MapDependences.
124 MapDependences = MapDependences.unite(NewMap);
125 }
126
127 return MapDependences;
128 }
129
130 /// Return true if the SAI in parameter is expandable.
131 ///
132 /// @param SAI the SAI that need to be checked.
133 /// @param Writes A set that will contains all the write accesses.
134 /// @param Reads A set that will contains all the read accesses.
135 /// @param S The SCop in which the SAI is in.
136 /// @param Dependences The RAW dependences of the SCop.
137 bool isExpandable(const ScopArrayInfo *SAI,
138 SmallPtrSetImpl<MemoryAccess *> &Writes,
139 SmallPtrSetImpl<MemoryAccess *> &Reads, Scop &S) {
140 if (SAI->isValueKind()) {
141 Writes.insert(S.getValueDef(SAI));
142 for (auto MA : S.getValueUses(SAI))
143 Reads.insert(MA);
144 return true;
145 } else if (SAI->isPHIKind()) {
146 auto Read = S.getPHIRead(SAI);
147
148 auto StmtDomain = isl::union_set(Read->getStatement()->getDomain());
149
150 auto Writes = S.getPHIIncomings(SAI);
151
152 // Get the domain where all the writes are writing to.
153 auto WriteDomain = isl::union_set::empty(S.getIslCtx());
154
155 for (auto Write : Writes) {
156 auto MapDeps = filterDependences(Dependences, Write);
157 for (isl::map Map : MapDeps.get_map_list())
158 WriteDomain = WriteDomain.unite(Map.range());
159 }
160
161 // For now, read from original scalar is not possible.
162 if (!StmtDomain.is_equal(WriteDomain)) {
163 emitRemark(SAI->getName() + " read from its original value.",
164 Read->getAccessInstruction());
165 return false;
166 }
167
168 return true;
169 } else if (SAI->isExitPHIKind()) {
170 // For now, we are not able to expand ExitPhi.
171 emitRemark(SAI->getName() + " is a ExitPhi node.",
172 S.getEnteringBlock()->getFirstNonPHI());
173 return false;
174 }
175
176 int NumberWrites = 0;
177 for (ScopStmt &Stmt : S) {
178 auto StmtReads = isl::union_map::empty(S.getIslCtx());
179 auto StmtWrites = isl::union_map::empty(S.getIslCtx());
180
181 for (MemoryAccess *MA : Stmt) {
182 // Check if the current MemoryAccess involved the current SAI.
183 if (SAI != MA->getLatestScopArrayInfo())
184 continue;
185
186 // For now, we are not able to expand array where read come after write
187 // (to the same location) in a same statement.
188 auto AccRel = isl::union_map(MA->getAccessRelation());
189 if (MA->isRead()) {
190 // Reject load after store to same location.
191 if (!StmtWrites.is_disjoint(AccRel)) {
192 emitRemark(SAI->getName() + " has read after write to the same "
193 "element in same statement. The "
194 "dependences found during analysis may "
195 "be wrong because Polly is not able to "
196 "handle such case for now.",
198 return false;
199 }
200
201 StmtReads = StmtReads.unite(AccRel);
202 } else {
203 StmtWrites = StmtWrites.unite(AccRel);
204 }
205
206 // For now, we are not able to expand MayWrite.
207 if (MA->isMayWrite()) {
208 emitRemark(SAI->getName() + " has a maywrite access.",
210 return false;
211 }
212
213 // For now, we are not able to expand SAI with more than one write.
214 if (MA->isMustWrite()) {
215 Writes.insert(MA);
216 NumberWrites++;
217 if (NumberWrites > 1) {
218 emitRemark(SAI->getName() + " has more than 1 write access.",
220 return false;
221 }
222 }
223
224 // Check if it is possible to expand this read.
225 if (MA->isRead()) {
226 // Get the domain of the current ScopStmt.
227 auto StmtDomain = Stmt.getDomain();
228
229 // Get the domain of the future Read access.
230 auto ReadDomainSet = MA->getAccessRelation().domain();
231 auto ReadDomain = isl::union_set(ReadDomainSet);
232
233 // Get the dependences relevant for this MA
234 auto MapDependences = filterDependences(Dependences.reverse(), MA);
235 unsigned NumberElementMap = isl_union_map_n_map(MapDependences.get());
236
237 if (NumberElementMap == 0) {
238 emitRemark("The expansion of " + SAI->getName() +
239 " would lead to a read from the original array.",
241 return false;
242 }
243
244 auto DepsDomain = MapDependences.domain();
245
246 // If there are multiple maps in the Deps, we cannot handle this case
247 // for now.
248 if (NumberElementMap != 1) {
249 emitRemark(SAI->getName() +
250 " has too many dependences to be handle for now.",
252 return false;
253 }
254
255 auto DepsDomainSet = isl::set(DepsDomain);
256
257 // For now, read from the original array is not possible.
258 if (!StmtDomain.is_subset(DepsDomainSet)) {
259 emitRemark("The expansion of " + SAI->getName() +
260 " would lead to a read from the original array.",
262 return false;
263 }
264
265 Reads.insert(MA);
266 }
267 }
268 }
269
270 // No need to expand SAI with no write.
271 if (NumberWrites == 0) {
272 emitRemark(SAI->getName() + " has 0 write access.",
273 S.getEnteringBlock()->getFirstNonPHI());
274 return false;
275 }
276
277 return true;
278 }
279
280 /// Expand the MemoryAccess according to Dependences and already expanded
281 /// MemoryAccesses.
282 ///
283 /// @param The SCop in which the memory access appears in.
284 /// @param The memory access that need to be expanded.
285 /// @param Dependences The RAW dependences of the SCop.
286 /// @param ExpandedSAI The expanded SAI created during write expansion.
287 /// @param Reverse if true, the Dependences union_map is reversed before
288 /// intersection.
289 void mapAccess(SmallPtrSetImpl<MemoryAccess *> &Accesses,
290 const isl::union_map &Dependences, ScopArrayInfo *ExpandedSAI,
291 bool Reverse) {
292 for (auto MA : Accesses) {
293 // Get the current AM.
294 auto CurrentAccessMap = MA->getAccessRelation();
295
296 // Get RAW dependences for the current WA.
297 auto DomainSet = MA->getAccessRelation().domain();
298 auto Domain = isl::union_set(DomainSet);
299
300 // Get the dependences relevant for this MA.
301 isl::union_map MapDependences =
302 filterDependences(Reverse ? Dependences.reverse() : Dependences, MA);
303
304 // If no dependences, no need to modify anything.
305 if (MapDependences.is_empty())
306 return;
307
308 assert(isl_union_map_n_map(MapDependences.get()) == 1 &&
309 "There are more than one RAW dependencies in the union map.");
310 auto NewAccessMap = isl::map::from_union_map(MapDependences);
311
312 auto Id = ExpandedSAI->getBasePtrId();
313
314 // Replace the out tuple id with the one of the access array.
315 NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, Id);
316
317 // Set the new access relation.
318 MA->setNewAccessRelation(NewAccessMap);
319 }
320 }
321
322 /// Expand the MemoryAccess according to its domain.
323 ///
324 /// @param S The SCop in which the memory access appears in.
325 /// @param MA The memory access that need to be expanded.
326 ScopArrayInfo *expandAccess(MemoryAccess *MA) {
327 // Get the current AM.
328 auto CurrentAccessMap = MA->getAccessRelation();
329
330 unsigned in_dimensions =
331 unsignedFromIslSize(CurrentAccessMap.domain_tuple_dim());
332
333 // Get domain from the current AM.
334 auto Domain = CurrentAccessMap.domain();
335
336 // Create a new AM from the domain.
337 auto NewAccessMap = isl::map::from_domain(Domain);
338
339 // Add dimensions to the new AM according to the current in_dim.
340 NewAccessMap = NewAccessMap.add_dims(isl::dim::out, in_dimensions);
341
342 // Create the string representing the name of the new SAI.
343 // One new SAI for each statement so that each write go to a different
344 // memory cell.
345 auto CurrentStmtDomain = MA->getStatement()->getDomain();
346 auto CurrentStmtName = CurrentStmtDomain.get_tuple_name();
347 auto CurrentOutId = CurrentAccessMap.get_tuple_id(isl::dim::out);
348 std::string CurrentOutIdString =
349 MA->getScopArrayInfo()->getName() + "_" + CurrentStmtName + "_expanded";
350
351 // Set the tuple id for the out dimension.
352 NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, CurrentOutId);
353
354 // Create the size vector.
355 std::vector<unsigned> Sizes;
356 for (unsigned i = 0; i < in_dimensions; i++) {
357 assert(isDimBoundedByConstant(CurrentStmtDomain, i) &&
358 "Domain boundary are not constant.");
359 auto UpperBound = getConstant(CurrentStmtDomain.dim_max(i), true, false);
360 assert(!UpperBound.is_null() && UpperBound.is_pos() &&
361 !UpperBound.is_nan() &&
362 "The upper bound is not a positive integer.");
363 assert(UpperBound.le(isl::val(CurrentAccessMap.ctx(),
364 std::numeric_limits<int>::max() - 1)) &&
365 "The upper bound overflow a int.");
366 Sizes.push_back(UpperBound.get_num_si() + 1);
367 }
368
369 // Get the ElementType of the current SAI.
370 auto ElementType = MA->getLatestScopArrayInfo()->getElementType();
371
372 // Create (or get if already existing) the new expanded SAI.
373 auto ExpandedSAI =
374 S.createScopArrayInfo(ElementType, CurrentOutIdString, Sizes);
375 ExpandedSAI->setIsOnHeap(true);
376
377 // Get the out Id of the expanded Array.
378 auto NewOutId = ExpandedSAI->getBasePtrId();
379
380 // Set the out id of the new AM to the new SAI id.
381 NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, NewOutId);
382
383 // Add constraints to linked output with input id.
384 auto SpaceMap = NewAccessMap.get_space();
385 auto ConstraintBasicMap = isl::basic_map::equal(
386 SpaceMap, unsignedFromIslSize(SpaceMap.dim(isl::dim::in)));
387 NewAccessMap = isl::map(ConstraintBasicMap);
388
389 // Set the new access relation map.
390 MA->setNewAccessRelation(NewAccessMap);
391
392 return ExpandedSAI;
393 }
394
395 /// Expand PHI memory accesses.
396 ///
397 /// @param The SCop in which the memory access appears in.
398 /// @param The ScopArrayInfo representing the PHI accesses to expand.
399 /// @param Dependences The RAW dependences of the SCop.
400 void expandPhi(Scop &S, const ScopArrayInfo *SAI,
402 SmallPtrSet<MemoryAccess *, 4> Writes;
403 for (auto MA : S.getPHIIncomings(SAI))
404 Writes.insert(MA);
405 auto Read = S.getPHIRead(SAI);
406 auto ExpandedSAI = expandAccess(Read);
407
408 mapAccess(Writes, Dependences, ExpandedSAI, false);
409 }
410
411public:
412 MaximalStaticExpansionImpl(Scop &S, isl::union_map &Dependences,
413 OptimizationRemarkEmitter &ORE)
414 : ORE(ORE), S(S), Dependences(Dependences) {}
415
416 /// Expand the accesses of the SCoP
417 ///
418 /// @param S The SCoP that must be expanded
419 /// @param D The dependencies information of SCoP
420 void expand() {
421 SmallVector<ScopArrayInfo *, 4> CurrentSAI(S.arrays().begin(),
422 S.arrays().end());
423 for (auto SAI : CurrentSAI) {
424 SmallPtrSet<MemoryAccess *, 4> AllWrites;
425 SmallPtrSet<MemoryAccess *, 4> AllReads;
426 if (!isExpandable(SAI, AllWrites, AllReads, S))
427 continue;
428
429 if (SAI->isValueKind() || SAI->isArrayKind()) {
430 assert(AllWrites.size() == 1 || SAI->isValueKind());
431
432 auto TheWrite = *(AllWrites.begin());
433 ScopArrayInfo *ExpandedArray = expandAccess(TheWrite);
434
435 mapAccess(AllReads, Dependences, ExpandedArray, true);
436 } else if (SAI->isPHIKind()) {
437 expandPhi(S, SAI, Dependences);
438 }
439 }
440 }
441
442 /// Dump the internal information about a performed MSE to @p OS.
443 void print(llvm::raw_ostream &OS) {
444 OS << "After arrays {\n";
445
446 for (auto &Array : S.arrays())
447 Array->print(OS);
448
449 OS << "}\n";
450
451 OS << "After accesses {\n";
452 for (auto &Stmt : S) {
453 OS.indent(4) << Stmt.getBaseName() << "{\n";
454 for (auto *MA : Stmt)
455 MA->print(OS);
456 OS.indent(4) << "}\n";
457 }
458 OS << "}\n";
459 }
460};
461
462static std::unique_ptr<MaximalStaticExpansionImpl>
463runMaximalStaticExpansion(Scop &S, OptimizationRemarkEmitter &ORE,
464 const Dependences &D) {
466
467 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
468 std::make_unique<MaximalStaticExpansionImpl>(S, Dependences, ORE);
469
470 Impl->expand();
471 return Impl;
472}
473
474static PreservedAnalyses runMSEUsingNPM(Scop &S, ScopAnalysisManager &SAM,
476 raw_ostream *OS) {
477 OptimizationRemarkEmitter ORE(&S.getFunction());
478
479 auto &DI = SAM.getResult<DependenceAnalysis>(S, SAR);
481
482 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
483 runMaximalStaticExpansion(S, ORE, D);
484
485 if (OS) {
486 *OS << "Printing analysis 'Polly - Maximal static expansion of SCoP' for "
487 "region: '"
488 << S.getName() << "' in function '" << S.getFunction().getName()
489 << "':\n";
490
491 if (Impl) {
492 *OS << "MSE result:\n";
493 Impl->print(*OS);
494 }
495 }
496
497 return PreservedAnalyses::all();
498}
499
500} // namespace
501
502PreservedAnalyses
505 SPMUpdater &) {
506 return runMSEUsingNPM(S, SAM, SAR, nullptr);
507}
508
509PreservedAnalyses
512 SPMUpdater &) {
513 return runMSEUsingNPM(S, SAM, SAR, &OS);
514}
515
516char MaximalStaticExpanderWrapperPass::ID = 0;
517
518bool MaximalStaticExpanderWrapperPass::runOnScop(Scop &S) {
519 // Get the ORE from OptimizationRemarkEmitterWrapperPass.
520 OptimizationRemarkEmitter *ORE =
521 &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
522
523 // Get the RAW Dependences.
524 auto &DI = getAnalysis<DependenceInfo>();
525 auto &D = DI.getDependences(Dependences::AL_Reference);
526
527 std::unique_ptr<MaximalStaticExpansionImpl> Impl =
528 runMaximalStaticExpansion(S, *ORE, D);
529
530 return false;
531}
532
533void MaximalStaticExpanderWrapperPass::printScop(raw_ostream &OS,
534 Scop &S) const {
535 S.print(OS, false);
536}
537
538void MaximalStaticExpanderWrapperPass::getAnalysisUsage(
539 AnalysisUsage &AU) const {
541 AU.addRequired<DependenceInfo>();
542 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
543}
544
546 return new MaximalStaticExpanderWrapperPass();
547}
548
549INITIALIZE_PASS_BEGIN(MaximalStaticExpanderWrapperPass, "polly-mse",
550 "Polly - Maximal static expansion of SCoP", false, false);
552INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass);
553INITIALIZE_PASS_END(MaximalStaticExpanderWrapperPass, "polly-mse",
554 "Polly - Maximal static expansion of SCoP", false, false)
INITIALIZE_PASS_BEGIN(DependenceInfo, "polly-dependences", "Polly - Calculate dependences", false, false)
INITIALIZE_PASS_END(DependenceInfo, "polly-dependences", "Polly - Calculate dependences", false, false) namespace
INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass)
unsigned unsignedFromIslSize(const isl::size &Size)
Check that Size is valid (only on debug builds) and cast it to unsigned.
Definition: ISLTools.h:40
#define DEBUG_TYPE
static isl::basic_map equal(isl::space space, unsigned int n_equal)
static isl::map from_union_map(isl::union_map umap)
static isl::map from_domain(isl::set set)
isl::set domain() const
isl::set project_out(isl::dim type, unsigned int first, unsigned int n) const
isl::id get_tuple_id() const
boolean is_bounded() const
class size tuple_dim() const
class size dim(isl::dim type) const
std::string get_tuple_name() const
isl::union_map unite(isl::union_map umap2) const
boolean is_empty() const
__isl_keep isl_union_map * get() const
static isl::union_map empty(isl::ctx ctx)
static isl::union_set empty(isl::ctx ctx)
The accumulated dependence information for a SCoP.
isl::union_map getDependences(int Kinds) const
Get the dependences of type Kinds.
llvm::PreservedAnalyses run(Scop &, ScopAnalysisManager &, ScopStandardAnalysisResults &, SPMUpdater &)
Represent memory accesses in statements.
Definition: ScopInfo.h:431
const ScopArrayInfo * getLatestScopArrayInfo() const
Get the ScopArrayInfo object for the base address, or the one set by setNewAccessRelation().
Definition: ScopInfo.cpp:557
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
Definition: ScopInfo.h:883
bool isRead() const
Is this a read memory access?
Definition: ScopInfo.h:758
bool isMustWrite() const
Is this a must-write memory access?
Definition: ScopInfo.h:761
void print(raw_ostream &OS) const
Print the MemoryAccess.
Definition: ScopInfo.cpp:925
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
Definition: ScopInfo.h:851
ScopStmt * getStatement() const
Get the statement that contains this memory access.
Definition: ScopInfo.h:1029
bool isMayWrite() const
Is this a may-write memory access?
Definition: ScopInfo.h:764
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
Definition: ScopInfo.h:793
void setNewAccessRelation(isl::map NewAccessRelation)
Set the updated access relation read from JSCOP file.
Definition: ScopInfo.cpp:1036
A class to store information about arrays in the SCoP.
Definition: ScopInfo.h:219
bool isExitPHIKind() const
Is this array info modeling an MemoryKind::ExitPHI?
Definition: ScopInfo.h:340
bool isArrayKind() const
Is this array info modeling an array?
Definition: ScopInfo.h:343
bool isValueKind() const
Is this array info modeling an llvm::Value?
Definition: ScopInfo.h:325
void setIsOnHeap(bool value)
Definition: ScopInfo.h:269
std::string getName() const
Get the name of this memory reference.
Definition: ScopInfo.cpp:336
bool isPHIKind() const
Is this array info modeling special PHI node memory?
Definition: ScopInfo.h:337
isl::id getBasePtrId() const
Return the isl id for the base pointer.
Definition: ScopInfo.cpp:342
Type * getElementType() const
Get the canonical element type of this array.
Definition: ScopInfo.h:310
ScopPass - This class adapts the RegionPass interface to allow convenient creation of passes that ope...
Definition: ScopPass.h:161
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: ScopPass.cpp:44
virtual bool runOnScop(Scop &S)=0
runOnScop - This method must be overloaded to perform the desired Polyhedral transformation or analys...
virtual void printScop(raw_ostream &OS, Scop &S) const
Print method for SCoPs.
Definition: ScopPass.h:173
Statement of the Scop.
Definition: ScopInfo.h:1138
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
Definition: ScopInfo.cpp:1229
Static Control Part.
Definition: ScopInfo.h:1628
static __isl_give isl_poly * expand(__isl_take isl_poly *poly, int *exp, int first)
#define assert(exp)
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
llvm::Pass * createMaximalStaticExpansionPass()
@ Array
MemoryKind::Array: Models a one or multi-dimensional array.
isl::val getConstant(isl::pw_aff PwAff, bool Max, bool Min)
If PwAff maps to a constant, return said constant.
Definition: ISLTools.cpp:552
AnalysisManager< Scop, ScopStandardAnalysisResults & > ScopAnalysisManager
Definition: ScopPass.h:46
PreservedAnalyses run(Scop &S, ScopAnalysisManager &, ScopStandardAnalysisResults &SAR, SPMUpdater &)
static TupleKindPtr Domain("Domain")
isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap)