1 //===------ DeLICM.cpp -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Undo the effect of Loop Invariant Code Motion (LICM) and
11 // GVN Partial Redundancy Elimination (PRE) on SCoP-level.
12 //
13 // Namely, remove register/scalar dependencies by mapping them back to array
14 // elements.
15 //
16 // The algorithms here work on the scatter space - the image space of the
17 // schedule returned by Scop::getSchedule(). We call an element in that space a
18 // "timepoint". Timepoints are lexicographically ordered such that we can
19 // defined ranges in the scatter space. We use two flavors of such ranges:
20 // Timepoint sets and zones. A timepoint set is simply a subset of the scatter
21 // space and is directly stored as isl_set.
22 //
23 // Zones are used to describe the space between timepoints as open sets, i.e.
24 // they do not contain the extrema. Using isl rational sets to express these
25 // would be overkill. We also cannot store them as the integer timepoints they
26 // contain; the (nonempty) zone between 1 and 2 would be empty and
27 // indistinguishable from e.g. the zone between 3 and 4. Also, we cannot store
28 // the integer set including the extrema; the set ]1,2[ + ]3,4[ could be
29 // coalesced to ]1,3[, although we defined the range [2,3] to be not in the set.
30 // Instead, we store the "half-open" integer extrema, including the lower bound,
31 // but excluding the upper bound. Examples:
32 //
33 // * The set { [i] : 1 <= i <= 3 } represents the zone ]0,3[ (which contains the
34 //   integer points 1 and 2, but not 0 or 3)
35 //
36 // * { [1] } represents the zone ]0,1[
37 //
38 // * { [i] : i = 1 or i = 3 } represents the zone ]0,1[ + ]2,3[
39 //
40 // Therefore, an integer i in the set represents the zone ]i-1,i[, i.e. strictly
41 // speaking the integer points never belong to the zone. However, depending an
42 // the interpretation, one might want to include them. Part of the
43 // interpretation may not be known when the zone is constructed.
44 //
45 // Reads are assumed to always take place before writes, hence we can think of
46 // reads taking place at the beginning of a timepoint and writes at the end.
47 //
48 // Let's assume that the zone represents the lifetime of a variable. That is,
49 // the zone begins with a write that defines the value during its lifetime and
50 // ends with the last read of that value. In the following we consider whether a
51 // read/write at the beginning/ending of the lifetime zone should be within the
52 // zone or outside of it.
53 //
54 // * A read at the timepoint that starts the live-range loads the previous
55 //   value. Hence, exclude the timepoint starting the zone.
56 //
57 // * A write at the timepoint that starts the live-range is not defined whether
58 //   it occurs before or after the write that starts the lifetime. We do not
59 //   allow this situation to occur. Hence, we include the timepoint starting the
60 //   zone to determine whether they are conflicting.
61 //
62 // * A read at the timepoint that ends the live-range reads the same variable.
63 //   We include the timepoint at the end of the zone to include that read into
64 //   the live-range. Doing otherwise would mean that the two reads access
65 //   different values, which would mean that the value they read are both alive
66 //   at the same time but occupy the same variable.
67 //
68 // * A write at the timepoint that ends the live-range starts a new live-range.
69 //   It must not be included in the live-range of the previous definition.
70 //
71 // All combinations of reads and writes at the endpoints are possible, but most
72 // of the time only the write->read (for instance, a live-range from definition
73 // to last use) and read->write (for instance, an unused range from last use to
74 // overwrite) and combinations are interesting (half-open ranges). write->write
75 // zones might be useful as well in some context to represent
76 // output-dependencies.
77 //
78 // @see convertZoneToTimepoints
79 //
80 //
81 // The code makes use of maps and sets in many different spaces. To not loose
82 // track in which space a set or map is expected to be in, variables holding an
83 // isl reference are usually annotated in the comments. They roughly follow isl
84 // syntax for spaces, but only the tuples, not the dimensions. The tuples have a
85 // meaning as follows:
86 //
87 // * Space[] - An unspecified tuple. Used for function parameters such that the
88 //             function caller can use it for anything they like.
89 //
90 // * Domain[] - A statement instance as returned by ScopStmt::getDomain()
91 //     isl_id_get_name: Stmt_<NameOfBasicBlock>
92 //     isl_id_get_user: Pointer to ScopStmt
93 //
94 // * Element[] - An array element as in the range part of
95 //               MemoryAccess::getAccessRelation()
96 //     isl_id_get_name: MemRef_<NameOfArrayVariable>
97 //     isl_id_get_user: Pointer to ScopArrayInfo
98 //
99 // * Scatter[] - Scatter space or space of timepoints
100 //     Has no tuple id
101 //
102 // * Zone[] - Range between timepoints as described above
103 //     Has no tuple id
104 //
105 // An annotation "{ Domain[] -> Scatter[] }" therefore means: A map from a
106 // statement instance to a timepoint, aka a schedule. There is only one scatter
107 // space, but most of the time multiple statements are processed in one set.
108 // This is why most of the time isl_union_map has to be used.
109 //
110 // The basic algorithm works as follows:
111 // At first we verify that the SCoP is compatible with this technique. For
112 // instance, two writes cannot write to the same location at the same statement
113 // instance because we cannot determine within the polyhedral model which one
114 // comes first. Once this was verified, we compute zones at which an array
115 // element is unused. This computation can fail if it takes too long. Then the
116 // main algorithm is executed. Because every store potentially trails an unused
117 // zone, we start at stores. We search for a scalar (MemoryKind::Value or
118 // MemoryKind::PHI) that we can map to the array element overwritten by the
119 // store, preferably one that is used by the store or at least the ScopStmt.
120 // When it does not conflict with the lifetime of the values in the array
121 // element, the map is applied and the unused zone updated as it is now used. We
122 // continue to try to map scalars to the array element until there are no more
123 // candidates to map. The algorithm is greedy in the sense that the first scalar
124 // not conflicting will be mapped. Other scalars processed later that could have
125 // fit the same unused zone will be rejected. As such the result depends on the
126 // processing order.
127 //
128 //===----------------------------------------------------------------------===//
129 
130 #include "polly/DeLICM.h"
131 #include "polly/Options.h"
132 #include "polly/ScopInfo.h"
133 #include "polly/ScopPass.h"
134 #include "polly/Support/ISLTools.h"
135 #include "llvm/ADT/Statistic.h"
136 #define DEBUG_TYPE "polly-delicm"
137 
138 using namespace polly;
139 using namespace llvm;
140 
141 namespace {
142 
143 cl::opt<int>
144     DelicmMaxOps("polly-delicm-max-ops",
145                  cl::desc("Maximum number of isl operations to invest for "
146                           "lifetime analysis; 0=no limit"),
147                  cl::init(1000000), cl::cat(PollyCategory));
148 
149 STATISTIC(DeLICMAnalyzed, "Number of successfully analyzed SCoPs");
150 STATISTIC(DeLICMOutOfQuota,
151           "Analyses aborted because max_operations was reached");
152 STATISTIC(DeLICMIncompatible, "Number of SCoPs incompatible for analysis");
153 STATISTIC(MappedValueScalars, "Number of mapped Value scalars");
154 STATISTIC(MappedPHIScalars, "Number of mapped PHI scalars");
155 STATISTIC(TargetsMapped, "Number of stores used for at least one mapping");
156 STATISTIC(DeLICMScopsModified, "Number of SCoPs optimized");
157 
158 /// Class for keeping track of scalar def-use chains in the polyhedral
159 /// representation.
160 ///
161 /// MemoryKind::Value:
162 /// There is one definition per llvm::Value or zero (read-only values defined
163 /// before the SCoP) and an arbitrary number of reads.
164 ///
165 /// MemoryKind::PHI, MemoryKind::ExitPHI:
166 /// There is at least one write (the incoming blocks/stmts) and one
167 /// (MemoryKind::PHI) or zero (MemoryKind::ExitPHI) reads per llvm::PHINode.
168 class ScalarDefUseChains {
169 private:
170   /// The definitions (i.e. write MemoryAccess) of a MemoryKind::Value scalar.
171   DenseMap<const ScopArrayInfo *, MemoryAccess *> ValueDefAccs;
172 
173   /// List of all uses (i.e. read MemoryAccesses) for a MemoryKind::Value
174   /// scalar.
175   DenseMap<const ScopArrayInfo *, SmallVector<MemoryAccess *, 4>> ValueUseAccs;
176 
177   /// The receiving part (i.e. read MemoryAccess) of a MemoryKind::PHI scalar.
178   DenseMap<const ScopArrayInfo *, MemoryAccess *> PHIReadAccs;
179 
180   /// List of all incoming values (write MemoryAccess) of a MemoryKind::PHI or
181   /// MemoryKind::ExitPHI scalar.
182   DenseMap<const ScopArrayInfo *, SmallVector<MemoryAccess *, 4>>
183       PHIIncomingAccs;
184 
185 public:
186   /// Find the MemoryAccesses that access the ScopArrayInfo-represented memory.
187   ///
188   /// @param S The SCoP to analyze.
189   void compute(Scop *S) {
190     // Purge any previous result.
191     reset();
192 
193     for (auto &Stmt : *S) {
194       for (auto *MA : Stmt) {
195         if (MA->isOriginalValueKind() && MA->isWrite()) {
196           auto *SAI = MA->getScopArrayInfo();
197           assert(!ValueDefAccs.count(SAI) &&
198                  "There can be at most one "
199                  "definition per MemoryKind::Value scalar");
200           ValueDefAccs[SAI] = MA;
201         }
202 
203         if (MA->isOriginalValueKind() && MA->isRead())
204           ValueUseAccs[MA->getScopArrayInfo()].push_back(MA);
205 
206         if (MA->isOriginalAnyPHIKind() && MA->isRead()) {
207           auto *SAI = MA->getScopArrayInfo();
208           assert(!PHIReadAccs.count(SAI) &&
209                  "There must be exactly one read "
210                  "per PHI (that's where the PHINode is)");
211           PHIReadAccs[SAI] = MA;
212         }
213 
214         if (MA->isOriginalAnyPHIKind() && MA->isWrite())
215           PHIIncomingAccs[MA->getScopArrayInfo()].push_back(MA);
216       }
217     }
218   }
219 
220   /// Free all memory used by the analysis.
221   void reset() {
222     ValueDefAccs.clear();
223     ValueUseAccs.clear();
224     PHIReadAccs.clear();
225     PHIIncomingAccs.clear();
226   }
227 
228   MemoryAccess *getValueDef(const ScopArrayInfo *SAI) const {
229     return ValueDefAccs.lookup(SAI);
230   }
231 
232   ArrayRef<MemoryAccess *> getValueUses(const ScopArrayInfo *SAI) const {
233     auto It = ValueUseAccs.find(SAI);
234     if (It == ValueUseAccs.end())
235       return {};
236     return It->second;
237   }
238 
239   MemoryAccess *getPHIRead(const ScopArrayInfo *SAI) const {
240     return PHIReadAccs.lookup(SAI);
241   }
242 
243   ArrayRef<MemoryAccess *> getPHIIncomings(const ScopArrayInfo *SAI) const {
244     auto It = PHIIncomingAccs.find(SAI);
245     if (It == PHIIncomingAccs.end())
246       return {};
247     return It->second;
248   }
249 };
250 
251 IslPtr<isl_union_map> computeReachingDefinition(IslPtr<isl_union_map> Schedule,
252                                                 IslPtr<isl_union_map> Writes,
253                                                 bool InclDef, bool InclRedef) {
254   return computeReachingWrite(Schedule, Writes, false, InclDef, InclRedef);
255 }
256 
257 IslPtr<isl_union_map> computeReachingOverwrite(IslPtr<isl_union_map> Schedule,
258                                                IslPtr<isl_union_map> Writes,
259                                                bool InclPrevWrite,
260                                                bool InclOverwrite) {
261   return computeReachingWrite(Schedule, Writes, true, InclPrevWrite,
262                               InclOverwrite);
263 }
264 
265 /// Compute the next overwrite for a scalar.
266 ///
267 /// @param Schedule      { DomainWrite[] -> Scatter[] }
268 ///                      Schedule of (at least) all writes. Instances not in @p
269 ///                      Writes are ignored.
270 /// @param Writes        { DomainWrite[] }
271 ///                      The element instances that write to the scalar.
272 /// @param InclPrevWrite Whether to extend the timepoints to include
273 ///                      the timepoint where the previous write happens.
274 /// @param InclOverwrite Whether the reaching overwrite includes the timepoint
275 ///                      of the overwrite itself.
276 ///
277 /// @return { Scatter[] -> DomainDef[] }
278 IslPtr<isl_union_map>
279 computeScalarReachingOverwrite(IslPtr<isl_union_map> Schedule,
280                                IslPtr<isl_union_set> Writes, bool InclPrevWrite,
281                                bool InclOverwrite) {
282 
283   // { DomainWrite[] }
284   auto WritesMap = give(isl_union_map_from_domain(Writes.take()));
285 
286   // { [Element[] -> Scatter[]] -> DomainWrite[] }
287   auto Result = computeReachingOverwrite(
288       std::move(Schedule), std::move(WritesMap), InclPrevWrite, InclOverwrite);
289 
290   return give(isl_union_map_domain_factor_range(Result.take()));
291 }
292 
293 /// Overload of computeScalarReachingOverwrite, with only one writing statement.
294 /// Consequently, the result consists of only one map space.
295 ///
296 /// @param Schedule      { DomainWrite[] -> Scatter[] }
297 /// @param Writes        { DomainWrite[] }
298 /// @param InclPrevWrite Include the previous write to result.
299 /// @param InclOverwrite Include the overwrite to the result.
300 ///
301 /// @return { Scatter[] -> DomainWrite[] }
302 IslPtr<isl_map> computeScalarReachingOverwrite(IslPtr<isl_union_map> Schedule,
303                                                IslPtr<isl_set> Writes,
304                                                bool InclPrevWrite,
305                                                bool InclOverwrite) {
306   auto ScatterSpace = getScatterSpace(Schedule);
307   auto DomSpace = give(isl_set_get_space(Writes.keep()));
308 
309   auto ReachOverwrite = computeScalarReachingOverwrite(
310       Schedule, give(isl_union_set_from_set(Writes.take())), InclPrevWrite,
311       InclOverwrite);
312 
313   auto ResultSpace = give(isl_space_map_from_domain_and_range(
314       ScatterSpace.take(), DomSpace.take()));
315   return singleton(std::move(ReachOverwrite), ResultSpace);
316 }
317 
318 /// Compute the reaching definition of a scalar.
319 ///
320 /// Compared to computeReachingDefinition, there is just one element which is
321 /// accessed and therefore only a set if instances that accesses that element is
322 /// required.
323 ///
324 /// @param Schedule  { DomainWrite[] -> Scatter[] }
325 /// @param Writes    { DomainWrite[] }
326 /// @param InclDef   Include the timepoint of the definition to the result.
327 /// @param InclRedef Include the timepoint of the overwrite into the result.
328 ///
329 /// @return { Scatter[] -> DomainWrite[] }
330 IslPtr<isl_union_map>
331 computeScalarReachingDefinition(IslPtr<isl_union_map> Schedule,
332                                 IslPtr<isl_union_set> Writes, bool InclDef,
333                                 bool InclRedef) {
334 
335   // { DomainWrite[] -> Element[] }
336   auto Defs = give(isl_union_map_from_domain(Writes.take()));
337 
338   // { [Element[] -> Scatter[]] -> DomainWrite[] }
339   auto ReachDefs =
340       computeReachingDefinition(Schedule, Defs, InclDef, InclRedef);
341 
342   // { Scatter[] -> DomainWrite[] }
343   return give(isl_union_set_unwrap(
344       isl_union_map_range(isl_union_map_curry(ReachDefs.take()))));
345 }
346 
347 /// Compute the reaching definition of a scalar.
348 ///
349 /// This overload accepts only a single writing statement as an isl_map,
350 /// consequently the result also is only a single isl_map.
351 ///
352 /// @param Schedule  { DomainWrite[] -> Scatter[] }
353 /// @param Writes    { DomainWrite[] }
354 /// @param InclDef   Include the timepoint of the definition to the result.
355 /// @param InclRedef Include the timepoint of the overwrite into the result.
356 ///
357 /// @return { Scatter[] -> DomainWrite[] }
358 IslPtr<isl_map> computeScalarReachingDefinition( // { Domain[] -> Zone[] }
359     IslPtr<isl_union_map> Schedule, IslPtr<isl_set> Writes, bool InclDef,
360     bool InclRedef) {
361   auto DomainSpace = give(isl_set_get_space(Writes.keep()));
362   auto ScatterSpace = getScatterSpace(Schedule);
363 
364   //  { Scatter[] -> DomainWrite[] }
365   auto UMap = computeScalarReachingDefinition(
366       Schedule, give(isl_union_set_from_set(Writes.take())), InclDef,
367       InclRedef);
368 
369   auto ResultSpace = give(isl_space_map_from_domain_and_range(
370       ScatterSpace.take(), DomainSpace.take()));
371   return singleton(UMap, ResultSpace);
372 }
373 
374 /// If InputVal is not defined in the stmt itself, return the MemoryAccess that
375 /// reads the scalar. Return nullptr otherwise (if the value is defined in the
376 /// scop, or is synthesizable).
377 MemoryAccess *getInputAccessOf(Value *InputVal, ScopStmt *Stmt) {
378   for (auto *MA : *Stmt) {
379     if (!MA->isRead())
380       continue;
381     if (!MA->isLatestScalarKind())
382       continue;
383 
384     assert(MA->getAccessValue() == MA->getBaseAddr());
385     if (MA->getAccessValue() == InputVal)
386       return MA;
387   }
388   return nullptr;
389 }
390 
391 /// Represent the knowledge of the contents of any array elements in any zone or
392 /// the knowledge we would add when mapping a scalar to an array element.
393 ///
394 /// Every array element at every zone unit has one of two states:
395 ///
396 /// - Unused: Not occupied by any value so a transformation can change it to
397 ///   other values.
398 ///
399 /// - Occupied: The element contains a value that is still needed.
400 ///
401 /// The union of Unused and Unknown zones forms the universe, the set of all
402 /// elements at every timepoint. The universe can easily be derived from the
403 /// array elements that are accessed someway. Arrays that are never accessed
404 /// also never play a role in any computation and can hence be ignored. With a
405 /// given universe, only one of the sets needs to stored implicitly. Computing
406 /// the complement is also an expensive operation, hence this class has been
407 /// designed that only one of sets is needed while the other is assumed to be
408 /// implicit. It can still be given, but is mostly ignored.
409 ///
410 /// There are two use cases for the Knowledge class:
411 ///
412 /// 1) To represent the knowledge of the current state of ScopInfo. The unused
413 ///    state means that an element is currently unused: there is no read of it
414 ///    before the next overwrite. Also called 'Existing'.
415 ///
416 /// 2) To represent the requirements for mapping a scalar to array elements. The
417 ///    unused state means that there is no change/requirement. Also called
418 ///    'Proposed'.
419 ///
420 /// In addition to these states at unit zones, Knowledge needs to know when
421 /// values are written. This is because written values may have no lifetime (one
422 /// reason is that the value is never read). Such writes would therefore never
423 /// conflict, but overwrite values that might still be required. Another source
424 /// of problems are multiple writes to the same element at the same timepoint,
425 /// because their order is undefined.
426 class Knowledge {
427 private:
428   /// { [Element[] -> Zone[]] }
429   /// Set of array elements and when they are alive.
430   /// Can contain a nullptr; in this case the set is implicitly defined as the
431   /// complement of #Unused.
432   ///
433   /// The set of alive array elements is represented as zone, as the set of live
434   /// values can differ depending on how the elements are interpreted.
435   /// Assuming a value X is written at timestep [0] and read at timestep [1]
436   /// without being used at any later point, then the value is alive in the
437   /// interval ]0,1[. This interval cannot be represented by an integer set, as
438   /// it does not contain any integer point. Zones allow us to represent this
439   /// interval and can be converted to sets of timepoints when needed (e.g., in
440   /// isConflicting when comparing to the write sets).
441   /// @see convertZoneToTimepoints and this file's comment for more details.
442   IslPtr<isl_union_set> Occupied;
443 
444   /// { [Element[] -> Zone[]] }
445   /// Set of array elements when they are not alive, i.e. their memory can be
446   /// used for other purposed. Can contain a nullptr; in this case the set is
447   /// implicitly defined as the complement of #Occupied.
448   IslPtr<isl_union_set> Unused;
449 
450   /// { [Element[] -> Scatter[]] }
451   /// The write actions currently in the scop or that would be added when
452   /// mapping a scalar.
453   IslPtr<isl_union_set> Written;
454 
455   /// Check whether this Knowledge object is well-formed.
456   void checkConsistency() const {
457 #ifndef NDEBUG
458     // Default-initialized object
459     if (!Occupied && !Unused && !Written)
460       return;
461 
462     assert(Occupied || Unused);
463     assert(Written);
464 
465     // If not all fields are defined, we cannot derived the universe.
466     if (!Occupied || !Unused)
467       return;
468 
469     assert(isl_union_set_is_disjoint(Occupied.keep(), Unused.keep()) ==
470            isl_bool_true);
471     auto Universe = give(isl_union_set_union(Occupied.copy(), Unused.copy()));
472     assert(isl_union_set_is_subset(Written.keep(), Universe.keep()) ==
473            isl_bool_true);
474 #endif
475   }
476 
477 public:
478   /// Initialize a nullptr-Knowledge. This is only provided for convenience; do
479   /// not use such an object.
480   Knowledge() {}
481 
482   /// Create a new object with the given members.
483   Knowledge(IslPtr<isl_union_set> Occupied, IslPtr<isl_union_set> Unused,
484             IslPtr<isl_union_set> Written)
485       : Occupied(std::move(Occupied)), Unused(std::move(Unused)),
486         Written(std::move(Written)) {
487     checkConsistency();
488   }
489 
490   /// Alternative constructor taking isl_sets instead isl_union_sets.
491   Knowledge(IslPtr<isl_set> Occupied, IslPtr<isl_set> Unused,
492             IslPtr<isl_set> Written)
493       : Knowledge(give(isl_union_set_from_set(Occupied.take())),
494                   give(isl_union_set_from_set(Unused.take())),
495                   give(isl_union_set_from_set(Written.take()))) {}
496 
497   /// Return whether this object was not default-constructed.
498   bool isUsable() const { return (Occupied || Unused) && Written; }
499 
500   /// Print the content of this object to @p OS.
501   void print(llvm::raw_ostream &OS, unsigned Indent = 0) const {
502     if (isUsable()) {
503       if (Occupied)
504         OS.indent(Indent) << "Occupied: " << Occupied << "\n";
505       else
506         OS.indent(Indent) << "Occupied: <Everything else not in Unused>\n";
507       if (Unused)
508         OS.indent(Indent) << "Unused:   " << Unused << "\n";
509       else
510         OS.indent(Indent) << "Unused:   <Everything else not in Occupied>\n";
511       OS.indent(Indent) << "Written : " << Written << '\n';
512     } else {
513       OS.indent(Indent) << "Invalid knowledge\n";
514     }
515   }
516 
517   /// Combine two knowledges, this and @p That.
518   void learnFrom(Knowledge That) {
519     assert(!isConflicting(*this, That));
520     assert(Unused && That.Occupied);
521     assert(
522         !That.Unused &&
523         "This function is only prepared to learn occupied elements from That");
524     assert(!Occupied && "This function does not implement "
525                         "`this->Occupied = "
526                         "give(isl_union_set_union(this->Occupied.take(), "
527                         "That.Occupied.copy()));`");
528 
529     Unused = give(isl_union_set_subtract(Unused.take(), That.Occupied.copy()));
530     Written = give(isl_union_set_union(Written.take(), That.Written.take()));
531 
532     checkConsistency();
533   }
534 
535   /// Determine whether two Knowledges conflict with each other.
536   ///
537   /// In theory @p Existing and @p Proposed are symmetric, but the
538   /// implementation is constrained by the implicit interpretation. That is, @p
539   /// Existing must have #Unused defined (use case 1) and @p Proposed must have
540   /// #Occupied defined (use case 1).
541   ///
542   /// A conflict is defined as non-preserved semantics when they are merged. For
543   /// instance, when for the same array and zone they assume different
544   /// llvm::Values.
545   ///
546   /// @param Existing One of the knowledges with #Unused defined.
547   /// @param Proposed One of the knowledges with #Occupied defined.
548   /// @param OS       Dump the conflict reason to this output stream; use
549   ///                 nullptr to not output anything.
550   /// @param Indent   Indention for the conflict reason.
551   ///
552   /// @return True, iff the two knowledges are conflicting.
553   static bool isConflicting(const Knowledge &Existing,
554                             const Knowledge &Proposed,
555                             llvm::raw_ostream *OS = nullptr,
556                             unsigned Indent = 0) {
557     assert(Existing.Unused);
558     assert(Proposed.Occupied);
559 
560 #ifndef NDEBUG
561     if (Existing.Occupied && Proposed.Unused) {
562       auto ExistingUniverse = give(isl_union_set_union(Existing.Occupied.copy(),
563                                                        Existing.Unused.copy()));
564       auto ProposedUniverse = give(isl_union_set_union(Proposed.Occupied.copy(),
565                                                        Proposed.Unused.copy()));
566       assert(isl_union_set_is_equal(ExistingUniverse.keep(),
567                                     ProposedUniverse.keep()) == isl_bool_true &&
568              "Both inputs' Knowledges must be over the same universe");
569     }
570 #endif
571 
572     // Are the new lifetimes required for Proposed unused in Existing?
573     if (isl_union_set_is_subset(Proposed.Occupied.keep(),
574                                 Existing.Unused.keep()) != isl_bool_true) {
575       if (OS) {
576         auto ConflictingLifetimes = give(isl_union_set_subtract(
577             Proposed.Occupied.copy(), Existing.Unused.copy()));
578         OS->indent(Indent) << "Proposed lifetimes are not unused in existing\n";
579         OS->indent(Indent) << "Conflicting lifetimes: " << ConflictingLifetimes
580                            << "\n";
581       }
582       return true;
583     }
584 
585     // Do the writes in Existing only overwrite unused values in Proposed?
586     // We convert here the set of lifetimes to actual timepoints. A lifetime is
587     // in conflict with a set of write timepoints, if either a live timepoint is
588     // clearly within the lifetime or if a write happens at the beginning of the
589     // lifetime (where it would conflict with the value that actually writes the
590     // value alive). There is no conflict at the end of a lifetime, as the alive
591     // value will always be read, before it is overwritten again. The last
592     // property holds in Polly for all scalar values and we expect all users of
593     // Knowledge to check this property also for accesses to MemoryKind::Array.
594     auto ProposedFixedDefs =
595         convertZoneToTimepoints(Proposed.Occupied, true, false);
596     if (isl_union_set_is_disjoint(Existing.Written.keep(),
597                                   ProposedFixedDefs.keep()) != isl_bool_true) {
598       if (OS) {
599         auto ConflictingWrites = give(isl_union_set_intersect(
600             Existing.Written.copy(), ProposedFixedDefs.copy()));
601         OS->indent(Indent) << "Proposed writes into range used by existing\n";
602         OS->indent(Indent) << "Conflicting writes: " << ConflictingWrites
603                            << "\n";
604       }
605       return true;
606     }
607 
608     // Do the new writes in Proposed only overwrite unused values in Existing?
609     auto ExistingAvailableDefs =
610         convertZoneToTimepoints(Existing.Unused, true, false);
611     if (isl_union_set_is_subset(Proposed.Written.keep(),
612                                 ExistingAvailableDefs.keep()) !=
613         isl_bool_true) {
614       if (OS) {
615         auto ConflictingWrites = give(isl_union_set_subtract(
616             Proposed.Written.copy(), ExistingAvailableDefs.copy()));
617         OS->indent(Indent)
618             << "Proposed a lifetime where there is an Existing write into it\n";
619         OS->indent(Indent) << "Conflicting writes: " << ConflictingWrites
620                            << "\n";
621       }
622       return true;
623     }
624 
625     // Does Proposed write at the same time as Existing already does (order of
626     // writes is undefined)?
627     if (isl_union_set_is_disjoint(Existing.Written.keep(),
628                                   Proposed.Written.keep()) != isl_bool_true) {
629       if (OS) {
630         auto ConflictingWrites = give(isl_union_set_intersect(
631             Existing.Written.copy(), Proposed.Written.copy()));
632         OS->indent(Indent) << "Proposed writes at the same time as an already "
633                               "Existing write\n";
634         OS->indent(Indent) << "Conflicting writes: " << ConflictingWrites
635                            << "\n";
636       }
637       return true;
638     }
639 
640     return false;
641   }
642 };
643 
644 std::string printIntruction(Instruction *Instr, bool IsForDebug = false) {
645   std::string Result;
646   raw_string_ostream OS(Result);
647   Instr->print(OS, IsForDebug);
648   OS.flush();
649   size_t i = 0;
650   while (i < Result.size() && Result[i] == ' ')
651     i += 1;
652   return Result.substr(i);
653 }
654 
655 /// Base class for algorithms based on zones, like DeLICM.
656 class ZoneAlgorithm {
657 protected:
658   /// Hold a reference to the isl_ctx to avoid it being freed before we released
659   /// all of the isl objects.
660   ///
661   /// This must be declared before any other member that holds an isl object.
662   /// This guarantees that the shared_ptr and its isl_ctx is destructed last,
663   /// after all other members free'd the isl objects they were holding.
664   std::shared_ptr<isl_ctx> IslCtx;
665 
666   /// Cached reaching definitions for each ScopStmt.
667   ///
668   /// Use getScalarReachingDefinition() to get its contents.
669   DenseMap<ScopStmt *, IslPtr<isl_map>> ScalarReachDefZone;
670 
671   /// The analyzed Scop.
672   Scop *S;
673 
674   /// Parameter space that does not need realignment.
675   IslPtr<isl_space> ParamSpace;
676 
677   /// Space the schedule maps to.
678   IslPtr<isl_space> ScatterSpace;
679 
680   /// Cached version of the schedule and domains.
681   IslPtr<isl_union_map> Schedule;
682 
683   /// Set of all referenced elements.
684   /// { Element[] -> Element[] }
685   IslPtr<isl_union_set> AllElements;
686 
687   /// Combined access relations of all MemoryKind::Array READ accesses.
688   /// { DomainRead[] -> Element[] }
689   IslPtr<isl_union_map> AllReads;
690 
691   /// Combined access relations of all MemoryKind::Array, MAY_WRITE accesses.
692   /// { DomainMayWrite[] -> Element[] }
693   IslPtr<isl_union_map> AllMayWrites;
694 
695   /// Combined access relations of all MemoryKind::Array, MUST_WRITE accesses.
696   /// { DomainMustWrite[] -> Element[] }
697   IslPtr<isl_union_map> AllMustWrites;
698 
699   /// Prepare the object before computing the zones of @p S.
700   ZoneAlgorithm(Scop *S)
701       : IslCtx(S->getSharedIslCtx()), S(S), Schedule(give(S->getSchedule())) {
702 
703     auto Domains = give(S->getDomains());
704 
705     Schedule =
706         give(isl_union_map_intersect_domain(Schedule.take(), Domains.take()));
707     ParamSpace = give(isl_union_map_get_space(Schedule.keep()));
708     ScatterSpace = getScatterSpace(Schedule);
709   }
710 
711 private:
712   /// Check whether @p Stmt can be accurately analyzed by zones.
713   ///
714   /// What violates our assumptions:
715   /// - A load after a write of the same location; we assume that all reads
716   ///   occur before the writes.
717   /// - Two writes to the same location; we cannot model the order in which
718   ///   these occur.
719   ///
720   /// Scalar reads implicitly always occur before other accesses therefore never
721   /// violate the first condition. There is also at most one write to a scalar,
722   /// satisfying the second condition.
723   bool isCompatibleStmt(ScopStmt *Stmt) {
724     auto Stores = makeEmptyUnionMap();
725     auto Loads = makeEmptyUnionMap();
726 
727     // This assumes that the MemoryKind::Array MemoryAccesses are iterated in
728     // order.
729     for (auto *MA : *Stmt) {
730       if (!MA->isLatestArrayKind())
731         continue;
732 
733       auto AccRel =
734           give(isl_union_map_from_map(getAccessRelationFor(MA).take()));
735 
736       if (MA->isRead()) {
737         // Reject load after store to same location.
738         if (!isl_union_map_is_disjoint(Stores.keep(), AccRel.keep())) {
739           OptimizationRemarkMissed R(DEBUG_TYPE, "LoadAfterStore",
740                                      MA->getAccessInstruction());
741           R << "load after store of same element in same statement";
742           R << " (previous stores: " << Stores;
743           R << ", loading: " << AccRel << ")";
744           S->getFunction().getContext().diagnose(R);
745           return false;
746         }
747 
748         Loads = give(isl_union_map_union(Loads.take(), AccRel.take()));
749 
750         continue;
751       }
752 
753       if (!isa<StoreInst>(MA->getAccessInstruction())) {
754         DEBUG(dbgs() << "WRITE that is not a StoreInst not supported\n");
755         OptimizationRemarkMissed R(DEBUG_TYPE, "UnusualStore",
756                                    MA->getAccessInstruction());
757         R << "encountered write that is not a StoreInst: "
758           << printIntruction(MA->getAccessInstruction());
759         S->getFunction().getContext().diagnose(R);
760         return false;
761       }
762 
763       // In region statements the order is less clear, eg. the load and store
764       // might be in a boxed loop.
765       if (Stmt->isRegionStmt() &&
766           !isl_union_map_is_disjoint(Loads.keep(), AccRel.keep())) {
767         OptimizationRemarkMissed R(DEBUG_TYPE, "StoreInSubregion",
768                                    MA->getAccessInstruction());
769         R << "store is in a non-affine subregion";
770         S->getFunction().getContext().diagnose(R);
771         return false;
772       }
773 
774       // Do not allow more than one store to the same location.
775       if (!isl_union_map_is_disjoint(Stores.keep(), AccRel.keep())) {
776         OptimizationRemarkMissed R(DEBUG_TYPE, "StoreAfterStore",
777                                    MA->getAccessInstruction());
778         R << "store after store of same element in same statement";
779         R << " (previous stores: " << Stores;
780         R << ", storing: " << AccRel << ")";
781         S->getFunction().getContext().diagnose(R);
782         return false;
783       }
784 
785       Stores = give(isl_union_map_union(Stores.take(), AccRel.take()));
786     }
787 
788     return true;
789   }
790 
791   void addArrayReadAccess(MemoryAccess *MA) {
792     assert(MA->isLatestArrayKind());
793     assert(MA->isRead());
794 
795     // { DomainRead[] -> Element[] }
796     auto AccRel = getAccessRelationFor(MA);
797     AllReads = give(isl_union_map_add_map(AllReads.take(), AccRel.copy()));
798   }
799 
800   void addArrayWriteAccess(MemoryAccess *MA) {
801     assert(MA->isLatestArrayKind());
802     assert(MA->isWrite());
803 
804     // { Domain[] -> Element[] }
805     auto AccRel = getAccessRelationFor(MA);
806 
807     if (MA->isMustWrite())
808       AllMustWrites =
809           give(isl_union_map_add_map(AllMustWrites.take(), AccRel.copy()));
810 
811     if (MA->isMayWrite())
812       AllMayWrites =
813           give(isl_union_map_add_map(AllMayWrites.take(), AccRel.copy()));
814   }
815 
816 protected:
817   IslPtr<isl_union_set> makeEmptyUnionSet() {
818     return give(isl_union_set_empty(ParamSpace.copy()));
819   }
820 
821   IslPtr<isl_union_map> makeEmptyUnionMap() {
822     return give(isl_union_map_empty(ParamSpace.copy()));
823   }
824 
825   /// Check whether @p S can be accurately analyzed by zones.
826   bool isCompatibleScop() {
827     for (auto &Stmt : *S) {
828       if (!isCompatibleStmt(&Stmt))
829         return false;
830     }
831     return true;
832   }
833 
834   /// Get the schedule for @p Stmt.
835   ///
836   /// The domain of the result is as narrow as possible.
837   IslPtr<isl_map> getScatterFor(ScopStmt *Stmt) const {
838     auto ResultSpace = give(isl_space_map_from_domain_and_range(
839         Stmt->getDomainSpace(), ScatterSpace.copy()));
840     return give(isl_union_map_extract_map(Schedule.keep(), ResultSpace.take()));
841   }
842 
843   /// Get the schedule of @p MA's parent statement.
844   IslPtr<isl_map> getScatterFor(MemoryAccess *MA) const {
845     return getScatterFor(MA->getStatement());
846   }
847 
848   /// Get the schedule for the statement instances of @p Domain.
849   IslPtr<isl_union_map> getScatterFor(IslPtr<isl_union_set> Domain) const {
850     return give(isl_union_map_intersect_domain(Schedule.copy(), Domain.take()));
851   }
852 
853   /// Get the schedule for the statement instances of @p Domain.
854   IslPtr<isl_map> getScatterFor(IslPtr<isl_set> Domain) const {
855     auto ResultSpace = give(isl_space_map_from_domain_and_range(
856         isl_set_get_space(Domain.keep()), ScatterSpace.copy()));
857     auto UDomain = give(isl_union_set_from_set(Domain.copy()));
858     auto UResult = getScatterFor(std::move(UDomain));
859     auto Result = singleton(std::move(UResult), std::move(ResultSpace));
860     assert(isl_set_is_equal(give(isl_map_domain(Result.copy())).keep(),
861                             Domain.keep()) == isl_bool_true);
862     return Result;
863   }
864 
865   /// Get the domain of @p Stmt.
866   IslPtr<isl_set> getDomainFor(ScopStmt *Stmt) const {
867     return give(Stmt->getDomain());
868   }
869 
870   /// Get the domain @p MA's parent statement.
871   IslPtr<isl_set> getDomainFor(MemoryAccess *MA) const {
872     return getDomainFor(MA->getStatement());
873   }
874 
875   /// Get the access relation of @p MA.
876   ///
877   /// The domain of the result is as narrow as possible.
878   IslPtr<isl_map> getAccessRelationFor(MemoryAccess *MA) const {
879     auto Domain = getDomainFor(MA);
880     auto AccRel = give(MA->getLatestAccessRelation());
881     return give(isl_map_intersect_domain(AccRel.take(), Domain.take()));
882   }
883 
884   /// Get the reaching definition of a scalar defined in @p Stmt.
885   ///
886   /// Note that this does not depend on the llvm::Instruction, only on the
887   /// statement it is defined in. Therefore the same computation can be reused.
888   ///
889   /// @param Stmt The statement in which a scalar is defined.
890   ///
891   /// @return { Scatter[] -> DomainDef[] }
892   IslPtr<isl_map> getScalarReachingDefinition(ScopStmt *Stmt) {
893     auto &Result = ScalarReachDefZone[Stmt];
894     if (Result)
895       return Result;
896 
897     auto Domain = getDomainFor(Stmt);
898     Result = computeScalarReachingDefinition(Schedule, Domain, false, true);
899     simplify(Result);
900 
901     assert(Result);
902     return Result;
903   }
904 
905   /// Compute the different zones.
906   void computeCommon() {
907     AllReads = makeEmptyUnionMap();
908     AllMayWrites = makeEmptyUnionMap();
909     AllMustWrites = makeEmptyUnionMap();
910 
911     for (auto &Stmt : *S) {
912       for (auto *MA : Stmt) {
913         if (!MA->isLatestArrayKind())
914           continue;
915 
916         if (MA->isRead())
917           addArrayReadAccess(MA);
918 
919         if (MA->isWrite())
920           addArrayWriteAccess(MA);
921       }
922     }
923 
924     // { DomainWrite[] -> Element[] }
925     auto AllWrites =
926         give(isl_union_map_union(AllMustWrites.copy(), AllMayWrites.copy()));
927 
928     // { Element[] }
929     AllElements = makeEmptyUnionSet();
930     foreachElt(AllWrites, [this](IslPtr<isl_map> Write) {
931       auto Space = give(isl_map_get_space(Write.keep()));
932       auto EltSpace = give(isl_space_range(Space.take()));
933       auto EltUniv = give(isl_set_universe(EltSpace.take()));
934       AllElements =
935           give(isl_union_set_add_set(AllElements.take(), EltUniv.take()));
936     });
937   }
938 
939   /// Print the current state of all MemoryAccesses to @p.
940   void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const {
941     OS.indent(Indent) << "After accesses {\n";
942     for (auto &Stmt : *S) {
943       OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
944       for (auto *MA : Stmt)
945         MA->print(OS);
946     }
947     OS.indent(Indent) << "}\n";
948   }
949 
950 public:
951   /// Return the SCoP this object is analyzing.
952   Scop *getScop() const { return S; }
953 };
954 
955 /// Implementation of the DeLICM/DePRE transformation.
956 class DeLICMImpl : public ZoneAlgorithm {
957 private:
958   /// Knowledge before any transformation took place.
959   Knowledge OriginalZone;
960 
961   /// Current knowledge of the SCoP including all already applied
962   /// transformations.
963   Knowledge Zone;
964 
965   /// For getting the MemoryAccesses that write or read a given scalar.
966   ScalarDefUseChains DefUse;
967 
968   /// Number of StoreInsts something can be mapped to.
969   int NumberOfCompatibleTargets = 0;
970 
971   /// The number of StoreInsts to which at least one value or PHI has been
972   /// mapped to.
973   int NumberOfTargetsMapped = 0;
974 
975   /// The number of llvm::Value mapped to some array element.
976   int NumberOfMappedValueScalars = 0;
977 
978   /// The number of PHIs mapped to some array element.
979   int NumberOfMappedPHIScalars = 0;
980 
981   /// Determine whether two knowledges are conflicting with each other.
982   ///
983   /// @see Knowledge::isConflicting
984   bool isConflicting(const Knowledge &Proposed) {
985     raw_ostream *OS = nullptr;
986     DEBUG(OS = &llvm::dbgs());
987     return Knowledge::isConflicting(Zone, Proposed, OS, 4);
988   }
989 
990   /// Determine whether @p SAI is a scalar that can be mapped to an array
991   /// element.
992   bool isMappable(const ScopArrayInfo *SAI) {
993     assert(SAI);
994 
995     if (SAI->isValueKind()) {
996       auto *MA = DefUse.getValueDef(SAI);
997       if (!MA) {
998         DEBUG(dbgs()
999               << "    Reject because value is read-only within the scop\n");
1000         return false;
1001       }
1002 
1003       // Mapping if value is used after scop is not supported. The code
1004       // generator would need to reload the scalar after the scop, but it
1005       // does not have the information to where it is mapped to. Only the
1006       // MemoryAccesses have that information, not the ScopArrayInfo.
1007       auto Inst = MA->getAccessInstruction();
1008       for (auto User : Inst->users()) {
1009         if (!isa<Instruction>(User))
1010           return false;
1011         auto UserInst = cast<Instruction>(User);
1012 
1013         if (!S->contains(UserInst)) {
1014           DEBUG(dbgs() << "    Reject because value is escaping\n");
1015           return false;
1016         }
1017       }
1018 
1019       return true;
1020     }
1021 
1022     if (SAI->isPHIKind()) {
1023       auto *MA = DefUse.getPHIRead(SAI);
1024       assert(MA);
1025 
1026       // Mapping of an incoming block from before the SCoP is not supported by
1027       // the code generator.
1028       auto PHI = cast<PHINode>(MA->getAccessInstruction());
1029       for (auto Incoming : PHI->blocks()) {
1030         if (!S->contains(Incoming)) {
1031           DEBUG(dbgs() << "    Reject because at least one incoming block is "
1032                           "not in the scop region\n");
1033           return false;
1034         }
1035       }
1036 
1037       return true;
1038     }
1039 
1040     DEBUG(dbgs() << "    Reject ExitPHI or other non-value\n");
1041     return false;
1042   }
1043 
1044   /// Compute the uses of a MemoryKind::Value and its lifetime (from its
1045   /// definition to the last use).
1046   ///
1047   /// @param SAI The ScopArrayInfo representing the value's storage.
1048   ///
1049   /// @return { DomainDef[] -> DomainUse[] }, { DomainDef[] -> Zone[] }
1050   ///         First element is the set of uses for each definition.
1051   ///         The second is the lifetime of each definition.
1052   std::tuple<IslPtr<isl_union_map>, IslPtr<isl_map>>
1053   computeValueUses(const ScopArrayInfo *SAI) {
1054     assert(SAI->isValueKind());
1055 
1056     // { DomainRead[] }
1057     auto Reads = makeEmptyUnionSet();
1058 
1059     // Find all uses.
1060     for (auto *MA : DefUse.getValueUses(SAI))
1061       Reads =
1062           give(isl_union_set_add_set(Reads.take(), getDomainFor(MA).take()));
1063 
1064     // { DomainRead[] -> Scatter[] }
1065     auto ReadSchedule = getScatterFor(Reads);
1066 
1067     auto *DefMA = DefUse.getValueDef(SAI);
1068     assert(DefMA);
1069 
1070     // { DomainDef[] }
1071     auto Writes = getDomainFor(DefMA);
1072 
1073     // { DomainDef[] -> Scatter[] }
1074     auto WriteScatter = getScatterFor(Writes);
1075 
1076     // { Scatter[] -> DomainDef[] }
1077     auto ReachDef = getScalarReachingDefinition(DefMA->getStatement());
1078 
1079     // { [DomainDef[] -> Scatter[]] -> DomainUse[] }
1080     auto Uses = give(
1081         isl_union_map_apply_range(isl_union_map_from_map(isl_map_range_map(
1082                                       isl_map_reverse(ReachDef.take()))),
1083                                   isl_union_map_reverse(ReadSchedule.take())));
1084 
1085     // { DomainDef[] -> Scatter[] }
1086     auto UseScatter =
1087         singleton(give(isl_union_set_unwrap(isl_union_map_domain(Uses.copy()))),
1088                   give(isl_space_map_from_domain_and_range(
1089                       isl_set_get_space(Writes.keep()), ScatterSpace.copy())));
1090 
1091     // { DomainDef[] -> Zone[] }
1092     auto Lifetime = betweenScatter(WriteScatter, UseScatter, false, true);
1093 
1094     // { DomainDef[] -> DomainRead[] }
1095     auto DefUses = give(isl_union_map_domain_factor_domain(Uses.take()));
1096 
1097     return std::make_pair(DefUses, Lifetime);
1098   }
1099 
1100   /// For each 'execution' of a PHINode, get the incoming block that was
1101   /// executed before.
1102   ///
1103   /// For each PHI instance we can directly determine which was the incoming
1104   /// block, and hence derive which value the PHI has.
1105   ///
1106   /// @param SAI The ScopArrayInfo representing the PHI's storage.
1107   ///
1108   /// @return { DomainPHIRead[] -> DomainPHIWrite[] }
1109   IslPtr<isl_union_map> computePerPHI(const ScopArrayInfo *SAI) {
1110     assert(SAI->isPHIKind());
1111 
1112     // { DomainPHIWrite[] -> Scatter[] }
1113     auto PHIWriteScatter = makeEmptyUnionMap();
1114 
1115     // Collect all incoming block timepoint.
1116     for (auto *MA : DefUse.getPHIIncomings(SAI)) {
1117       auto Scatter = getScatterFor(MA);
1118       PHIWriteScatter =
1119           give(isl_union_map_add_map(PHIWriteScatter.take(), Scatter.take()));
1120     }
1121 
1122     // { DomainPHIRead[] -> Scatter[] }
1123     auto PHIReadScatter = getScatterFor(DefUse.getPHIRead(SAI));
1124 
1125     // { DomainPHIRead[] -> Scatter[] }
1126     auto BeforeRead = beforeScatter(PHIReadScatter, true);
1127 
1128     // { Scatter[] }
1129     auto WriteTimes = singleton(
1130         give(isl_union_map_range(PHIWriteScatter.copy())), ScatterSpace);
1131 
1132     // { DomainPHIRead[] -> Scatter[] }
1133     auto PHIWriteTimes =
1134         give(isl_map_intersect_range(BeforeRead.take(), WriteTimes.take()));
1135     auto LastPerPHIWrites = give(isl_map_lexmax(PHIWriteTimes.take()));
1136 
1137     // { DomainPHIRead[] -> DomainPHIWrite[] }
1138     auto Result = give(isl_union_map_apply_range(
1139         isl_union_map_from_map(LastPerPHIWrites.take()),
1140         isl_union_map_reverse(PHIWriteScatter.take())));
1141     assert(isl_union_map_is_single_valued(Result.keep()) == isl_bool_true);
1142     assert(isl_union_map_is_injective(Result.keep()) == isl_bool_true);
1143     return Result;
1144   }
1145 
1146   /// Try to map a MemoryKind::Value to a given array element.
1147   ///
1148   /// @param SAI       Representation of the scalar's memory to map.
1149   /// @param TargetElt { Scatter[] -> Element[] }
1150   ///                  Suggestion where to map a scalar to when at a timepoint.
1151   ///
1152   /// @return true if the scalar was successfully mapped.
1153   bool tryMapValue(const ScopArrayInfo *SAI, IslPtr<isl_map> TargetElt) {
1154     assert(SAI->isValueKind());
1155 
1156     auto *DefMA = DefUse.getValueDef(SAI);
1157     assert(DefMA->isValueKind());
1158     assert(DefMA->isMustWrite());
1159 
1160     // Stop if the scalar has already been mapped.
1161     if (!DefMA->getLatestScopArrayInfo()->isValueKind())
1162       return false;
1163 
1164     // { DomainDef[] -> Scatter[] }
1165     auto DefSched = getScatterFor(DefMA);
1166 
1167     // Where each write is mapped to, according to the suggestion.
1168     // { DomainDef[] -> Element[] }
1169     auto DefTarget = give(isl_map_apply_domain(
1170         TargetElt.copy(), isl_map_reverse(DefSched.copy())));
1171     simplify(DefTarget);
1172     DEBUG(dbgs() << "    Def Mapping: " << DefTarget << '\n');
1173 
1174     auto OrigDomain = getDomainFor(DefMA);
1175     auto MappedDomain = give(isl_map_domain(DefTarget.copy()));
1176     if (!isl_set_is_subset(OrigDomain.keep(), MappedDomain.keep())) {
1177       DEBUG(dbgs()
1178             << "    Reject because mapping does not encompass all instances\n");
1179       return false;
1180     }
1181 
1182     // { DomainDef[] -> Zone[] }
1183     IslPtr<isl_map> Lifetime;
1184 
1185     // { DomainDef[] -> DomainUse[] }
1186     IslPtr<isl_union_map> DefUses;
1187 
1188     std::tie(DefUses, Lifetime) = computeValueUses(SAI);
1189     DEBUG(dbgs() << "    Lifetime: " << Lifetime << '\n');
1190 
1191     /// { [Element[] -> Zone[]] }
1192     auto EltZone = give(
1193         isl_map_wrap(isl_map_apply_domain(Lifetime.copy(), DefTarget.copy())));
1194     simplify(EltZone);
1195 
1196     // { [Element[] -> Scatter[]] }
1197     auto DefEltSched = give(isl_map_wrap(isl_map_reverse(
1198         isl_map_apply_domain(DefTarget.copy(), DefSched.copy()))));
1199     simplify(DefEltSched);
1200 
1201     Knowledge Proposed(EltZone, nullptr, DefEltSched);
1202     if (isConflicting(Proposed))
1203       return false;
1204 
1205     // { DomainUse[] -> Element[] }
1206     auto UseTarget = give(
1207         isl_union_map_apply_range(isl_union_map_reverse(DefUses.take()),
1208                                   isl_union_map_from_map(DefTarget.copy())));
1209 
1210     mapValue(SAI, std::move(DefTarget), std::move(UseTarget),
1211              std::move(Lifetime), std::move(Proposed));
1212     return true;
1213   }
1214 
1215   /// After a scalar has been mapped, update the global knowledge.
1216   void applyLifetime(Knowledge Proposed) {
1217     Zone.learnFrom(std::move(Proposed));
1218   }
1219 
1220   /// Map a MemoryKind::Value scalar to an array element.
1221   ///
1222   /// Callers must have ensured that the mapping is valid and not conflicting.
1223   ///
1224   /// @param SAI       The ScopArrayInfo representing the scalar's memory to
1225   ///                  map.
1226   /// @param DefTarget { DomainDef[] -> Element[] }
1227   ///                  The array element to map the scalar to.
1228   /// @param UseTarget { DomainUse[] -> Element[] }
1229   ///                  The array elements the uses are mapped to.
1230   /// @param Lifetime  { DomainDef[] -> Zone[] }
1231   ///                  The lifetime of each llvm::Value definition for
1232   ///                  reporting.
1233   /// @param Proposed  Mapping constraints for reporting.
1234   void mapValue(const ScopArrayInfo *SAI, IslPtr<isl_map> DefTarget,
1235                 IslPtr<isl_union_map> UseTarget, IslPtr<isl_map> Lifetime,
1236                 Knowledge Proposed) {
1237     // Redirect the read accesses.
1238     for (auto *MA : DefUse.getValueUses(SAI)) {
1239       // { DomainUse[] }
1240       auto Domain = getDomainFor(MA);
1241 
1242       // { DomainUse[] -> Element[] }
1243       auto NewAccRel = give(isl_union_map_intersect_domain(
1244           UseTarget.copy(), isl_union_set_from_set(Domain.take())));
1245       simplify(NewAccRel);
1246 
1247       assert(isl_union_map_n_map(NewAccRel.keep()) == 1);
1248       MA->setNewAccessRelation(isl_map_from_union_map(NewAccRel.take()));
1249     }
1250 
1251     auto *WA = DefUse.getValueDef(SAI);
1252     WA->setNewAccessRelation(DefTarget.copy());
1253     applyLifetime(Proposed);
1254 
1255     MappedValueScalars++;
1256     NumberOfMappedValueScalars += 1;
1257   }
1258 
1259   /// Try to map a MemoryKind::PHI scalar to a given array element.
1260   ///
1261   /// @param SAI       Representation of the scalar's memory to map.
1262   /// @param TargetElt { Scatter[] -> Element[] }
1263   ///                  Suggestion where to map the scalar to when at a
1264   ///                  timepoint.
1265   ///
1266   /// @return true if the PHI scalar has been mapped.
1267   bool tryMapPHI(const ScopArrayInfo *SAI, IslPtr<isl_map> TargetElt) {
1268     auto *PHIRead = DefUse.getPHIRead(SAI);
1269     assert(PHIRead->isPHIKind());
1270     assert(PHIRead->isRead());
1271 
1272     // Skip if already been mapped.
1273     if (!PHIRead->getLatestScopArrayInfo()->isPHIKind())
1274       return false;
1275 
1276     // { DomainRead[] -> Scatter[] }
1277     auto PHISched = getScatterFor(PHIRead);
1278 
1279     // { DomainRead[] -> Element[] }
1280     auto PHITarget =
1281         give(isl_map_apply_range(PHISched.copy(), TargetElt.copy()));
1282     simplify(PHITarget);
1283     DEBUG(dbgs() << "    Mapping: " << PHITarget << '\n');
1284 
1285     auto OrigDomain = getDomainFor(PHIRead);
1286     auto MappedDomain = give(isl_map_domain(PHITarget.copy()));
1287     if (!isl_set_is_subset(OrigDomain.keep(), MappedDomain.keep())) {
1288       DEBUG(dbgs()
1289             << "    Reject because mapping does not encompass all instances\n");
1290       return false;
1291     }
1292 
1293     // { DomainRead[] -> DomainWrite[] }
1294     auto PerPHIWrites = computePerPHI(SAI);
1295 
1296     // { DomainWrite[] -> Element[] }
1297     auto WritesTarget = give(isl_union_map_reverse(isl_union_map_apply_domain(
1298         PerPHIWrites.copy(), isl_union_map_from_map(PHITarget.copy()))));
1299     simplify(WritesTarget);
1300 
1301     // { DomainWrite[] }
1302     auto ExpandedWritesDom = give(isl_union_map_domain(WritesTarget.copy()));
1303     auto UniverseWritesDom = give(isl_union_set_empty(ParamSpace.copy()));
1304 
1305     for (auto *MA : DefUse.getPHIIncomings(SAI))
1306       UniverseWritesDom = give(isl_union_set_add_set(UniverseWritesDom.take(),
1307                                                      getDomainFor(MA).take()));
1308 
1309     if (!isl_union_set_is_subset(UniverseWritesDom.keep(),
1310                                  ExpandedWritesDom.keep())) {
1311       DEBUG(dbgs() << "    Reject because did not find PHI write mapping for "
1312                       "all instances\n");
1313       DEBUG(dbgs() << "      Deduced Mapping:     " << WritesTarget << '\n');
1314       DEBUG(dbgs() << "      Missing instances:    "
1315                    << give(isl_union_set_subtract(UniverseWritesDom.copy(),
1316                                                   ExpandedWritesDom.copy()))
1317                    << '\n');
1318       return false;
1319     }
1320 
1321     //  { DomainRead[] -> Scatter[] }
1322     auto PerPHIWriteScatter = give(isl_map_from_union_map(
1323         isl_union_map_apply_range(PerPHIWrites.copy(), Schedule.copy())));
1324 
1325     // { DomainRead[] -> Zone[] }
1326     auto Lifetime = betweenScatter(PerPHIWriteScatter, PHISched, false, true);
1327     simplify(Lifetime);
1328     DEBUG(dbgs() << "    Lifetime: " << Lifetime << "\n");
1329 
1330     // { DomainWrite[] -> Zone[] }
1331     auto WriteLifetime = give(isl_union_map_apply_domain(
1332         isl_union_map_from_map(Lifetime.copy()), PerPHIWrites.copy()));
1333 
1334     // { DomainWrite[] -> [Element[] -> Scatter[]] }
1335     auto WrittenTranslator =
1336         give(isl_union_map_range_product(WritesTarget.copy(), Schedule.copy()));
1337 
1338     // { [Element[] -> Scatter[]] }
1339     auto Written = give(isl_union_map_range(WrittenTranslator.copy()));
1340     simplify(Written);
1341 
1342     // { DomainWrite[] -> [Element[] -> Zone[]] }
1343     auto LifetimeTranslator = give(
1344         isl_union_map_range_product(WritesTarget.copy(), WriteLifetime.take()));
1345 
1346     // { [Element[] -> Zone[] }
1347     auto Occupied = give(isl_union_map_range(LifetimeTranslator.copy()));
1348     simplify(Occupied);
1349 
1350     Knowledge Proposed(Occupied, nullptr, Written);
1351     if (isConflicting(Proposed))
1352       return false;
1353 
1354     mapPHI(SAI, std::move(PHITarget), std::move(WritesTarget),
1355            std::move(Lifetime), std::move(Proposed));
1356     return true;
1357   }
1358 
1359   /// Map a MemoryKind::PHI scalar to an array element.
1360   ///
1361   /// Callers must have ensured that the mapping is valid and not conflicting
1362   /// with the common knowledge.
1363   ///
1364   /// @param SAI         The ScopArrayInfo representing the scalar's memory to
1365   ///                    map.
1366   /// @param ReadTarget  { DomainRead[] -> Element[] }
1367   ///                    The array element to map the scalar to.
1368   /// @param WriteTarget { DomainWrite[] -> Element[] }
1369   ///                    New access target for each PHI incoming write.
1370   /// @param Lifetime    { DomainRead[] -> Zone[] }
1371   ///                    The lifetime of each PHI for reporting.
1372   /// @param Proposed    Mapping constraints for reporting.
1373   void mapPHI(const ScopArrayInfo *SAI, IslPtr<isl_map> ReadTarget,
1374               IslPtr<isl_union_map> WriteTarget, IslPtr<isl_map> Lifetime,
1375               Knowledge Proposed) {
1376     // Redirect the PHI incoming writes.
1377     for (auto *MA : DefUse.getPHIIncomings(SAI)) {
1378       // { DomainWrite[] }
1379       auto Domain = getDomainFor(MA);
1380 
1381       // { DomainWrite[] -> Element[] }
1382       auto NewAccRel = give(isl_union_map_intersect_domain(
1383           WriteTarget.copy(), isl_union_set_from_set(Domain.take())));
1384       simplify(NewAccRel);
1385 
1386       assert(isl_union_map_n_map(NewAccRel.keep()) == 1);
1387       MA->setNewAccessRelation(isl_map_from_union_map(NewAccRel.take()));
1388     }
1389 
1390     // Redirect the PHI read.
1391     auto *PHIRead = DefUse.getPHIRead(SAI);
1392     PHIRead->setNewAccessRelation(ReadTarget.copy());
1393     applyLifetime(Proposed);
1394 
1395     MappedPHIScalars++;
1396     NumberOfMappedPHIScalars++;
1397   }
1398 
1399   /// Search and map scalars to memory overwritten by @p TargetStoreMA.
1400   ///
1401   /// Start trying to map scalars that are used in the same statement as the
1402   /// store. For every successful mapping, try to also map scalars of the
1403   /// statements where those are written. Repeat, until no more mapping
1404   /// opportunity is found.
1405   ///
1406   /// There is currently no preference in which order scalars are tried.
1407   /// Ideally, we would direct it towards a load instruction of the same array
1408   /// element.
1409   bool collapseScalarsToStore(MemoryAccess *TargetStoreMA) {
1410     assert(TargetStoreMA->isLatestArrayKind());
1411     assert(TargetStoreMA->isMustWrite());
1412 
1413     auto TargetStmt = TargetStoreMA->getStatement();
1414 
1415     // { DomTarget[] }
1416     auto TargetDom = getDomainFor(TargetStmt);
1417 
1418     // { DomTarget[] -> Element[] }
1419     auto TargetAccRel = getAccessRelationFor(TargetStoreMA);
1420 
1421     // { Zone[] -> DomTarget[] }
1422     // For each point in time, find the next target store instance.
1423     auto Target =
1424         computeScalarReachingOverwrite(Schedule, TargetDom, false, true);
1425 
1426     // { Zone[] -> Element[] }
1427     // Use the target store's write location as a suggestion to map scalars to.
1428     auto EltTarget =
1429         give(isl_map_apply_range(Target.take(), TargetAccRel.take()));
1430     simplify(EltTarget);
1431     DEBUG(dbgs() << "    Target mapping is " << EltTarget << '\n');
1432 
1433     // Stack of elements not yet processed.
1434     SmallVector<MemoryAccess *, 16> Worklist;
1435 
1436     // Set of scalars already tested.
1437     SmallPtrSet<const ScopArrayInfo *, 16> Closed;
1438 
1439     // Lambda to add all scalar reads to the work list.
1440     auto ProcessAllIncoming = [&](ScopStmt *Stmt) {
1441       for (auto *MA : *Stmt) {
1442         if (!MA->isLatestScalarKind())
1443           continue;
1444         if (!MA->isRead())
1445           continue;
1446 
1447         Worklist.push_back(MA);
1448       }
1449     };
1450 
1451     // Add initial scalar. Either the value written by the store, or all inputs
1452     // of its statement.
1453     auto WrittenVal = TargetStoreMA->getAccessValue();
1454     if (auto InputAcc = getInputAccessOf(WrittenVal, TargetStmt))
1455       Worklist.push_back(InputAcc);
1456     else
1457       ProcessAllIncoming(TargetStmt);
1458 
1459     auto AnyMapped = false;
1460     auto &DL =
1461         S->getRegion().getEntry()->getParent()->getParent()->getDataLayout();
1462     auto StoreSize =
1463         DL.getTypeAllocSize(TargetStoreMA->getAccessValue()->getType());
1464 
1465     while (!Worklist.empty()) {
1466       auto *MA = Worklist.pop_back_val();
1467 
1468       auto *SAI = MA->getScopArrayInfo();
1469       if (Closed.count(SAI))
1470         continue;
1471       Closed.insert(SAI);
1472       DEBUG(dbgs() << "\n    Trying to map " << MA << " (SAI: " << SAI
1473                    << ")\n");
1474 
1475       // Skip non-mappable scalars.
1476       if (!isMappable(SAI))
1477         continue;
1478 
1479       auto MASize = DL.getTypeAllocSize(MA->getAccessValue()->getType());
1480       if (MASize > StoreSize) {
1481         DEBUG(dbgs() << "    Reject because storage size is insufficient\n");
1482         continue;
1483       }
1484 
1485       // Try to map MemoryKind::Value scalars.
1486       if (SAI->isValueKind()) {
1487         if (!tryMapValue(SAI, EltTarget))
1488           continue;
1489 
1490         auto *DefAcc = DefUse.getValueDef(SAI);
1491         ProcessAllIncoming(DefAcc->getStatement());
1492 
1493         AnyMapped = true;
1494         continue;
1495       }
1496 
1497       // Try to map MemoryKind::PHI scalars.
1498       if (SAI->isPHIKind()) {
1499         if (!tryMapPHI(SAI, EltTarget))
1500           continue;
1501         // Add inputs of all incoming statements to the worklist.
1502         for (auto *PHIWrite : DefUse.getPHIIncomings(SAI))
1503           ProcessAllIncoming(PHIWrite->getStatement());
1504 
1505         AnyMapped = true;
1506         continue;
1507       }
1508     }
1509 
1510     if (AnyMapped) {
1511       TargetsMapped++;
1512       NumberOfTargetsMapped++;
1513     }
1514     return AnyMapped;
1515   }
1516 
1517   /// Compute when an array element is unused.
1518   ///
1519   /// @return { [Element[] -> Zone[]] }
1520   IslPtr<isl_union_set> computeLifetime() const {
1521     // { Element[] -> Zone[] }
1522     auto ArrayUnused = computeArrayUnused(Schedule, AllMustWrites, AllReads,
1523                                           false, false, true);
1524 
1525     auto Result = give(isl_union_map_wrap(ArrayUnused.copy()));
1526 
1527     simplify(Result);
1528     return Result;
1529   }
1530 
1531   /// Determine when an array element is written to.
1532   ///
1533   /// @return { [Element[] -> Scatter[]] }
1534   IslPtr<isl_union_set> computeWritten() const {
1535     // { WriteDomain[] -> Element[] }
1536     auto AllWrites =
1537         give(isl_union_map_union(AllMustWrites.copy(), AllMayWrites.copy()));
1538 
1539     // { Scatter[] -> Element[] }
1540     auto WriteTimepoints =
1541         give(isl_union_map_apply_domain(AllWrites.copy(), Schedule.copy()));
1542 
1543     auto Result =
1544         give(isl_union_map_wrap(isl_union_map_reverse(WriteTimepoints.copy())));
1545 
1546     simplify(Result);
1547     return Result;
1548   }
1549 
1550   /// Determine whether an access touches at most one element.
1551   ///
1552   /// The accessed element could be a scalar or accessing an array with constant
1553   /// subscript, such that all instances access only that element.
1554   ///
1555   /// @param MA The access to test.
1556   ///
1557   /// @return True, if zero or one elements are accessed; False if at least two
1558   ///         different elements are accessed.
1559   bool isScalarAccess(MemoryAccess *MA) {
1560     auto Map = getAccessRelationFor(MA);
1561     auto Set = give(isl_map_range(Map.take()));
1562     return isl_set_is_singleton(Set.keep()) == isl_bool_true;
1563   }
1564 
1565   /// Print mapping statistics to @p OS.
1566   void printStatistics(llvm::raw_ostream &OS, int Indent = 0) const {
1567     OS.indent(Indent) << "Statistics {\n";
1568     OS.indent(Indent + 4) << "Compatible overwrites: "
1569                           << NumberOfCompatibleTargets << "\n";
1570     OS.indent(Indent + 4) << "Overwrites mapped to:  " << NumberOfTargetsMapped
1571                           << '\n';
1572     OS.indent(Indent + 4) << "Value scalars mapped:  "
1573                           << NumberOfMappedValueScalars << '\n';
1574     OS.indent(Indent + 4) << "PHI scalars mapped:    "
1575                           << NumberOfMappedPHIScalars << '\n';
1576     OS.indent(Indent) << "}\n";
1577   }
1578 
1579   /// Return whether at least one transformation been applied.
1580   bool isModified() const { return NumberOfTargetsMapped > 0; }
1581 
1582 public:
1583   DeLICMImpl(Scop *S) : ZoneAlgorithm(S) {}
1584 
1585   /// Calculate the lifetime (definition to last use) of every array element.
1586   ///
1587   /// @return True if the computed lifetimes (#Zone) is usable.
1588   bool computeZone() {
1589     // Check that nothing strange occurs.
1590     if (!isCompatibleScop()) {
1591       DeLICMIncompatible++;
1592       return false;
1593     }
1594 
1595     DefUse.compute(S);
1596     IslPtr<isl_union_set> EltUnused, EltWritten;
1597 
1598     {
1599       IslMaxOperationsGuard MaxOpGuard(IslCtx.get(), DelicmMaxOps);
1600 
1601       computeCommon();
1602 
1603       EltUnused = computeLifetime();
1604       EltWritten = computeWritten();
1605     }
1606     DeLICMAnalyzed++;
1607 
1608     if (!EltUnused || !EltWritten) {
1609       assert(isl_ctx_last_error(IslCtx.get()) == isl_error_quota &&
1610              "The only reason that these things have not been computed should "
1611              "be if the max-operations limit hit");
1612       DeLICMOutOfQuota++;
1613       DEBUG(dbgs() << "DeLICM analysis exceeded max_operations\n");
1614       DebugLoc Begin, End;
1615       getDebugLocations(getBBPairForRegion(&S->getRegion()), Begin, End);
1616       OptimizationRemarkAnalysis R(DEBUG_TYPE, "OutOfQuota", Begin,
1617                                    S->getEntry());
1618       R << "maximal number of operations exceeded during zone analysis";
1619       S->getFunction().getContext().diagnose(R);
1620       return false;
1621     }
1622 
1623     Zone = OriginalZone = Knowledge(nullptr, EltUnused, EltWritten);
1624     DEBUG(dbgs() << "Computed Zone:\n"; OriginalZone.print(dbgs(), 4));
1625 
1626     assert(Zone.isUsable() && OriginalZone.isUsable());
1627     return true;
1628   }
1629 
1630   /// Try to map as many scalars to unused array elements as possible.
1631   ///
1632   /// Multiple scalars might be mappable to intersecting unused array element
1633   /// zones, but we can only chose one. This is a greedy algorithm, therefore
1634   /// the first processed element claims it.
1635   void greedyCollapse() {
1636     bool Modified = false;
1637 
1638     for (auto &Stmt : *S) {
1639       for (auto *MA : Stmt) {
1640         if (!MA->isLatestArrayKind())
1641           continue;
1642         if (!MA->isWrite())
1643           continue;
1644 
1645         if (MA->isMayWrite()) {
1646           DEBUG(dbgs() << "Access " << MA
1647                        << " pruned because it is a MAY_WRITE\n");
1648           OptimizationRemarkMissed R(DEBUG_TYPE, "TargetMayWrite",
1649                                      MA->getAccessInstruction());
1650           R << "Skipped possible mapping target because it is not an "
1651                "unconditional overwrite";
1652           S->getFunction().getContext().diagnose(R);
1653           continue;
1654         }
1655 
1656         if (Stmt.getNumIterators() == 0) {
1657           DEBUG(dbgs() << "Access " << MA
1658                        << " pruned because it is not in a loop\n");
1659           OptimizationRemarkMissed R(DEBUG_TYPE, "WriteNotInLoop",
1660                                      MA->getAccessInstruction());
1661           R << "skipped possible mapping target because it is not in a loop";
1662           S->getFunction().getContext().diagnose(R);
1663           continue;
1664         }
1665 
1666         if (isScalarAccess(MA)) {
1667           DEBUG(dbgs() << "Access " << MA
1668                        << " pruned because it writes only a single element\n");
1669           OptimizationRemarkMissed R(DEBUG_TYPE, "ScalarWrite",
1670                                      MA->getAccessInstruction());
1671           R << "skipped possible mapping target because the memory location "
1672                "written to does not depend on its outer loop";
1673           S->getFunction().getContext().diagnose(R);
1674           continue;
1675         }
1676 
1677         NumberOfCompatibleTargets++;
1678         DEBUG(dbgs() << "Analyzing target access " << MA << "\n");
1679         if (collapseScalarsToStore(MA))
1680           Modified = true;
1681       }
1682     }
1683 
1684     if (Modified)
1685       DeLICMScopsModified++;
1686   }
1687 
1688   /// Dump the internal information about a performed DeLICM to @p OS.
1689   void print(llvm::raw_ostream &OS, int Indent = 0) {
1690     if (!Zone.isUsable()) {
1691       OS.indent(Indent) << "Zone not computed\n";
1692       return;
1693     }
1694 
1695     printStatistics(OS, Indent);
1696     if (!isModified()) {
1697       OS.indent(Indent) << "No modification has been made\n";
1698       return;
1699     }
1700     printAccesses(OS, Indent);
1701   }
1702 };
1703 
1704 class DeLICM : public ScopPass {
1705 private:
1706   DeLICM(const DeLICM &) = delete;
1707   const DeLICM &operator=(const DeLICM &) = delete;
1708 
1709   /// The pass implementation, also holding per-scop data.
1710   std::unique_ptr<DeLICMImpl> Impl;
1711 
1712   void collapseToUnused(Scop &S) {
1713     Impl = make_unique<DeLICMImpl>(&S);
1714 
1715     if (!Impl->computeZone()) {
1716       DEBUG(dbgs() << "Abort because cannot reliably compute lifetimes\n");
1717       return;
1718     }
1719 
1720     DEBUG(dbgs() << "Collapsing scalars to unused array elements...\n");
1721     Impl->greedyCollapse();
1722 
1723     DEBUG(dbgs() << "\nFinal Scop:\n");
1724     DEBUG(S.print(dbgs()));
1725   }
1726 
1727 public:
1728   static char ID;
1729   explicit DeLICM() : ScopPass(ID) {}
1730 
1731   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
1732     AU.addRequiredTransitive<ScopInfoRegionPass>();
1733     AU.setPreservesAll();
1734   }
1735 
1736   virtual bool runOnScop(Scop &S) override {
1737     // Free resources for previous scop's computation, if not yet done.
1738     releaseMemory();
1739 
1740     collapseToUnused(S);
1741 
1742     return false;
1743   }
1744 
1745   virtual void printScop(raw_ostream &OS, Scop &S) const override {
1746     if (!Impl)
1747       return;
1748     assert(Impl->getScop() == &S);
1749 
1750     OS << "DeLICM result:\n";
1751     Impl->print(OS);
1752   }
1753 
1754   virtual void releaseMemory() override { Impl.reset(); }
1755 };
1756 
1757 char DeLICM::ID;
1758 } // anonymous namespace
1759 
1760 Pass *polly::createDeLICMPass() { return new DeLICM(); }
1761 
1762 INITIALIZE_PASS_BEGIN(DeLICM, "polly-delicm", "Polly - DeLICM/DePRE", false,
1763                       false)
1764 INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass)
1765 INITIALIZE_PASS_END(DeLICM, "polly-delicm", "Polly - DeLICM/DePRE", false,
1766                     false)
1767 
1768 bool polly::isConflicting(IslPtr<isl_union_set> ExistingOccupied,
1769                           IslPtr<isl_union_set> ExistingUnused,
1770                           IslPtr<isl_union_set> ExistingWrites,
1771                           IslPtr<isl_union_set> ProposedOccupied,
1772                           IslPtr<isl_union_set> ProposedUnused,
1773                           IslPtr<isl_union_set> ProposedWrites,
1774                           llvm::raw_ostream *OS, unsigned Indent) {
1775   Knowledge Existing(std::move(ExistingOccupied), std::move(ExistingUnused),
1776                      std::move(ExistingWrites));
1777   Knowledge Proposed(std::move(ProposedOccupied), std::move(ProposedUnused),
1778                      std::move(ProposedWrites));
1779 
1780   return Knowledge::isConflicting(Existing, Proposed, OS, Indent);
1781 }
1782