Fix Polly
[polly-mirror.git] / lib / Transform / Simplify.cpp
blob202eb87021756fe84802dd90d78b2d6b3b99a264
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.
11 //===----------------------------------------------------------------------===//
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/Support/Debug.h"
22 #define DEBUG_TYPE "polly-simplify"
24 using namespace llvm;
25 using namespace polly;
27 namespace {
29 #define TWO_STATISTICS(VARNAME, DESC) \
30 static llvm::Statistic VARNAME[2] = { \
31 {DEBUG_TYPE, #VARNAME "0", DESC " (first)"}, \
32 {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}}
34 /// Number of max disjuncts we allow in removeOverwrites(). This is to avoid
35 /// that the analysis of accesses in a statement is becoming too complex. Chosen
36 /// to be relatively small because all the common cases should access only few
37 /// array elements per statement.
38 static int const SimplifyMaxDisjuncts = 4;
40 TWO_STATISTICS(ScopsProcessed, "Number of SCoPs processed");
41 TWO_STATISTICS(ScopsModified, "Number of SCoPs simplified");
43 TWO_STATISTICS(TotalOverwritesRemoved, "Number of removed overwritten writes");
44 TWO_STATISTICS(TotalWritesCoalesced, "Number of writes coalesced with another");
45 TWO_STATISTICS(TotalRedundantWritesRemoved,
46 "Number of writes of same value removed in any SCoP");
47 TWO_STATISTICS(TotalEmptyPartialAccessesRemoved,
48 "Number of empty partial accesses removed");
49 TWO_STATISTICS(TotalDeadAccessesRemoved, "Number of dead accesses removed");
50 TWO_STATISTICS(TotalDeadInstructionsRemoved,
51 "Number of unused instructions removed");
52 TWO_STATISTICS(TotalStmtsRemoved, "Number of statements removed in any SCoP");
54 TWO_STATISTICS(NumValueWrites, "Number of scalar value writes after Simplify");
55 TWO_STATISTICS(
56 NumValueWritesInLoops,
57 "Number of scalar value writes nested in affine loops after Simplify");
58 TWO_STATISTICS(NumPHIWrites,
59 "Number of scalar phi writes after the first simplification");
60 TWO_STATISTICS(
61 NumPHIWritesInLoops,
62 "Number of scalar phi writes nested in affine loops after Simplify");
63 TWO_STATISTICS(NumSingletonWrites, "Number of singleton writes after Simplify");
64 TWO_STATISTICS(
65 NumSingletonWritesInLoops,
66 "Number of singleton writes nested in affine loops after Simplify");
68 static bool isImplicitRead(MemoryAccess *MA) {
69 return MA->isRead() && MA->isOriginalScalarKind();
72 static bool isExplicitAccess(MemoryAccess *MA) {
73 return MA->isOriginalArrayKind();
76 static bool isImplicitWrite(MemoryAccess *MA) {
77 return MA->isWrite() && MA->isOriginalScalarKind();
80 /// Like isl::union_map::add_map, but may also return an underapproximated
81 /// result if getting too complex.
82 ///
83 /// This is implemented by adding disjuncts to the results until the limit is
84 /// reached.
85 static isl::union_map underapproximatedAddMap(isl::union_map UMap,
86 isl::map Map) {
87 if (UMap.is_null() || Map.is_null())
88 return {};
90 isl::map PrevMap = UMap.extract_map(Map.get_space());
92 // Fast path: If known that we cannot exceed the disjunct limit, just add
93 // them.
94 if (isl_map_n_basic_map(PrevMap.get()) + isl_map_n_basic_map(Map.get()) <=
95 SimplifyMaxDisjuncts)
96 return UMap.add_map(Map);
98 isl::map Result = isl::map::empty(PrevMap.get_space());
99 for (isl::basic_map BMap : PrevMap.get_basic_map_list()) {
100 if (Result.n_basic_map() > SimplifyMaxDisjuncts)
101 break;
102 Result = Result.unite(BMap);
104 for (isl::basic_map BMap : Map.get_basic_map_list()) {
105 if (isl_map_n_basic_map(Result.get()) > SimplifyMaxDisjuncts)
106 break;
107 Result = Result.unite(BMap);
110 isl::union_map UResult =
111 UMap.subtract(isl::map::universe(PrevMap.get_space()));
112 UResult.add_map(Result);
114 return UResult;
117 class Simplify : public ScopPass {
118 private:
119 /// The invocation id (if there are multiple instances in the pass manager's
120 /// pipeline) to determine which statistics to update.
121 int CallNo;
123 /// The last/current SCoP that is/has been processed.
124 Scop *S;
126 /// Number of writes that are overwritten anyway.
127 int OverwritesRemoved = 0;
129 /// Number of combined writes.
130 int WritesCoalesced = 0;
132 /// Number of redundant writes removed from this SCoP.
133 int RedundantWritesRemoved = 0;
135 /// Number of writes with empty access domain removed.
136 int EmptyPartialAccessesRemoved = 0;
138 /// Number of unused accesses removed from this SCoP.
139 int DeadAccessesRemoved = 0;
141 /// Number of unused instructions removed from this SCoP.
142 int DeadInstructionsRemoved = 0;
144 /// Number of unnecessary statements removed from the SCoP.
145 int StmtsRemoved = 0;
147 /// Return whether at least one simplification has been applied.
148 bool isModified() const {
149 return OverwritesRemoved > 0 || WritesCoalesced > 0 ||
150 RedundantWritesRemoved > 0 || EmptyPartialAccessesRemoved > 0 ||
151 DeadAccessesRemoved > 0 || DeadInstructionsRemoved > 0 ||
152 StmtsRemoved > 0;
155 /// Remove writes that are overwritten unconditionally later in the same
156 /// statement.
158 /// There must be no read of the same value between the write (that is to be
159 /// removed) and the overwrite.
160 void removeOverwrites() {
161 for (auto &Stmt : *S) {
162 isl::set Domain = Stmt.getDomain();
163 isl::union_map WillBeOverwritten =
164 isl::union_map::empty(S->getParamSpace());
166 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
168 // Iterate in reverse order, so the overwrite comes before the write that
169 // is to be removed.
170 for (auto *MA : reverse(Accesses)) {
172 // In region statements, the explicit accesses can be in blocks that are
173 // can be executed in any order. We therefore process only the implicit
174 // writes and stop after that.
175 if (Stmt.isRegionStmt() && isExplicitAccess(MA))
176 break;
178 auto AccRel = MA->getAccessRelation();
179 AccRel = AccRel.intersect_domain(Domain);
180 AccRel = AccRel.intersect_params(S->getContext());
182 // If a value is read in-between, do not consider it as overwritten.
183 if (MA->isRead()) {
184 // Invalidate all overwrites for the array it accesses to avoid too
185 // complex isl sets.
186 isl::map AccRelUniv = isl::map::universe(AccRel.get_space());
187 WillBeOverwritten = WillBeOverwritten.subtract(AccRelUniv);
188 continue;
191 // If all of a write's elements are overwritten, remove it.
192 isl::union_map AccRelUnion = AccRel;
193 if (AccRelUnion.is_subset(WillBeOverwritten)) {
194 LLVM_DEBUG(dbgs() << "Removing " << MA
195 << " which will be overwritten anyway\n");
197 Stmt.removeSingleMemoryAccess(MA);
198 OverwritesRemoved++;
199 TotalOverwritesRemoved[CallNo]++;
202 // Unconditional writes overwrite other values.
203 if (MA->isMustWrite()) {
204 // Avoid too complex isl sets. If necessary, throw away some of the
205 // knowledge.
206 WillBeOverwritten =
207 underapproximatedAddMap(WillBeOverwritten, AccRel);
213 /// Combine writes that write the same value if possible.
215 /// This function is able to combine:
216 /// - Partial writes with disjoint domain.
217 /// - Writes that write to the same array element.
219 /// In all cases, both writes must write the same values.
220 void coalesceWrites() {
221 for (auto &Stmt : *S) {
222 isl::set Domain = Stmt.getDomain().intersect_params(S->getContext());
224 // We let isl do the lookup for the same-value condition. For this, we
225 // wrap llvm::Value into an isl::set such that isl can do the lookup in
226 // its hashtable implementation. llvm::Values are only compared within a
227 // ScopStmt, so the map can be local to this scope. TODO: Refactor with
228 // ZoneAlgorithm::makeValueSet()
229 SmallDenseMap<Value *, isl::set> ValueSets;
230 auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
231 assert(V);
232 isl::set &Result = ValueSets[V];
233 if (Result.is_null()) {
234 isl::ctx Ctx = S->getIslCtx();
235 std::string Name =
236 getIslCompatibleName("Val", V, ValueSets.size() - 1,
237 std::string(), UseInstructionNames);
238 isl::id Id = isl::id::alloc(Ctx, Name, V);
239 Result = isl::set::universe(
240 isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
242 return Result;
245 // List of all eligible (for coalescing) writes of the future.
246 // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
247 isl::union_map FutureWrites = isl::union_map::empty(S->getParamSpace());
249 // Iterate over accesses from the last to the first.
250 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
251 for (MemoryAccess *MA : reverse(Accesses)) {
252 // In region statements, the explicit accesses can be in blocks that can
253 // be executed in any order. We therefore process only the implicit
254 // writes and stop after that.
255 if (Stmt.isRegionStmt() && isExplicitAccess(MA))
256 break;
258 // { Domain[] -> Element[] }
259 isl::map AccRel =
260 MA->getLatestAccessRelation().intersect_domain(Domain);
262 // { [Domain[] -> Element[]] }
263 isl::set AccRelWrapped = AccRel.wrap();
265 // { Value[] }
266 isl::set ValSet;
268 if (MA->isMustWrite() && (MA->isOriginalScalarKind() ||
269 isa<StoreInst>(MA->getAccessInstruction()))) {
270 // Normally, tryGetValueStored() should be used to determine which
271 // element is written, but it can return nullptr; For PHI accesses,
272 // getAccessValue() returns the PHI instead of the PHI's incoming
273 // value. In this case, where we only compare values of a single
274 // statement, this is fine, because within a statement, a PHI in a
275 // successor block has always the same value as the incoming write. We
276 // still preferably use the incoming value directly so we also catch
277 // direct uses of that.
278 Value *StoredVal = MA->tryGetValueStored();
279 if (!StoredVal)
280 StoredVal = MA->getAccessValue();
281 ValSet = makeValueSet(StoredVal);
283 // { Domain[] }
284 isl::set AccDomain = AccRel.domain();
286 // Parts of the statement's domain that is not written by this access.
287 isl::set UndefDomain = Domain.subtract(AccDomain);
289 // { Element[] }
290 isl::set ElementUniverse =
291 isl::set::universe(AccRel.get_space().range());
293 // { Domain[] -> Element[] }
294 isl::map UndefAnything =
295 isl::map::from_domain_and_range(UndefDomain, ElementUniverse);
297 // We are looking a compatible write access. The other write can
298 // access these elements...
299 isl::map AllowedAccesses = AccRel.unite(UndefAnything);
301 // ... and must write the same value.
302 // { [Domain[] -> Element[]] -> Value[] }
303 isl::map Filter =
304 isl::map::from_domain_and_range(AllowedAccesses.wrap(), ValSet);
306 // Lookup future write that fulfills these conditions.
307 // { [[Domain[] -> Element[]] -> Value[]] -> MemoryAccess[] }
308 isl::union_map Filtered =
309 FutureWrites.uncurry().intersect_domain(Filter.wrap());
311 // Iterate through the candidates.
312 for (isl::map Map : Filtered.get_map_list()) {
313 MemoryAccess *OtherMA = (MemoryAccess *)Map.get_space()
314 .get_tuple_id(isl::dim::out)
315 .get_user();
317 isl::map OtherAccRel =
318 OtherMA->getLatestAccessRelation().intersect_domain(Domain);
320 // The filter only guaranteed that some of OtherMA's accessed
321 // elements are allowed. Verify that it only accesses allowed
322 // elements. Otherwise, continue with the next candidate.
323 if (!OtherAccRel.is_subset(AllowedAccesses).is_true())
324 continue;
326 // The combined access relation.
327 // { Domain[] -> Element[] }
328 isl::map NewAccRel = AccRel.unite(OtherAccRel);
329 simplify(NewAccRel);
331 // Carry out the coalescing.
332 Stmt.removeSingleMemoryAccess(MA);
333 OtherMA->setNewAccessRelation(NewAccRel);
335 // We removed MA, OtherMA takes its role.
336 MA = OtherMA;
338 TotalWritesCoalesced[CallNo]++;
339 WritesCoalesced++;
341 // Don't look for more candidates.
342 break;
346 // Two writes cannot be coalesced if there is another access (to some of
347 // the written elements) between them. Remove all visited write accesses
348 // from the list of eligible writes. Don't just remove the accessed
349 // elements, but any MemoryAccess that touches any of the invalidated
350 // elements.
351 SmallPtrSet<MemoryAccess *, 2> TouchedAccesses;
352 for (isl::map Map :
353 FutureWrites.intersect_domain(AccRelWrapped).get_map_list()) {
354 MemoryAccess *MA = (MemoryAccess *)Map.get_space()
355 .range()
356 .unwrap()
357 .get_tuple_id(isl::dim::out)
358 .get_user();
359 TouchedAccesses.insert(MA);
361 isl::union_map NewFutureWrites =
362 isl::union_map::empty(FutureWrites.get_space());
363 for (isl::map FutureWrite : FutureWrites.get_map_list()) {
364 MemoryAccess *MA = (MemoryAccess *)FutureWrite.get_space()
365 .range()
366 .unwrap()
367 .get_tuple_id(isl::dim::out)
368 .get_user();
369 if (!TouchedAccesses.count(MA))
370 NewFutureWrites = NewFutureWrites.add_map(FutureWrite);
372 FutureWrites = NewFutureWrites;
374 if (MA->isMustWrite() && !ValSet.is_null()) {
375 // { MemoryAccess[] }
376 auto AccSet =
377 isl::set::universe(isl::space(S->getIslCtx(), 0, 0)
378 .set_tuple_id(isl::dim::set, MA->getId()));
380 // { Val[] -> MemoryAccess[] }
381 isl::map ValAccSet = isl::map::from_domain_and_range(ValSet, AccSet);
383 // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
384 isl::map AccRelValAcc =
385 isl::map::from_domain_and_range(AccRelWrapped, ValAccSet.wrap());
386 FutureWrites = FutureWrites.add_map(AccRelValAcc);
392 /// Remove writes that just write the same value already stored in the
393 /// element.
394 void removeRedundantWrites() {
395 for (auto &Stmt : *S) {
396 SmallDenseMap<Value *, isl::set> ValueSets;
397 auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
398 assert(V);
399 isl::set &Result = ValueSets[V];
400 if (Result.is_null()) {
401 isl_ctx *Ctx = S->getIslCtx().get();
402 std::string Name =
403 getIslCompatibleName("Val", V, ValueSets.size() - 1,
404 std::string(), UseInstructionNames);
405 isl::id Id = isl::manage(isl_id_alloc(Ctx, Name.c_str(), V));
406 Result = isl::set::universe(
407 isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
409 return Result;
412 isl::set Domain = Stmt.getDomain();
413 Domain = Domain.intersect_params(S->getContext());
415 // List of element reads that still have the same value while iterating
416 // through the MemoryAccesses.
417 // { [Domain[] -> Element[]] -> Val[] }
418 isl::union_map Known = isl::union_map::empty(S->getParamSpace());
420 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
421 for (MemoryAccess *MA : Accesses) {
422 // Is the memory access in a defined order relative to the other
423 // accesses? In region statements, only the first and the last accesses
424 // have defined order. Execution of those in the middle may depend on
425 // runtime conditions an therefore cannot be modified.
426 bool IsOrdered =
427 Stmt.isBlockStmt() || MA->isOriginalScalarKind() ||
428 (!S->getBoxedLoops().size() && MA->getAccessInstruction() &&
429 Stmt.getEntryBlock() == MA->getAccessInstruction()->getParent());
431 isl::map AccRel = MA->getAccessRelation();
432 AccRel = AccRel.intersect_domain(Domain);
433 isl::set AccRelWrapped = AccRel.wrap();
435 // Determine whether a write is redundant (stores only values that are
436 // already present in the written array elements) and remove it if this
437 // is the case.
438 if (IsOrdered && MA->isMustWrite() &&
439 (isa<StoreInst>(MA->getAccessInstruction()) ||
440 MA->isOriginalScalarKind())) {
441 Value *StoredVal = MA->tryGetValueStored();
442 if (!StoredVal)
443 StoredVal = MA->getAccessValue();
445 if (StoredVal) {
446 // Lookup in the set of known values.
447 isl::map AccRelStoredVal = isl::map::from_domain_and_range(
448 AccRelWrapped, makeValueSet(StoredVal));
449 if (isl::union_map(AccRelStoredVal).is_subset(Known)) {
450 LLVM_DEBUG(dbgs() << "Cleanup of " << MA << ":\n");
451 LLVM_DEBUG(dbgs() << " Scalar: " << *StoredVal << "\n");
452 LLVM_DEBUG(dbgs() << " AccRel: " << AccRel << "\n");
454 Stmt.removeSingleMemoryAccess(MA);
456 RedundantWritesRemoved++;
457 TotalRedundantWritesRemoved[CallNo]++;
462 // Update the know values set.
463 if (MA->isRead()) {
464 // Loaded values are the currently known values of the array element
465 // it was loaded from.
466 Value *LoadedVal = MA->getAccessValue();
467 if (LoadedVal && IsOrdered) {
468 isl::map AccRelVal = isl::map::from_domain_and_range(
469 AccRelWrapped, makeValueSet(LoadedVal));
471 Known = Known.add_map(AccRelVal);
473 } else if (MA->isWrite()) {
474 // Remove (possibly) overwritten values from the known elements set.
475 // We remove all elements of the accessed array to avoid too complex
476 // isl sets.
477 isl::set AccRelUniv = isl::set::universe(AccRelWrapped.get_space());
478 Known = Known.subtract_domain(AccRelUniv);
480 // At this point, we could add the written value of must-writes.
481 // However, writing same values is already handled by
482 // coalesceWrites().
488 /// Remove statements without side effects.
489 void removeUnnecessaryStmts() {
490 auto NumStmtsBefore = S->getSize();
491 S->simplifySCoP(true);
492 assert(NumStmtsBefore >= S->getSize());
493 StmtsRemoved = NumStmtsBefore - S->getSize();
494 LLVM_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore
495 << ") statements\n");
496 TotalStmtsRemoved[CallNo] += StmtsRemoved;
499 /// Remove accesses that have an empty domain.
500 void removeEmptyPartialAccesses() {
501 for (ScopStmt &Stmt : *S) {
502 // Defer the actual removal to not invalidate iterators.
503 SmallVector<MemoryAccess *, 8> DeferredRemove;
505 for (MemoryAccess *MA : Stmt) {
506 if (!MA->isWrite())
507 continue;
509 isl::map AccRel = MA->getAccessRelation();
510 if (!AccRel.is_empty().is_true())
511 continue;
513 LLVM_DEBUG(
514 dbgs() << "Removing " << MA
515 << " because it's a partial access that never occurs\n");
516 DeferredRemove.push_back(MA);
519 for (MemoryAccess *MA : DeferredRemove) {
520 Stmt.removeSingleMemoryAccess(MA);
521 EmptyPartialAccessesRemoved++;
522 TotalEmptyPartialAccessesRemoved[CallNo]++;
527 /// Mark all reachable instructions and access, and sweep those that are not
528 /// reachable.
529 void markAndSweep(LoopInfo *LI) {
530 DenseSet<MemoryAccess *> UsedMA;
531 DenseSet<VirtualInstruction> UsedInsts;
533 // Get all reachable instructions and accesses.
534 markReachable(S, LI, UsedInsts, UsedMA);
536 // Remove all non-reachable accesses.
537 // We need get all MemoryAccesses first, in order to not invalidate the
538 // iterators when removing them.
539 SmallVector<MemoryAccess *, 64> AllMAs;
540 for (ScopStmt &Stmt : *S)
541 AllMAs.append(Stmt.begin(), Stmt.end());
543 for (MemoryAccess *MA : AllMAs) {
544 if (UsedMA.count(MA))
545 continue;
546 LLVM_DEBUG(dbgs() << "Removing " << MA
547 << " because its value is not used\n");
548 ScopStmt *Stmt = MA->getStatement();
549 Stmt->removeSingleMemoryAccess(MA);
551 DeadAccessesRemoved++;
552 TotalDeadAccessesRemoved[CallNo]++;
555 // Remove all non-reachable instructions.
556 for (ScopStmt &Stmt : *S) {
557 // Note that for region statements, we can only remove the non-terminator
558 // instructions of the entry block. All other instructions are not in the
559 // instructions list, but implicitly always part of the statement.
561 SmallVector<Instruction *, 32> AllInsts(Stmt.insts_begin(),
562 Stmt.insts_end());
563 SmallVector<Instruction *, 32> RemainInsts;
565 for (Instruction *Inst : AllInsts) {
566 auto It = UsedInsts.find({&Stmt, Inst});
567 if (It == UsedInsts.end()) {
568 LLVM_DEBUG(dbgs() << "Removing "; Inst->print(dbgs());
569 dbgs() << " because it is not used\n");
570 DeadInstructionsRemoved++;
571 TotalDeadInstructionsRemoved[CallNo]++;
572 continue;
575 RemainInsts.push_back(Inst);
577 // If instructions appear multiple times, keep only the first.
578 UsedInsts.erase(It);
581 // Set the new instruction list to be only those we did not remove.
582 Stmt.setInstructions(RemainInsts);
586 /// Print simplification statistics to @p OS.
587 void printStatistics(llvm::raw_ostream &OS, int Indent = 0) const {
588 OS.indent(Indent) << "Statistics {\n";
589 OS.indent(Indent + 4) << "Overwrites removed: " << OverwritesRemoved
590 << '\n';
591 OS.indent(Indent + 4) << "Partial writes coalesced: " << WritesCoalesced
592 << "\n";
593 OS.indent(Indent + 4) << "Redundant writes removed: "
594 << RedundantWritesRemoved << "\n";
595 OS.indent(Indent + 4) << "Accesses with empty domains removed: "
596 << EmptyPartialAccessesRemoved << "\n";
597 OS.indent(Indent + 4) << "Dead accesses removed: " << DeadAccessesRemoved
598 << '\n';
599 OS.indent(Indent + 4) << "Dead instructions removed: "
600 << DeadInstructionsRemoved << '\n';
601 OS.indent(Indent + 4) << "Stmts removed: " << StmtsRemoved << "\n";
602 OS.indent(Indent) << "}\n";
605 /// Print the current state of all MemoryAccesses to @p OS.
606 void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const {
607 OS.indent(Indent) << "After accesses {\n";
608 for (auto &Stmt : *S) {
609 OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
610 for (auto *MA : Stmt)
611 MA->print(OS);
613 OS.indent(Indent) << "}\n";
616 public:
617 static char ID;
618 explicit Simplify(int CallNo = 0) : ScopPass(ID), CallNo(CallNo) {}
620 virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
621 AU.addRequiredTransitive<ScopInfoRegionPass>();
622 AU.addRequired<LoopInfoWrapperPass>();
623 AU.setPreservesAll();
626 virtual bool runOnScop(Scop &S) override {
627 // Reset statistics of last processed SCoP.
628 releaseMemory();
629 assert(!isModified());
631 // Prepare processing of this SCoP.
632 this->S = &S;
633 ScopsProcessed[CallNo]++;
635 LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n");
636 removeEmptyPartialAccesses();
638 LLVM_DEBUG(dbgs() << "Removing overwrites...\n");
639 removeOverwrites();
641 LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n");
642 coalesceWrites();
644 LLVM_DEBUG(dbgs() << "Removing redundant writes...\n");
645 removeRedundantWrites();
647 LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n");
648 LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
649 markAndSweep(LI);
651 LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n");
652 removeUnnecessaryStmts();
654 if (isModified())
655 ScopsModified[CallNo]++;
656 LLVM_DEBUG(dbgs() << "\nFinal Scop:\n");
657 LLVM_DEBUG(dbgs() << S);
659 auto ScopStats = S.getStatistics();
660 NumValueWrites[CallNo] += ScopStats.NumValueWrites;
661 NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops;
662 NumPHIWrites[CallNo] += ScopStats.NumPHIWrites;
663 NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops;
664 NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites;
665 NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops;
667 return false;
670 virtual void printScop(raw_ostream &OS, Scop &S) const override {
671 assert(&S == this->S &&
672 "Can only print analysis for the last processed SCoP");
673 printStatistics(OS);
675 if (!isModified()) {
676 OS << "SCoP could not be simplified\n";
677 return;
679 printAccesses(OS);
682 virtual void releaseMemory() override {
683 S = nullptr;
685 OverwritesRemoved = 0;
686 WritesCoalesced = 0;
687 RedundantWritesRemoved = 0;
688 EmptyPartialAccessesRemoved = 0;
689 DeadAccessesRemoved = 0;
690 DeadInstructionsRemoved = 0;
691 StmtsRemoved = 0;
695 char Simplify::ID;
696 } // anonymous namespace
698 namespace polly {
699 SmallVector<MemoryAccess *, 32> getAccessesInOrder(ScopStmt &Stmt) {
701 SmallVector<MemoryAccess *, 32> Accesses;
703 for (MemoryAccess *MemAcc : Stmt)
704 if (isImplicitRead(MemAcc))
705 Accesses.push_back(MemAcc);
707 for (MemoryAccess *MemAcc : Stmt)
708 if (isExplicitAccess(MemAcc))
709 Accesses.push_back(MemAcc);
711 for (MemoryAccess *MemAcc : Stmt)
712 if (isImplicitWrite(MemAcc))
713 Accesses.push_back(MemAcc);
715 return Accesses;
717 } // namespace polly
719 Pass *polly::createSimplifyPass(int CallNo) { return new Simplify(CallNo); }
721 INITIALIZE_PASS_BEGIN(Simplify, "polly-simplify", "Polly - Simplify", false,
722 false)
723 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
724 INITIALIZE_PASS_END(Simplify, "polly-simplify", "Polly - Simplify", false,
725 false)