1 //===------ Simplify.cpp ----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
25 using namespace polly
;
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");
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");
62 "Number of scalar phi writes nested in affine loops after Simplify");
63 TWO_STATISTICS(NumSingletonWrites
, "Number of singleton writes after Simplify");
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.
83 /// This is implemented by adding disjuncts to the results until the limit is
85 static isl::union_map
underapproximatedAddMap(isl::union_map UMap
,
87 if (UMap
.is_null() || Map
.is_null())
90 isl::map PrevMap
= UMap
.extract_map(Map
.get_space());
92 // Fast path: If known that we cannot exceed the disjunct limit, just add
94 if (isl_map_n_basic_map(PrevMap
.get()) + isl_map_n_basic_map(Map
.get()) <=
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
)
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
)
107 Result
= Result
.unite(BMap
);
110 isl::union_map UResult
=
111 UMap
.subtract(isl::map::universe(PrevMap
.get_space()));
112 UResult
.add_map(Result
);
117 class Simplify
: public ScopPass
{
119 /// The invocation id (if there are multiple instances in the pass manager's
120 /// pipeline) to determine which statistics to update.
123 /// The last/current SCoP that is/has been processed.
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 ||
155 /// Remove writes that are overwritten unconditionally later in the same
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
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
))
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.
184 // Invalidate all overwrites for the array it accesses to avoid too
186 isl::map AccRelUniv
= isl::map::universe(AccRel
.get_space());
187 WillBeOverwritten
= WillBeOverwritten
.subtract(AccRelUniv
);
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
);
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
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
{
232 isl::set
&Result
= ValueSets
[V
];
233 if (Result
.is_null()) {
234 isl::ctx Ctx
= S
->getIslCtx();
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
));
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
))
258 // { Domain[] -> Element[] }
260 MA
->getLatestAccessRelation().intersect_domain(Domain
);
262 // { [Domain[] -> Element[]] }
263 isl::set AccRelWrapped
= AccRel
.wrap();
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();
280 StoredVal
= MA
->getAccessValue();
281 ValSet
= makeValueSet(StoredVal
);
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
);
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[] }
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
)
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())
326 // The combined access relation.
327 // { Domain[] -> Element[] }
328 isl::map NewAccRel
= AccRel
.unite(OtherAccRel
);
331 // Carry out the coalescing.
332 Stmt
.removeSingleMemoryAccess(MA
);
333 OtherMA
->setNewAccessRelation(NewAccRel
);
335 // We removed MA, OtherMA takes its role.
338 TotalWritesCoalesced
[CallNo
]++;
341 // Don't look for more candidates.
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
351 SmallPtrSet
<MemoryAccess
*, 2> TouchedAccesses
;
353 FutureWrites
.intersect_domain(AccRelWrapped
).get_map_list()) {
354 MemoryAccess
*MA
= (MemoryAccess
*)Map
.get_space()
357 .get_tuple_id(isl::dim::out
)
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()
367 .get_tuple_id(isl::dim::out
)
369 if (!TouchedAccesses
.count(MA
))
370 NewFutureWrites
= NewFutureWrites
.add_map(FutureWrite
);
372 FutureWrites
= NewFutureWrites
;
374 if (MA
->isMustWrite() && !ValSet
.is_null()) {
375 // { MemoryAccess[] }
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
394 void removeRedundantWrites() {
395 for (auto &Stmt
: *S
) {
396 SmallDenseMap
<Value
*, isl::set
> ValueSets
;
397 auto makeValueSet
= [&ValueSets
, this](Value
*V
) -> isl::set
{
399 isl::set
&Result
= ValueSets
[V
];
400 if (Result
.is_null()) {
401 isl_ctx
*Ctx
= S
->getIslCtx().get();
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
));
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.
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
438 if (IsOrdered
&& MA
->isMustWrite() &&
439 (isa
<StoreInst
>(MA
->getAccessInstruction()) ||
440 MA
->isOriginalScalarKind())) {
441 Value
*StoredVal
= MA
->tryGetValueStored();
443 StoredVal
= MA
->getAccessValue();
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.
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
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
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
) {
509 isl::map AccRel
= MA
->getAccessRelation();
510 if (!AccRel
.is_empty().is_true())
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
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
))
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(),
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
]++;
575 RemainInsts
.push_back(Inst
);
577 // If instructions appear multiple times, keep only the first.
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
591 OS
.indent(Indent
+ 4) << "Partial writes coalesced: " << WritesCoalesced
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
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
)
613 OS
.indent(Indent
) << "}\n";
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.
629 assert(!isModified());
631 // Prepare processing of this SCoP.
633 ScopsProcessed
[CallNo
]++;
635 LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n");
636 removeEmptyPartialAccesses();
638 LLVM_DEBUG(dbgs() << "Removing overwrites...\n");
641 LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n");
644 LLVM_DEBUG(dbgs() << "Removing redundant writes...\n");
645 removeRedundantWrites();
647 LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n");
648 LoopInfo
*LI
= &getAnalysis
<LoopInfoWrapperPass
>().getLoopInfo();
651 LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n");
652 removeUnnecessaryStmts();
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
;
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");
676 OS
<< "SCoP could not be simplified\n";
682 virtual void releaseMemory() override
{
685 OverwritesRemoved
= 0;
687 RedundantWritesRemoved
= 0;
688 EmptyPartialAccessesRemoved
= 0;
689 DeadAccessesRemoved
= 0;
690 DeadInstructionsRemoved
= 0;
696 } // anonymous namespace
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
);
719 Pass
*polly::createSimplifyPass(int CallNo
) { return new Simplify(CallNo
); }
721 INITIALIZE_PASS_BEGIN(Simplify
, "polly-simplify", "Polly - Simplify", false,
723 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass
)
724 INITIALIZE_PASS_END(Simplify
, "polly-simplify", "Polly - Simplify", false,