• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===------ Simplify.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Simplify a SCoP by removing unnecessary statements and accesses.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "polly/Simplify.h"
14 #include "polly/ScopInfo.h"
15 #include "polly/ScopPass.h"
16 #include "polly/Support/GICHelper.h"
17 #include "polly/Support/ISLOStream.h"
18 #include "polly/Support/ISLTools.h"
19 #include "polly/Support/VirtualInstruction.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/Support/Debug.h"
23 #define DEBUG_TYPE "polly-simplify"
24 
25 using namespace llvm;
26 using namespace polly;
27 
28 namespace {
29 
30 #define TWO_STATISTICS(VARNAME, DESC)                                          \
31   static llvm::Statistic VARNAME[2] = {                                        \
32       {DEBUG_TYPE, #VARNAME "0", DESC " (first)"},                             \
33       {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}}
34 
35 /// Number of max disjuncts we allow in removeOverwrites(). This is to avoid
36 /// that the analysis of accesses in a statement is becoming too complex. Chosen
37 /// to be relatively small because all the common cases should access only few
38 /// array elements per statement.
39 static int const SimplifyMaxDisjuncts = 4;
40 
41 TWO_STATISTICS(ScopsProcessed, "Number of SCoPs processed");
42 TWO_STATISTICS(ScopsModified, "Number of SCoPs simplified");
43 
44 TWO_STATISTICS(TotalEmptyDomainsRemoved,
45                "Number of statement with empty domains removed in any SCoP");
46 TWO_STATISTICS(TotalOverwritesRemoved, "Number of removed overwritten writes");
47 TWO_STATISTICS(TotalWritesCoalesced, "Number of writes coalesced with another");
48 TWO_STATISTICS(TotalRedundantWritesRemoved,
49                "Number of writes of same value removed in any SCoP");
50 TWO_STATISTICS(TotalEmptyPartialAccessesRemoved,
51                "Number of empty partial accesses removed");
52 TWO_STATISTICS(TotalDeadAccessesRemoved, "Number of dead accesses removed");
53 TWO_STATISTICS(TotalDeadInstructionsRemoved,
54                "Number of unused instructions removed");
55 TWO_STATISTICS(TotalStmtsRemoved, "Number of statements removed in any SCoP");
56 
57 TWO_STATISTICS(NumValueWrites, "Number of scalar value writes after Simplify");
58 TWO_STATISTICS(
59     NumValueWritesInLoops,
60     "Number of scalar value writes nested in affine loops after Simplify");
61 TWO_STATISTICS(NumPHIWrites,
62                "Number of scalar phi writes after the first simplification");
63 TWO_STATISTICS(
64     NumPHIWritesInLoops,
65     "Number of scalar phi writes nested in affine loops after Simplify");
66 TWO_STATISTICS(NumSingletonWrites, "Number of singleton writes after Simplify");
67 TWO_STATISTICS(
68     NumSingletonWritesInLoops,
69     "Number of singleton writes nested in affine loops after Simplify");
70 
isImplicitRead(MemoryAccess * MA)71 static bool isImplicitRead(MemoryAccess *MA) {
72   return MA->isRead() && MA->isOriginalScalarKind();
73 }
74 
isExplicitAccess(MemoryAccess * MA)75 static bool isExplicitAccess(MemoryAccess *MA) {
76   return MA->isOriginalArrayKind();
77 }
78 
isImplicitWrite(MemoryAccess * MA)79 static bool isImplicitWrite(MemoryAccess *MA) {
80   return MA->isWrite() && MA->isOriginalScalarKind();
81 }
82 
83 /// Like isl::union_map::add_map, but may also return an underapproximated
84 /// result if getting too complex.
85 ///
86 /// This is implemented by adding disjuncts to the results until the limit is
87 /// reached.
underapproximatedAddMap(isl::union_map UMap,isl::map Map)88 static isl::union_map underapproximatedAddMap(isl::union_map UMap,
89                                               isl::map Map) {
90   if (UMap.is_null() || Map.is_null())
91     return {};
92 
93   isl::map PrevMap = UMap.extract_map(Map.get_space());
94 
95   // Fast path: If known that we cannot exceed the disjunct limit, just add
96   // them.
97   if (isl_map_n_basic_map(PrevMap.get()) + isl_map_n_basic_map(Map.get()) <=
98       SimplifyMaxDisjuncts)
99     return UMap.add_map(Map);
100 
101   isl::map Result = isl::map::empty(PrevMap.get_space());
102   for (isl::basic_map BMap : PrevMap.get_basic_map_list()) {
103     if (Result.n_basic_map() > SimplifyMaxDisjuncts)
104       break;
105     Result = Result.unite(BMap);
106   }
107   for (isl::basic_map BMap : Map.get_basic_map_list()) {
108     if (isl_map_n_basic_map(Result.get()) > SimplifyMaxDisjuncts)
109       break;
110     Result = Result.unite(BMap);
111   }
112 
113   isl::union_map UResult =
114       UMap.subtract(isl::map::universe(PrevMap.get_space()));
115   UResult.add_map(Result);
116 
117   return UResult;
118 }
119 } // namespace
120 
121 /// Return whether at least one simplification has been applied.
isModified() const122 bool SimplifyVisitor::isModified() const {
123   return EmptyDomainsRemoved > 0 || OverwritesRemoved > 0 ||
124          WritesCoalesced > 0 || RedundantWritesRemoved > 0 ||
125          EmptyPartialAccessesRemoved > 0 || DeadAccessesRemoved > 0 ||
126          DeadInstructionsRemoved > 0 || StmtsRemoved > 0;
127 }
128 
129 /// Remove statements that are never executed due to their domains being
130 /// empty.
131 ///
132 /// In contrast to Scop::simplifySCoP, this removes based on the SCoP's
133 /// effective domain, i.e. including the SCoP's context as used by some other
134 /// simplification methods in this pass. This is necessary because the
135 /// analysis on empty domains is unreliable, e.g. remove a scalar value
136 /// definition MemoryAccesses, but not its use.
removeEmptyDomainStmts()137 void SimplifyVisitor::removeEmptyDomainStmts() {
138   size_t NumStmtsBefore = S->getSize();
139 
140   S->removeStmts([](ScopStmt &Stmt) -> bool {
141     auto EffectiveDomain =
142         Stmt.getDomain().intersect_params(Stmt.getParent()->getContext());
143     return EffectiveDomain.is_empty();
144   });
145 
146   assert(NumStmtsBefore >= S->getSize());
147   EmptyDomainsRemoved = NumStmtsBefore - S->getSize();
148   LLVM_DEBUG(dbgs() << "Removed " << EmptyDomainsRemoved << " (of "
149                     << NumStmtsBefore << ") statements with empty domains \n");
150   TotalEmptyDomainsRemoved[CallNo] += EmptyDomainsRemoved;
151 }
152 
153 /// Remove writes that are overwritten unconditionally later in the same
154 /// statement.
155 ///
156 /// There must be no read of the same value between the write (that is to be
157 /// removed) and the overwrite.
removeOverwrites()158 void SimplifyVisitor::removeOverwrites() {
159   for (auto &Stmt : *S) {
160     isl::set Domain = Stmt.getDomain();
161     isl::union_map WillBeOverwritten =
162         isl::union_map::empty(S->getParamSpace());
163 
164     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
165 
166     // Iterate in reverse order, so the overwrite comes before the write that
167     // is to be removed.
168     for (auto *MA : reverse(Accesses)) {
169 
170       // In region statements, the explicit accesses can be in blocks that are
171       // can be executed in any order. We therefore process only the implicit
172       // writes and stop after that.
173       if (Stmt.isRegionStmt() && isExplicitAccess(MA))
174         break;
175 
176       auto AccRel = MA->getAccessRelation();
177       AccRel = AccRel.intersect_domain(Domain);
178       AccRel = AccRel.intersect_params(S->getContext());
179 
180       // If a value is read in-between, do not consider it as overwritten.
181       if (MA->isRead()) {
182         // Invalidate all overwrites for the array it accesses to avoid too
183         // complex isl sets.
184         isl::map AccRelUniv = isl::map::universe(AccRel.get_space());
185         WillBeOverwritten = WillBeOverwritten.subtract(AccRelUniv);
186         continue;
187       }
188 
189       // If all of a write's elements are overwritten, remove it.
190       isl::union_map AccRelUnion = AccRel;
191       if (AccRelUnion.is_subset(WillBeOverwritten)) {
192         LLVM_DEBUG(dbgs() << "Removing " << MA
193                           << " which will be overwritten anyway\n");
194 
195         Stmt.removeSingleMemoryAccess(MA);
196         OverwritesRemoved++;
197         TotalOverwritesRemoved[CallNo]++;
198       }
199 
200       // Unconditional writes overwrite other values.
201       if (MA->isMustWrite()) {
202         // Avoid too complex isl sets. If necessary, throw away some of the
203         // knowledge.
204         WillBeOverwritten = underapproximatedAddMap(WillBeOverwritten, AccRel);
205       }
206     }
207   }
208 }
209 
210 /// Combine writes that write the same value if possible.
211 ///
212 /// This function is able to combine:
213 /// - Partial writes with disjoint domain.
214 /// - Writes that write to the same array element.
215 ///
216 /// In all cases, both writes must write the same values.
coalesceWrites()217 void SimplifyVisitor::coalesceWrites() {
218   for (auto &Stmt : *S) {
219     isl::set Domain = Stmt.getDomain().intersect_params(S->getContext());
220 
221     // We let isl do the lookup for the same-value condition. For this, we
222     // wrap llvm::Value into an isl::set such that isl can do the lookup in
223     // its hashtable implementation. llvm::Values are only compared within a
224     // ScopStmt, so the map can be local to this scope. TODO: Refactor with
225     // ZoneAlgorithm::makeValueSet()
226     SmallDenseMap<Value *, isl::set> ValueSets;
227     auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
228       assert(V);
229       isl::set &Result = ValueSets[V];
230       if (Result.is_null()) {
231         isl::ctx Ctx = S->getIslCtx();
232         std::string Name = getIslCompatibleName(
233             "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames);
234         isl::id Id = isl::id::alloc(Ctx, Name, V);
235         Result = isl::set::universe(
236             isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
237       }
238       return Result;
239     };
240 
241     // List of all eligible (for coalescing) writes of the future.
242     // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
243     isl::union_map FutureWrites = isl::union_map::empty(S->getParamSpace());
244 
245     // Iterate over accesses from the last to the first.
246     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
247     for (MemoryAccess *MA : reverse(Accesses)) {
248       // In region statements, the explicit accesses can be in blocks that can
249       // be executed in any order. We therefore process only the implicit
250       // writes and stop after that.
251       if (Stmt.isRegionStmt() && isExplicitAccess(MA))
252         break;
253 
254       // { Domain[] -> Element[] }
255       isl::map AccRel = MA->getLatestAccessRelation().intersect_domain(Domain);
256 
257       // { [Domain[] -> Element[]] }
258       isl::set AccRelWrapped = AccRel.wrap();
259 
260       // { Value[] }
261       isl::set ValSet;
262 
263       if (MA->isMustWrite() && (MA->isOriginalScalarKind() ||
264                                 isa<StoreInst>(MA->getAccessInstruction()))) {
265         // Normally, tryGetValueStored() should be used to determine which
266         // element is written, but it can return nullptr; For PHI accesses,
267         // getAccessValue() returns the PHI instead of the PHI's incoming
268         // value. In this case, where we only compare values of a single
269         // statement, this is fine, because within a statement, a PHI in a
270         // successor block has always the same value as the incoming write. We
271         // still preferably use the incoming value directly so we also catch
272         // direct uses of that.
273         Value *StoredVal = MA->tryGetValueStored();
274         if (!StoredVal)
275           StoredVal = MA->getAccessValue();
276         ValSet = makeValueSet(StoredVal);
277 
278         // { Domain[] }
279         isl::set AccDomain = AccRel.domain();
280 
281         // Parts of the statement's domain that is not written by this access.
282         isl::set UndefDomain = Domain.subtract(AccDomain);
283 
284         // { Element[] }
285         isl::set ElementUniverse =
286             isl::set::universe(AccRel.get_space().range());
287 
288         // { Domain[] -> Element[] }
289         isl::map UndefAnything =
290             isl::map::from_domain_and_range(UndefDomain, ElementUniverse);
291 
292         // We are looking a compatible write access. The other write can
293         // access these elements...
294         isl::map AllowedAccesses = AccRel.unite(UndefAnything);
295 
296         // ... and must write the same value.
297         // { [Domain[] -> Element[]] -> Value[] }
298         isl::map Filter =
299             isl::map::from_domain_and_range(AllowedAccesses.wrap(), ValSet);
300 
301         // Lookup future write that fulfills these conditions.
302         // { [[Domain[] -> Element[]] -> Value[]] -> MemoryAccess[] }
303         isl::union_map Filtered =
304             FutureWrites.uncurry().intersect_domain(Filter.wrap());
305 
306         // Iterate through the candidates.
307         for (isl::map Map : Filtered.get_map_list()) {
308           MemoryAccess *OtherMA = (MemoryAccess *)Map.get_space()
309                                       .get_tuple_id(isl::dim::out)
310                                       .get_user();
311 
312           isl::map OtherAccRel =
313               OtherMA->getLatestAccessRelation().intersect_domain(Domain);
314 
315           // The filter only guaranteed that some of OtherMA's accessed
316           // elements are allowed. Verify that it only accesses allowed
317           // elements. Otherwise, continue with the next candidate.
318           if (!OtherAccRel.is_subset(AllowedAccesses).is_true())
319             continue;
320 
321           // The combined access relation.
322           // { Domain[] -> Element[] }
323           isl::map NewAccRel = AccRel.unite(OtherAccRel);
324           simplify(NewAccRel);
325 
326           // Carry out the coalescing.
327           Stmt.removeSingleMemoryAccess(MA);
328           OtherMA->setNewAccessRelation(NewAccRel);
329 
330           // We removed MA, OtherMA takes its role.
331           MA = OtherMA;
332 
333           TotalWritesCoalesced[CallNo]++;
334           WritesCoalesced++;
335 
336           // Don't look for more candidates.
337           break;
338         }
339       }
340 
341       // Two writes cannot be coalesced if there is another access (to some of
342       // the written elements) between them. Remove all visited write accesses
343       // from the list of eligible writes. Don't just remove the accessed
344       // elements, but any MemoryAccess that touches any of the invalidated
345       // elements.
346       SmallPtrSet<MemoryAccess *, 2> TouchedAccesses;
347       for (isl::map Map :
348            FutureWrites.intersect_domain(AccRelWrapped).get_map_list()) {
349         MemoryAccess *MA = (MemoryAccess *)Map.get_space()
350                                .range()
351                                .unwrap()
352                                .get_tuple_id(isl::dim::out)
353                                .get_user();
354         TouchedAccesses.insert(MA);
355       }
356       isl::union_map NewFutureWrites =
357           isl::union_map::empty(FutureWrites.get_space());
358       for (isl::map FutureWrite : FutureWrites.get_map_list()) {
359         MemoryAccess *MA = (MemoryAccess *)FutureWrite.get_space()
360                                .range()
361                                .unwrap()
362                                .get_tuple_id(isl::dim::out)
363                                .get_user();
364         if (!TouchedAccesses.count(MA))
365           NewFutureWrites = NewFutureWrites.add_map(FutureWrite);
366       }
367       FutureWrites = NewFutureWrites;
368 
369       if (MA->isMustWrite() && !ValSet.is_null()) {
370         // { MemoryAccess[] }
371         auto AccSet =
372             isl::set::universe(isl::space(S->getIslCtx(), 0, 0)
373                                    .set_tuple_id(isl::dim::set, MA->getId()));
374 
375         // { Val[] -> MemoryAccess[] }
376         isl::map ValAccSet = isl::map::from_domain_and_range(ValSet, AccSet);
377 
378         // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
379         isl::map AccRelValAcc =
380             isl::map::from_domain_and_range(AccRelWrapped, ValAccSet.wrap());
381         FutureWrites = FutureWrites.add_map(AccRelValAcc);
382       }
383     }
384   }
385 }
386 
387 /// Remove writes that just write the same value already stored in the
388 /// element.
removeRedundantWrites()389 void SimplifyVisitor::removeRedundantWrites() {
390   for (auto &Stmt : *S) {
391     SmallDenseMap<Value *, isl::set> ValueSets;
392     auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
393       assert(V);
394       isl::set &Result = ValueSets[V];
395       if (Result.is_null()) {
396         isl_ctx *Ctx = S->getIslCtx().get();
397         std::string Name = getIslCompatibleName(
398             "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames);
399         isl::id Id = isl::manage(isl_id_alloc(Ctx, Name.c_str(), V));
400         Result = isl::set::universe(
401             isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
402       }
403       return Result;
404     };
405 
406     isl::set Domain = Stmt.getDomain();
407     Domain = Domain.intersect_params(S->getContext());
408 
409     // List of element reads that still have the same value while iterating
410     // through the MemoryAccesses.
411     // { [Domain[] -> Element[]] -> Val[] }
412     isl::union_map Known = isl::union_map::empty(S->getParamSpace());
413 
414     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
415     for (MemoryAccess *MA : Accesses) {
416       // Is the memory access in a defined order relative to the other
417       // accesses? In region statements, only the first and the last accesses
418       // have defined order. Execution of those in the middle may depend on
419       // runtime conditions an therefore cannot be modified.
420       bool IsOrdered =
421           Stmt.isBlockStmt() || MA->isOriginalScalarKind() ||
422           (!S->getBoxedLoops().size() && MA->getAccessInstruction() &&
423            Stmt.getEntryBlock() == MA->getAccessInstruction()->getParent());
424 
425       isl::map AccRel = MA->getAccessRelation();
426       AccRel = AccRel.intersect_domain(Domain);
427       isl::set AccRelWrapped = AccRel.wrap();
428 
429       // Determine whether a write is redundant (stores only values that are
430       // already present in the written array elements) and remove it if this
431       // is the case.
432       if (IsOrdered && MA->isMustWrite() &&
433           (isa<StoreInst>(MA->getAccessInstruction()) ||
434            MA->isOriginalScalarKind())) {
435         Value *StoredVal = MA->tryGetValueStored();
436         if (!StoredVal)
437           StoredVal = MA->getAccessValue();
438 
439         if (StoredVal) {
440           // Lookup in the set of known values.
441           isl::map AccRelStoredVal = isl::map::from_domain_and_range(
442               AccRelWrapped, makeValueSet(StoredVal));
443           if (isl::union_map(AccRelStoredVal).is_subset(Known)) {
444             LLVM_DEBUG(dbgs() << "Cleanup of " << MA << ":\n");
445             LLVM_DEBUG(dbgs() << "      Scalar: " << *StoredVal << "\n");
446             LLVM_DEBUG(dbgs() << "      AccRel: " << AccRel << "\n");
447 
448             Stmt.removeSingleMemoryAccess(MA);
449 
450             RedundantWritesRemoved++;
451             TotalRedundantWritesRemoved[CallNo]++;
452           }
453         }
454       }
455 
456       // Update the know values set.
457       if (MA->isRead()) {
458         // Loaded values are the currently known values of the array element
459         // it was loaded from.
460         Value *LoadedVal = MA->getAccessValue();
461         if (LoadedVal && IsOrdered) {
462           isl::map AccRelVal = isl::map::from_domain_and_range(
463               AccRelWrapped, makeValueSet(LoadedVal));
464 
465           Known = Known.add_map(AccRelVal);
466         }
467       } else if (MA->isWrite()) {
468         // Remove (possibly) overwritten values from the known elements set.
469         // We remove all elements of the accessed array to avoid too complex
470         // isl sets.
471         isl::set AccRelUniv = isl::set::universe(AccRelWrapped.get_space());
472         Known = Known.subtract_domain(AccRelUniv);
473 
474         // At this point, we could add the written value of must-writes.
475         // However, writing same values is already handled by
476         // coalesceWrites().
477       }
478     }
479   }
480 }
481 
482 /// Remove statements without side effects.
removeUnnecessaryStmts()483 void SimplifyVisitor::removeUnnecessaryStmts() {
484   auto NumStmtsBefore = S->getSize();
485   S->simplifySCoP(true);
486   assert(NumStmtsBefore >= S->getSize());
487   StmtsRemoved = NumStmtsBefore - S->getSize();
488   LLVM_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore
489                     << ") statements\n");
490   TotalStmtsRemoved[CallNo] += StmtsRemoved;
491 }
492 
493 /// Remove accesses that have an empty domain.
removeEmptyPartialAccesses()494 void SimplifyVisitor::removeEmptyPartialAccesses() {
495   for (ScopStmt &Stmt : *S) {
496     // Defer the actual removal to not invalidate iterators.
497     SmallVector<MemoryAccess *, 8> DeferredRemove;
498 
499     for (MemoryAccess *MA : Stmt) {
500       if (!MA->isWrite())
501         continue;
502 
503       isl::map AccRel = MA->getAccessRelation();
504       if (!AccRel.is_empty().is_true())
505         continue;
506 
507       LLVM_DEBUG(
508           dbgs() << "Removing " << MA
509                  << " because it's a partial access that never occurs\n");
510       DeferredRemove.push_back(MA);
511     }
512 
513     for (MemoryAccess *MA : DeferredRemove) {
514       Stmt.removeSingleMemoryAccess(MA);
515       EmptyPartialAccessesRemoved++;
516       TotalEmptyPartialAccessesRemoved[CallNo]++;
517     }
518   }
519 }
520 
521 /// Mark all reachable instructions and access, and sweep those that are not
522 /// reachable.
markAndSweep(LoopInfo * LI)523 void SimplifyVisitor::markAndSweep(LoopInfo *LI) {
524   DenseSet<MemoryAccess *> UsedMA;
525   DenseSet<VirtualInstruction> UsedInsts;
526 
527   // Get all reachable instructions and accesses.
528   markReachable(S, LI, UsedInsts, UsedMA);
529 
530   // Remove all non-reachable accesses.
531   // We need get all MemoryAccesses first, in order to not invalidate the
532   // iterators when removing them.
533   SmallVector<MemoryAccess *, 64> AllMAs;
534   for (ScopStmt &Stmt : *S)
535     AllMAs.append(Stmt.begin(), Stmt.end());
536 
537   for (MemoryAccess *MA : AllMAs) {
538     if (UsedMA.count(MA))
539       continue;
540     LLVM_DEBUG(dbgs() << "Removing " << MA
541                       << " because its value is not used\n");
542     ScopStmt *Stmt = MA->getStatement();
543     Stmt->removeSingleMemoryAccess(MA);
544 
545     DeadAccessesRemoved++;
546     TotalDeadAccessesRemoved[CallNo]++;
547   }
548 
549   // Remove all non-reachable instructions.
550   for (ScopStmt &Stmt : *S) {
551     // Note that for region statements, we can only remove the non-terminator
552     // instructions of the entry block. All other instructions are not in the
553     // instructions list, but implicitly always part of the statement.
554 
555     SmallVector<Instruction *, 32> AllInsts(Stmt.insts_begin(),
556                                             Stmt.insts_end());
557     SmallVector<Instruction *, 32> RemainInsts;
558 
559     for (Instruction *Inst : AllInsts) {
560       auto It = UsedInsts.find({&Stmt, Inst});
561       if (It == UsedInsts.end()) {
562         LLVM_DEBUG(dbgs() << "Removing "; Inst->print(dbgs());
563                    dbgs() << " because it is not used\n");
564         DeadInstructionsRemoved++;
565         TotalDeadInstructionsRemoved[CallNo]++;
566         continue;
567       }
568 
569       RemainInsts.push_back(Inst);
570 
571       // If instructions appear multiple times, keep only the first.
572       UsedInsts.erase(It);
573     }
574 
575     // Set the new instruction list to be only those we did not remove.
576     Stmt.setInstructions(RemainInsts);
577   }
578 }
579 
580 /// Print simplification statistics to @p OS.
printStatistics(llvm::raw_ostream & OS,int Indent) const581 void SimplifyVisitor::printStatistics(llvm::raw_ostream &OS, int Indent) const {
582   OS.indent(Indent) << "Statistics {\n";
583   OS.indent(Indent + 4) << "Empty domains removed: " << EmptyDomainsRemoved
584                         << '\n';
585   OS.indent(Indent + 4) << "Overwrites removed: " << OverwritesRemoved << '\n';
586   OS.indent(Indent + 4) << "Partial writes coalesced: " << WritesCoalesced
587                         << "\n";
588   OS.indent(Indent + 4) << "Redundant writes removed: "
589                         << RedundantWritesRemoved << "\n";
590   OS.indent(Indent + 4) << "Accesses with empty domains removed: "
591                         << EmptyPartialAccessesRemoved << "\n";
592   OS.indent(Indent + 4) << "Dead accesses removed: " << DeadAccessesRemoved
593                         << '\n';
594   OS.indent(Indent + 4) << "Dead instructions removed: "
595                         << DeadInstructionsRemoved << '\n';
596   OS.indent(Indent + 4) << "Stmts removed: " << StmtsRemoved << "\n";
597   OS.indent(Indent) << "}\n";
598 }
599 
600 /// Print the current state of all MemoryAccesses to @p OS.
printAccesses(llvm::raw_ostream & OS,int Indent) const601 void SimplifyVisitor::printAccesses(llvm::raw_ostream &OS, int Indent) const {
602   OS.indent(Indent) << "After accesses {\n";
603   for (auto &Stmt : *S) {
604     OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
605     for (auto *MA : Stmt)
606       MA->print(OS);
607   }
608   OS.indent(Indent) << "}\n";
609 }
610 
visit(Scop & S,LoopInfo * LI)611 bool SimplifyVisitor::visit(Scop &S, LoopInfo *LI) {
612   // Reset statistics of last processed SCoP.
613   releaseMemory();
614   assert(!isModified());
615 
616   // Prepare processing of this SCoP.
617   this->S = &S;
618   ScopsProcessed[CallNo]++;
619 
620   LLVM_DEBUG(dbgs() << "Removing statements that are never executed...\n");
621   removeEmptyDomainStmts();
622 
623   LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n");
624   removeEmptyPartialAccesses();
625 
626   LLVM_DEBUG(dbgs() << "Removing overwrites...\n");
627   removeOverwrites();
628 
629   LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n");
630   coalesceWrites();
631 
632   LLVM_DEBUG(dbgs() << "Removing redundant writes...\n");
633   removeRedundantWrites();
634 
635   LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n");
636   markAndSweep(LI);
637 
638   LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n");
639   removeUnnecessaryStmts();
640 
641   if (isModified())
642     ScopsModified[CallNo]++;
643   LLVM_DEBUG(dbgs() << "\nFinal Scop:\n");
644   LLVM_DEBUG(dbgs() << S);
645 
646   auto ScopStats = S.getStatistics();
647   NumValueWrites[CallNo] += ScopStats.NumValueWrites;
648   NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops;
649   NumPHIWrites[CallNo] += ScopStats.NumPHIWrites;
650   NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops;
651   NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites;
652   NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops;
653 
654   return false;
655 }
656 
printScop(raw_ostream & OS,Scop & S) const657 void SimplifyVisitor::printScop(raw_ostream &OS, Scop &S) const {
658   assert(&S == this->S &&
659          "Can only print analysis for the last processed SCoP");
660   printStatistics(OS);
661 
662   if (!isModified()) {
663     OS << "SCoP could not be simplified\n";
664     return;
665   }
666   printAccesses(OS);
667 }
668 
releaseMemory()669 void SimplifyVisitor::releaseMemory() {
670   S = nullptr;
671 
672   EmptyDomainsRemoved = 0;
673   OverwritesRemoved = 0;
674   WritesCoalesced = 0;
675   RedundantWritesRemoved = 0;
676   EmptyPartialAccessesRemoved = 0;
677   DeadAccessesRemoved = 0;
678   DeadInstructionsRemoved = 0;
679   StmtsRemoved = 0;
680 }
681 
682 namespace {
683 class SimplifyLegacyPass : public ScopPass {
684 public:
685   static char ID;
686   SimplifyVisitor Imp;
687 
SimplifyLegacyPass(int CallNo=0)688   explicit SimplifyLegacyPass(int CallNo = 0) : ScopPass(ID), Imp(CallNo) {}
689 
getAnalysisUsage(AnalysisUsage & AU) const690   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
691     AU.addRequiredTransitive<ScopInfoRegionPass>();
692     AU.addRequired<LoopInfoWrapperPass>();
693     AU.setPreservesAll();
694   }
695 
runOnScop(Scop & S)696   virtual bool runOnScop(Scop &S) override {
697     return Imp.visit(S, &getAnalysis<LoopInfoWrapperPass>().getLoopInfo());
698   }
699 
printScop(raw_ostream & OS,Scop & S) const700   virtual void printScop(raw_ostream &OS, Scop &S) const override {
701     Imp.printScop(OS, S);
702   }
703 
releaseMemory()704   virtual void releaseMemory() override { Imp.releaseMemory(); }
705 };
706 
707 char SimplifyLegacyPass::ID;
708 } // anonymous namespace
709 
710 namespace polly {
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)711 llvm::PreservedAnalyses SimplifyPass::run(Scop &S, ScopAnalysisManager &SAM,
712                                           ScopStandardAnalysisResults &SAR,
713                                           SPMUpdater &U) {
714   if (!Imp.visit(S, &SAR.LI))
715     return llvm::PreservedAnalyses::all();
716 
717   return llvm::PreservedAnalyses::none();
718 }
719 
720 llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)721 SimplifyPrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
722                          ScopStandardAnalysisResults &SAR, SPMUpdater &U) {
723   bool Changed = Imp.visit(S, &SAR.LI);
724   Imp.printScop(OS, S);
725 
726   if (!Changed)
727     return llvm::PreservedAnalyses::all();
728 
729   return llvm::PreservedAnalyses::none();
730 }
731 
getAccessesInOrder(ScopStmt & Stmt)732 SmallVector<MemoryAccess *, 32> getAccessesInOrder(ScopStmt &Stmt) {
733 
734   SmallVector<MemoryAccess *, 32> Accesses;
735 
736   for (MemoryAccess *MemAcc : Stmt)
737     if (isImplicitRead(MemAcc))
738       Accesses.push_back(MemAcc);
739 
740   for (MemoryAccess *MemAcc : Stmt)
741     if (isExplicitAccess(MemAcc))
742       Accesses.push_back(MemAcc);
743 
744   for (MemoryAccess *MemAcc : Stmt)
745     if (isImplicitWrite(MemAcc))
746       Accesses.push_back(MemAcc);
747 
748   return Accesses;
749 }
750 } // namespace polly
751 
createSimplifyPass(int CallNo)752 Pass *polly::createSimplifyPass(int CallNo) {
753   return new SimplifyLegacyPass(CallNo);
754 }
755 
756 INITIALIZE_PASS_BEGIN(SimplifyLegacyPass, "polly-simplify", "Polly - Simplify",
757                       false, false)
758 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
759 INITIALIZE_PASS_END(SimplifyLegacyPass, "polly-simplify", "Polly - Simplify",
760                     false, false)
761