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