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