xref: /llvm-project/polly/lib/Transform/Simplify.cpp (revision 601d7eab0665ba298d81952da11593124fd893a0)
10446d81eSMichael Kruse //===------ Simplify.cpp ----------------------------------------*- C++ -*-===//
20446d81eSMichael Kruse //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60446d81eSMichael Kruse //
70446d81eSMichael Kruse //===----------------------------------------------------------------------===//
80446d81eSMichael Kruse //
90446d81eSMichael Kruse // Simplify a SCoP by removing unnecessary statements and accesses.
100446d81eSMichael Kruse //
110446d81eSMichael Kruse //===----------------------------------------------------------------------===//
120446d81eSMichael Kruse 
130446d81eSMichael Kruse #include "polly/Simplify.h"
140446d81eSMichael Kruse #include "polly/ScopInfo.h"
150446d81eSMichael Kruse #include "polly/ScopPass.h"
160446d81eSMichael Kruse #include "polly/Support/GICHelper.h"
1733204859STobias Grosser #include "polly/Support/ISLOStream.h"
18ce9617f4SMichael Kruse #include "polly/Support/ISLTools.h"
1922058c3fSMichael Kruse #include "polly/Support/VirtualInstruction.h"
200446d81eSMichael Kruse #include "llvm/ADT/Statistic.h"
2105da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
220446d81eSMichael Kruse #include "llvm/Support/Debug.h"
23ccdc271aSKazu Hirata #include <optional>
2423753c60SMichael Kruse 
25*601d7eabSKarthika Devi C #include "polly/Support/PollyDebug.h"
260446d81eSMichael Kruse #define DEBUG_TYPE "polly-simplify"
270446d81eSMichael Kruse 
280446d81eSMichael Kruse using namespace llvm;
290446d81eSMichael Kruse using namespace polly;
300446d81eSMichael Kruse 
310446d81eSMichael Kruse namespace {
320446d81eSMichael Kruse 
3306ed5292SMichael Kruse #define TWO_STATISTICS(VARNAME, DESC)                                          \
3406ed5292SMichael Kruse   static llvm::Statistic VARNAME[2] = {                                        \
35126158f0SVolodymyr Sapsai       {DEBUG_TYPE, #VARNAME "0", DESC " (first)"},                             \
36126158f0SVolodymyr Sapsai       {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}}
3706ed5292SMichael Kruse 
38693ef999SMichael Kruse /// Number of max disjuncts we allow in removeOverwrites(). This is to avoid
39693ef999SMichael Kruse /// that the analysis of accesses in a statement is becoming too complex. Chosen
40693ef999SMichael Kruse /// to be relatively small because all the common cases should access only few
41693ef999SMichael Kruse /// array elements per statement.
4244596fe6SRiccardo Mori static unsigned const SimplifyMaxDisjuncts = 4;
43693ef999SMichael Kruse 
4406ed5292SMichael Kruse TWO_STATISTICS(ScopsProcessed, "Number of SCoPs processed");
4506ed5292SMichael Kruse TWO_STATISTICS(ScopsModified, "Number of SCoPs simplified");
460446d81eSMichael Kruse 
476983741eSMichael Kruse TWO_STATISTICS(TotalEmptyDomainsRemoved,
486983741eSMichael Kruse                "Number of statement with empty domains removed in any SCoP");
4906ed5292SMichael Kruse TWO_STATISTICS(TotalOverwritesRemoved, "Number of removed overwritten writes");
5006ed5292SMichael Kruse TWO_STATISTICS(TotalWritesCoalesced, "Number of writes coalesced with another");
5106ed5292SMichael Kruse TWO_STATISTICS(TotalRedundantWritesRemoved,
520446d81eSMichael Kruse                "Number of writes of same value removed in any SCoP");
5306ed5292SMichael Kruse TWO_STATISTICS(TotalEmptyPartialAccessesRemoved,
54ab8f0d57SMichael Kruse                "Number of empty partial accesses removed");
5506ed5292SMichael Kruse TWO_STATISTICS(TotalDeadAccessesRemoved, "Number of dead accesses removed");
5606ed5292SMichael Kruse TWO_STATISTICS(TotalDeadInstructionsRemoved,
5722058c3fSMichael Kruse                "Number of unused instructions removed");
5806ed5292SMichael Kruse TWO_STATISTICS(TotalStmtsRemoved, "Number of statements removed in any SCoP");
5906ed5292SMichael Kruse 
6006ed5292SMichael Kruse TWO_STATISTICS(NumValueWrites, "Number of scalar value writes after Simplify");
6106ed5292SMichael Kruse TWO_STATISTICS(
6206ed5292SMichael Kruse     NumValueWritesInLoops,
6306ed5292SMichael Kruse     "Number of scalar value writes nested in affine loops after Simplify");
6406ed5292SMichael Kruse TWO_STATISTICS(NumPHIWrites,
6506ed5292SMichael Kruse                "Number of scalar phi writes after the first simplification");
6606ed5292SMichael Kruse TWO_STATISTICS(
6706ed5292SMichael Kruse     NumPHIWritesInLoops,
6806ed5292SMichael Kruse     "Number of scalar phi writes nested in affine loops after Simplify");
6906ed5292SMichael Kruse TWO_STATISTICS(NumSingletonWrites, "Number of singleton writes after Simplify");
7006ed5292SMichael Kruse TWO_STATISTICS(
7106ed5292SMichael Kruse     NumSingletonWritesInLoops,
7206ed5292SMichael Kruse     "Number of singleton writes nested in affine loops after Simplify");
730446d81eSMichael Kruse 
isImplicitRead(MemoryAccess * MA)74f263610bSMichael Kruse static bool isImplicitRead(MemoryAccess *MA) {
75f263610bSMichael Kruse   return MA->isRead() && MA->isOriginalScalarKind();
76f263610bSMichael Kruse }
77f263610bSMichael Kruse 
isExplicitAccess(MemoryAccess * MA)78f263610bSMichael Kruse static bool isExplicitAccess(MemoryAccess *MA) {
79f263610bSMichael Kruse   return MA->isOriginalArrayKind();
80f263610bSMichael Kruse }
81f263610bSMichael Kruse 
isImplicitWrite(MemoryAccess * MA)82f263610bSMichael Kruse static bool isImplicitWrite(MemoryAccess *MA) {
83f263610bSMichael Kruse   return MA->isWrite() && MA->isOriginalScalarKind();
84f263610bSMichael Kruse }
85f263610bSMichael Kruse 
86d5ee355fSRiccardo Mori /// Like isl::union_map::unite, but may also return an underapproximated
87693ef999SMichael Kruse /// result if getting too complex.
88693ef999SMichael Kruse ///
89693ef999SMichael Kruse /// This is implemented by adding disjuncts to the results until the limit is
90693ef999SMichael Kruse /// reached.
underapproximatedAddMap(isl::union_map UMap,isl::map Map)91693ef999SMichael Kruse static isl::union_map underapproximatedAddMap(isl::union_map UMap,
92693ef999SMichael Kruse                                               isl::map Map) {
93693ef999SMichael Kruse   if (UMap.is_null() || Map.is_null())
94693ef999SMichael Kruse     return {};
95693ef999SMichael Kruse 
96693ef999SMichael Kruse   isl::map PrevMap = UMap.extract_map(Map.get_space());
97693ef999SMichael Kruse 
98693ef999SMichael Kruse   // Fast path: If known that we cannot exceed the disjunct limit, just add
99693ef999SMichael Kruse   // them.
10044596fe6SRiccardo Mori   if (unsignedFromIslSize(PrevMap.n_basic_map()) +
10144596fe6SRiccardo Mori           unsignedFromIslSize(Map.n_basic_map()) <=
102693ef999SMichael Kruse       SimplifyMaxDisjuncts)
103d5ee355fSRiccardo Mori     return UMap.unite(Map);
104693ef999SMichael Kruse 
105693ef999SMichael Kruse   isl::map Result = isl::map::empty(PrevMap.get_space());
106a3387168STobias Grosser   for (isl::basic_map BMap : PrevMap.get_basic_map_list()) {
10744596fe6SRiccardo Mori     if (unsignedFromIslSize(Result.n_basic_map()) > SimplifyMaxDisjuncts)
108a3387168STobias Grosser       break;
109693ef999SMichael Kruse     Result = Result.unite(BMap);
110a3387168STobias Grosser   }
111a3387168STobias Grosser   for (isl::basic_map BMap : Map.get_basic_map_list()) {
11244596fe6SRiccardo Mori     if (unsignedFromIslSize(Result.n_basic_map()) > SimplifyMaxDisjuncts)
113a3387168STobias Grosser       break;
114693ef999SMichael Kruse     Result = Result.unite(BMap);
115a3387168STobias Grosser   }
116693ef999SMichael Kruse 
117693ef999SMichael Kruse   isl::union_map UResult =
118693ef999SMichael Kruse       UMap.subtract(isl::map::universe(PrevMap.get_space()));
119d5ee355fSRiccardo Mori   UResult.unite(Result);
120693ef999SMichael Kruse 
121693ef999SMichael Kruse   return UResult;
122693ef999SMichael Kruse }
12323753c60SMichael Kruse 
124bd93df93SMichael Kruse class SimplifyImpl final {
12523753c60SMichael Kruse private:
12623753c60SMichael Kruse   /// The invocation id (if there are multiple instances in the pass manager's
12723753c60SMichael Kruse   /// pipeline) to determine which statistics to update.
12823753c60SMichael Kruse   int CallNo;
12923753c60SMichael Kruse 
13023753c60SMichael Kruse   /// The last/current SCoP that is/has been processed.
13123753c60SMichael Kruse   Scop *S = nullptr;
13223753c60SMichael Kruse 
13323753c60SMichael Kruse   /// Number of statements with empty domains removed from the SCoP.
13423753c60SMichael Kruse   int EmptyDomainsRemoved = 0;
13523753c60SMichael Kruse 
13623753c60SMichael Kruse   /// Number of writes that are overwritten anyway.
13723753c60SMichael Kruse   int OverwritesRemoved = 0;
13823753c60SMichael Kruse 
13923753c60SMichael Kruse   /// Number of combined writes.
14023753c60SMichael Kruse   int WritesCoalesced = 0;
14123753c60SMichael Kruse 
14223753c60SMichael Kruse   /// Number of redundant writes removed from this SCoP.
14323753c60SMichael Kruse   int RedundantWritesRemoved = 0;
14423753c60SMichael Kruse 
14523753c60SMichael Kruse   /// Number of writes with empty access domain removed.
14623753c60SMichael Kruse   int EmptyPartialAccessesRemoved = 0;
14723753c60SMichael Kruse 
14823753c60SMichael Kruse   /// Number of unused accesses removed from this SCoP.
14923753c60SMichael Kruse   int DeadAccessesRemoved = 0;
15023753c60SMichael Kruse 
15123753c60SMichael Kruse   /// Number of unused instructions removed from this SCoP.
15223753c60SMichael Kruse   int DeadInstructionsRemoved = 0;
15323753c60SMichael Kruse 
15423753c60SMichael Kruse   /// Number of unnecessary statements removed from the SCoP.
15523753c60SMichael Kruse   int StmtsRemoved = 0;
15623753c60SMichael Kruse 
15723753c60SMichael Kruse   /// Remove statements that are never executed due to their domains being
15823753c60SMichael Kruse   /// empty.
15923753c60SMichael Kruse   ///
16023753c60SMichael Kruse   /// In contrast to Scop::simplifySCoP, this removes based on the SCoP's
16123753c60SMichael Kruse   /// effective domain, i.e. including the SCoP's context as used by some other
16223753c60SMichael Kruse   /// simplification methods in this pass. This is necessary because the
16323753c60SMichael Kruse   /// analysis on empty domains is unreliable, e.g. remove a scalar value
16423753c60SMichael Kruse   /// definition MemoryAccesses, but not its use.
16523753c60SMichael Kruse   void removeEmptyDomainStmts();
16623753c60SMichael Kruse 
16723753c60SMichael Kruse   /// Remove writes that are overwritten unconditionally later in the same
16823753c60SMichael Kruse   /// statement.
16923753c60SMichael Kruse   ///
17023753c60SMichael Kruse   /// There must be no read of the same value between the write (that is to be
17123753c60SMichael Kruse   /// removed) and the overwrite.
17223753c60SMichael Kruse   void removeOverwrites();
17323753c60SMichael Kruse 
17423753c60SMichael Kruse   /// Combine writes that write the same value if possible.
17523753c60SMichael Kruse   ///
17623753c60SMichael Kruse   /// This function is able to combine:
17723753c60SMichael Kruse   /// - Partial writes with disjoint domain.
17823753c60SMichael Kruse   /// - Writes that write to the same array element.
17923753c60SMichael Kruse   ///
18023753c60SMichael Kruse   /// In all cases, both writes must write the same values.
18123753c60SMichael Kruse   void coalesceWrites();
18223753c60SMichael Kruse 
18323753c60SMichael Kruse   /// Remove writes that just write the same value already stored in the
18423753c60SMichael Kruse   /// element.
18523753c60SMichael Kruse   void removeRedundantWrites();
18623753c60SMichael Kruse 
18723753c60SMichael Kruse   /// Remove statements without side effects.
18823753c60SMichael Kruse   void removeUnnecessaryStmts();
18923753c60SMichael Kruse 
19023753c60SMichael Kruse   /// Remove accesses that have an empty domain.
19123753c60SMichael Kruse   void removeEmptyPartialAccesses();
19223753c60SMichael Kruse 
19323753c60SMichael Kruse   /// Mark all reachable instructions and access, and sweep those that are not
19423753c60SMichael Kruse   /// reachable.
19523753c60SMichael Kruse   void markAndSweep(LoopInfo *LI);
19623753c60SMichael Kruse 
19723753c60SMichael Kruse   /// Print simplification statistics to @p OS.
19823753c60SMichael Kruse   void printStatistics(llvm::raw_ostream &OS, int Indent = 0) const;
19923753c60SMichael Kruse 
20023753c60SMichael Kruse   /// Print the current state of all MemoryAccesses to @p OS.
20123753c60SMichael Kruse   void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const;
20223753c60SMichael Kruse 
20323753c60SMichael Kruse public:
SimplifyImpl(int CallNo=0)20423753c60SMichael Kruse   explicit SimplifyImpl(int CallNo = 0) : CallNo(CallNo) {}
20523753c60SMichael Kruse 
20623753c60SMichael Kruse   void run(Scop &S, LoopInfo *LI);
20723753c60SMichael Kruse 
20823753c60SMichael Kruse   void printScop(raw_ostream &OS, Scop &S) const;
209693ef999SMichael Kruse 
2100446d81eSMichael Kruse   /// Return whether at least one simplification has been applied.
21123753c60SMichael Kruse   bool isModified() const;
21223753c60SMichael Kruse };
21323753c60SMichael Kruse 
21423753c60SMichael Kruse /// Return whether at least one simplification has been applied.
isModified() const21523753c60SMichael Kruse bool SimplifyImpl::isModified() const {
2166983741eSMichael Kruse   return EmptyDomainsRemoved > 0 || OverwritesRemoved > 0 ||
2176983741eSMichael Kruse          WritesCoalesced > 0 || RedundantWritesRemoved > 0 ||
2186983741eSMichael Kruse          EmptyPartialAccessesRemoved > 0 || DeadAccessesRemoved > 0 ||
2196983741eSMichael Kruse          DeadInstructionsRemoved > 0 || StmtsRemoved > 0;
2206983741eSMichael Kruse }
2216983741eSMichael Kruse 
2226983741eSMichael Kruse /// Remove statements that are never executed due to their domains being
2236983741eSMichael Kruse /// empty.
2246983741eSMichael Kruse ///
2256983741eSMichael Kruse /// In contrast to Scop::simplifySCoP, this removes based on the SCoP's
2266983741eSMichael Kruse /// effective domain, i.e. including the SCoP's context as used by some other
2276983741eSMichael Kruse /// simplification methods in this pass. This is necessary because the
2286983741eSMichael Kruse /// analysis on empty domains is unreliable, e.g. remove a scalar value
2296983741eSMichael Kruse /// definition MemoryAccesses, but not its use.
removeEmptyDomainStmts()23023753c60SMichael Kruse void SimplifyImpl::removeEmptyDomainStmts() {
2316983741eSMichael Kruse   size_t NumStmtsBefore = S->getSize();
2326983741eSMichael Kruse 
2336538fff3SMichael Kruse   S->removeStmts([](ScopStmt &Stmt) -> bool {
2346983741eSMichael Kruse     auto EffectiveDomain =
2356983741eSMichael Kruse         Stmt.getDomain().intersect_params(Stmt.getParent()->getContext());
2366983741eSMichael Kruse     return EffectiveDomain.is_empty();
2376538fff3SMichael Kruse   });
2386983741eSMichael Kruse 
2396983741eSMichael Kruse   assert(NumStmtsBefore >= S->getSize());
2406983741eSMichael Kruse   EmptyDomainsRemoved = NumStmtsBefore - S->getSize();
241*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removed " << EmptyDomainsRemoved << " (of "
242deb00cf0SPengxuan Zheng                      << NumStmtsBefore << ") statements with empty domains \n");
2436983741eSMichael Kruse   TotalEmptyDomainsRemoved[CallNo] += EmptyDomainsRemoved;
2440446d81eSMichael Kruse }
2450446d81eSMichael Kruse 
246f263610bSMichael Kruse /// Remove writes that are overwritten unconditionally later in the same
247f263610bSMichael Kruse /// statement.
248f263610bSMichael Kruse ///
249f263610bSMichael Kruse /// There must be no read of the same value between the write (that is to be
250f263610bSMichael Kruse /// removed) and the overwrite.
removeOverwrites()25123753c60SMichael Kruse void SimplifyImpl::removeOverwrites() {
252f263610bSMichael Kruse   for (auto &Stmt : *S) {
253dcf8d696STobias Grosser     isl::set Domain = Stmt.getDomain();
254bad3ebbaSRiccardo Mori     isl::union_map WillBeOverwritten = isl::union_map::empty(S->getIslCtx());
255f263610bSMichael Kruse 
2569746f817SSiddharth Bhat     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
257f263610bSMichael Kruse 
258f263610bSMichael Kruse     // Iterate in reverse order, so the overwrite comes before the write that
259f263610bSMichael Kruse     // is to be removed.
260f263610bSMichael Kruse     for (auto *MA : reverse(Accesses)) {
261f263610bSMichael Kruse 
262f263610bSMichael Kruse       // In region statements, the explicit accesses can be in blocks that are
263f263610bSMichael Kruse       // can be executed in any order. We therefore process only the implicit
264f263610bSMichael Kruse       // writes and stop after that.
265f263610bSMichael Kruse       if (Stmt.isRegionStmt() && isExplicitAccess(MA))
266f263610bSMichael Kruse         break;
267f263610bSMichael Kruse 
2681515f6b9STobias Grosser       auto AccRel = MA->getAccessRelation();
269f263610bSMichael Kruse       AccRel = AccRel.intersect_domain(Domain);
270b65ccc43STobias Grosser       AccRel = AccRel.intersect_params(S->getContext());
271f263610bSMichael Kruse 
272f263610bSMichael Kruse       // If a value is read in-between, do not consider it as overwritten.
273f263610bSMichael Kruse       if (MA->isRead()) {
274693ef999SMichael Kruse         // Invalidate all overwrites for the array it accesses to avoid too
275693ef999SMichael Kruse         // complex isl sets.
276693ef999SMichael Kruse         isl::map AccRelUniv = isl::map::universe(AccRel.get_space());
277693ef999SMichael Kruse         WillBeOverwritten = WillBeOverwritten.subtract(AccRelUniv);
278f263610bSMichael Kruse         continue;
279f263610bSMichael Kruse       }
280f263610bSMichael Kruse 
281f263610bSMichael Kruse       // If all of a write's elements are overwritten, remove it.
282f263610bSMichael Kruse       isl::union_map AccRelUnion = AccRel;
283b5f61bdeSTobias Grosser       if (AccRelUnion.is_subset(WillBeOverwritten)) {
284*601d7eabSKarthika Devi C         POLLY_DEBUG(dbgs() << "Removing " << MA
285f263610bSMichael Kruse                            << " which will be overwritten anyway\n");
286f263610bSMichael Kruse 
287f263610bSMichael Kruse         Stmt.removeSingleMemoryAccess(MA);
288f263610bSMichael Kruse         OverwritesRemoved++;
28906ed5292SMichael Kruse         TotalOverwritesRemoved[CallNo]++;
290f263610bSMichael Kruse       }
291f263610bSMichael Kruse 
292f263610bSMichael Kruse       // Unconditional writes overwrite other values.
293693ef999SMichael Kruse       if (MA->isMustWrite()) {
294693ef999SMichael Kruse         // Avoid too complex isl sets. If necessary, throw away some of the
295693ef999SMichael Kruse         // knowledge.
296deb00cf0SPengxuan Zheng         WillBeOverwritten = underapproximatedAddMap(WillBeOverwritten, AccRel);
297693ef999SMichael Kruse       }
298f263610bSMichael Kruse     }
299f263610bSMichael Kruse   }
300f263610bSMichael Kruse }
301f263610bSMichael Kruse 
302ce9617f4SMichael Kruse /// Combine writes that write the same value if possible.
303ce9617f4SMichael Kruse ///
304ce9617f4SMichael Kruse /// This function is able to combine:
305ce9617f4SMichael Kruse /// - Partial writes with disjoint domain.
306ce9617f4SMichael Kruse /// - Writes that write to the same array element.
307ce9617f4SMichael Kruse ///
308ce9617f4SMichael Kruse /// In all cases, both writes must write the same values.
coalesceWrites()30923753c60SMichael Kruse void SimplifyImpl::coalesceWrites() {
310ce9617f4SMichael Kruse   for (auto &Stmt : *S) {
311b65ccc43STobias Grosser     isl::set Domain = Stmt.getDomain().intersect_params(S->getContext());
312ce9617f4SMichael Kruse 
313ce9617f4SMichael Kruse     // We let isl do the lookup for the same-value condition. For this, we
314ce9617f4SMichael Kruse     // wrap llvm::Value into an isl::set such that isl can do the lookup in
315ce9617f4SMichael Kruse     // its hashtable implementation. llvm::Values are only compared within a
316ce9617f4SMichael Kruse     // ScopStmt, so the map can be local to this scope. TODO: Refactor with
317ce9617f4SMichael Kruse     // ZoneAlgorithm::makeValueSet()
318ce9617f4SMichael Kruse     SmallDenseMap<Value *, isl::set> ValueSets;
319ce9617f4SMichael Kruse     auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
320ce9617f4SMichael Kruse       assert(V);
321ce9617f4SMichael Kruse       isl::set &Result = ValueSets[V];
322ce9617f4SMichael Kruse       if (Result.is_null()) {
32300fd43b3SPhilip Pfaffe         isl::ctx Ctx = S->getIslCtx();
324deb00cf0SPengxuan Zheng         std::string Name = getIslCompatibleName(
325deb00cf0SPengxuan Zheng             "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames);
32600fd43b3SPhilip Pfaffe         isl::id Id = isl::id::alloc(Ctx, Name, V);
327ce9617f4SMichael Kruse         Result = isl::set::universe(
328ce9617f4SMichael Kruse             isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
329ce9617f4SMichael Kruse       }
330ce9617f4SMichael Kruse       return Result;
331ce9617f4SMichael Kruse     };
332ce9617f4SMichael Kruse 
333ce9617f4SMichael Kruse     // List of all eligible (for coalescing) writes of the future.
334ce9617f4SMichael Kruse     // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
335bad3ebbaSRiccardo Mori     isl::union_map FutureWrites = isl::union_map::empty(S->getIslCtx());
336ce9617f4SMichael Kruse 
337ce9617f4SMichael Kruse     // Iterate over accesses from the last to the first.
338ce9617f4SMichael Kruse     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
339ce9617f4SMichael Kruse     for (MemoryAccess *MA : reverse(Accesses)) {
340ce9617f4SMichael Kruse       // In region statements, the explicit accesses can be in blocks that can
341ce9617f4SMichael Kruse       // be executed in any order. We therefore process only the implicit
342ce9617f4SMichael Kruse       // writes and stop after that.
343ce9617f4SMichael Kruse       if (Stmt.isRegionStmt() && isExplicitAccess(MA))
344ce9617f4SMichael Kruse         break;
345ce9617f4SMichael Kruse 
346ce9617f4SMichael Kruse       // { Domain[] -> Element[] }
347deb00cf0SPengxuan Zheng       isl::map AccRel = MA->getLatestAccessRelation().intersect_domain(Domain);
348ce9617f4SMichael Kruse 
349ce9617f4SMichael Kruse       // { [Domain[] -> Element[]] }
350ce9617f4SMichael Kruse       isl::set AccRelWrapped = AccRel.wrap();
351ce9617f4SMichael Kruse 
352ce9617f4SMichael Kruse       // { Value[] }
353ce9617f4SMichael Kruse       isl::set ValSet;
354ce9617f4SMichael Kruse 
355ce9617f4SMichael Kruse       if (MA->isMustWrite() && (MA->isOriginalScalarKind() ||
356ce9617f4SMichael Kruse                                 isa<StoreInst>(MA->getAccessInstruction()))) {
357ce9617f4SMichael Kruse         // Normally, tryGetValueStored() should be used to determine which
358ce9617f4SMichael Kruse         // element is written, but it can return nullptr; For PHI accesses,
359ce9617f4SMichael Kruse         // getAccessValue() returns the PHI instead of the PHI's incoming
360ce9617f4SMichael Kruse         // value. In this case, where we only compare values of a single
361ce9617f4SMichael Kruse         // statement, this is fine, because within a statement, a PHI in a
362ce9617f4SMichael Kruse         // successor block has always the same value as the incoming write. We
363ce9617f4SMichael Kruse         // still preferably use the incoming value directly so we also catch
364ce9617f4SMichael Kruse         // direct uses of that.
365ce9617f4SMichael Kruse         Value *StoredVal = MA->tryGetValueStored();
366ce9617f4SMichael Kruse         if (!StoredVal)
367ce9617f4SMichael Kruse           StoredVal = MA->getAccessValue();
368ce9617f4SMichael Kruse         ValSet = makeValueSet(StoredVal);
369ce9617f4SMichael Kruse 
370ce9617f4SMichael Kruse         // { Domain[] }
371ce9617f4SMichael Kruse         isl::set AccDomain = AccRel.domain();
372ce9617f4SMichael Kruse 
373ce9617f4SMichael Kruse         // Parts of the statement's domain that is not written by this access.
374ce9617f4SMichael Kruse         isl::set UndefDomain = Domain.subtract(AccDomain);
375ce9617f4SMichael Kruse 
376ce9617f4SMichael Kruse         // { Element[] }
377ce9617f4SMichael Kruse         isl::set ElementUniverse =
378ce9617f4SMichael Kruse             isl::set::universe(AccRel.get_space().range());
379ce9617f4SMichael Kruse 
380ce9617f4SMichael Kruse         // { Domain[] -> Element[] }
381ce9617f4SMichael Kruse         isl::map UndefAnything =
382ce9617f4SMichael Kruse             isl::map::from_domain_and_range(UndefDomain, ElementUniverse);
383ce9617f4SMichael Kruse 
384ce9617f4SMichael Kruse         // We are looking a compatible write access. The other write can
385ce9617f4SMichael Kruse         // access these elements...
386ce9617f4SMichael Kruse         isl::map AllowedAccesses = AccRel.unite(UndefAnything);
387ce9617f4SMichael Kruse 
388ce9617f4SMichael Kruse         // ... and must write the same value.
389ce9617f4SMichael Kruse         // { [Domain[] -> Element[]] -> Value[] }
390ce9617f4SMichael Kruse         isl::map Filter =
391ce9617f4SMichael Kruse             isl::map::from_domain_and_range(AllowedAccesses.wrap(), ValSet);
392ce9617f4SMichael Kruse 
393ce9617f4SMichael Kruse         // Lookup future write that fulfills these conditions.
394ce9617f4SMichael Kruse         // { [[Domain[] -> Element[]] -> Value[]] -> MemoryAccess[] }
395ce9617f4SMichael Kruse         isl::union_map Filtered =
396ce9617f4SMichael Kruse             FutureWrites.uncurry().intersect_domain(Filter.wrap());
397ce9617f4SMichael Kruse 
398ce9617f4SMichael Kruse         // Iterate through the candidates.
399a3387168STobias Grosser         for (isl::map Map : Filtered.get_map_list()) {
400ce9617f4SMichael Kruse           MemoryAccess *OtherMA = (MemoryAccess *)Map.get_space()
401ce9617f4SMichael Kruse                                       .get_tuple_id(isl::dim::out)
402ce9617f4SMichael Kruse                                       .get_user();
403ce9617f4SMichael Kruse 
404ce9617f4SMichael Kruse           isl::map OtherAccRel =
405ce9617f4SMichael Kruse               OtherMA->getLatestAccessRelation().intersect_domain(Domain);
406ce9617f4SMichael Kruse 
407ce9617f4SMichael Kruse           // The filter only guaranteed that some of OtherMA's accessed
408ce9617f4SMichael Kruse           // elements are allowed. Verify that it only accesses allowed
409ce9617f4SMichael Kruse           // elements. Otherwise, continue with the next candidate.
410ce9617f4SMichael Kruse           if (!OtherAccRel.is_subset(AllowedAccesses).is_true())
411a3387168STobias Grosser             continue;
412ce9617f4SMichael Kruse 
413ce9617f4SMichael Kruse           // The combined access relation.
414ce9617f4SMichael Kruse           // { Domain[] -> Element[] }
415ce9617f4SMichael Kruse           isl::map NewAccRel = AccRel.unite(OtherAccRel);
416ce9617f4SMichael Kruse           simplify(NewAccRel);
417ce9617f4SMichael Kruse 
418ce9617f4SMichael Kruse           // Carry out the coalescing.
419ce9617f4SMichael Kruse           Stmt.removeSingleMemoryAccess(MA);
4207b45af13STobias Grosser           OtherMA->setNewAccessRelation(NewAccRel);
421ce9617f4SMichael Kruse 
422ce9617f4SMichael Kruse           // We removed MA, OtherMA takes its role.
423ce9617f4SMichael Kruse           MA = OtherMA;
424ce9617f4SMichael Kruse 
42506ed5292SMichael Kruse           TotalWritesCoalesced[CallNo]++;
426ce9617f4SMichael Kruse           WritesCoalesced++;
427ce9617f4SMichael Kruse 
428ce9617f4SMichael Kruse           // Don't look for more candidates.
429a3387168STobias Grosser           break;
430a3387168STobias Grosser         }
431ce9617f4SMichael Kruse       }
432ce9617f4SMichael Kruse 
433ce9617f4SMichael Kruse       // Two writes cannot be coalesced if there is another access (to some of
434ce9617f4SMichael Kruse       // the written elements) between them. Remove all visited write accesses
435ce9617f4SMichael Kruse       // from the list of eligible writes. Don't just remove the accessed
436ce9617f4SMichael Kruse       // elements, but any MemoryAccess that touches any of the invalidated
437ce9617f4SMichael Kruse       // elements.
438693ef999SMichael Kruse       SmallPtrSet<MemoryAccess *, 2> TouchedAccesses;
439a3387168STobias Grosser       for (isl::map Map :
440a3387168STobias Grosser            FutureWrites.intersect_domain(AccRelWrapped).get_map_list()) {
441693ef999SMichael Kruse         MemoryAccess *MA = (MemoryAccess *)Map.get_space()
442ce9617f4SMichael Kruse                                .range()
443ce9617f4SMichael Kruse                                .unwrap()
444693ef999SMichael Kruse                                .get_tuple_id(isl::dim::out)
445693ef999SMichael Kruse                                .get_user();
446693ef999SMichael Kruse         TouchedAccesses.insert(MA);
447a3387168STobias Grosser       }
448693ef999SMichael Kruse       isl::union_map NewFutureWrites =
449bad3ebbaSRiccardo Mori           isl::union_map::empty(FutureWrites.ctx());
450a3387168STobias Grosser       for (isl::map FutureWrite : FutureWrites.get_map_list()) {
451693ef999SMichael Kruse         MemoryAccess *MA = (MemoryAccess *)FutureWrite.get_space()
452693ef999SMichael Kruse                                .range()
453693ef999SMichael Kruse                                .unwrap()
454693ef999SMichael Kruse                                .get_tuple_id(isl::dim::out)
455693ef999SMichael Kruse                                .get_user();
456693ef999SMichael Kruse         if (!TouchedAccesses.count(MA))
457d5ee355fSRiccardo Mori           NewFutureWrites = NewFutureWrites.unite(FutureWrite);
458a3387168STobias Grosser       }
459693ef999SMichael Kruse       FutureWrites = NewFutureWrites;
460ce9617f4SMichael Kruse 
461ce9617f4SMichael Kruse       if (MA->isMustWrite() && !ValSet.is_null()) {
462ce9617f4SMichael Kruse         // { MemoryAccess[] }
463ce9617f4SMichael Kruse         auto AccSet =
464ce9617f4SMichael Kruse             isl::set::universe(isl::space(S->getIslCtx(), 0, 0)
465ce9617f4SMichael Kruse                                    .set_tuple_id(isl::dim::set, MA->getId()));
466ce9617f4SMichael Kruse 
467ce9617f4SMichael Kruse         // { Val[] -> MemoryAccess[] }
468ce9617f4SMichael Kruse         isl::map ValAccSet = isl::map::from_domain_and_range(ValSet, AccSet);
469ce9617f4SMichael Kruse 
470ce9617f4SMichael Kruse         // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
471ce9617f4SMichael Kruse         isl::map AccRelValAcc =
472ce9617f4SMichael Kruse             isl::map::from_domain_and_range(AccRelWrapped, ValAccSet.wrap());
473d5ee355fSRiccardo Mori         FutureWrites = FutureWrites.unite(AccRelValAcc);
474ce9617f4SMichael Kruse       }
475ce9617f4SMichael Kruse     }
476ce9617f4SMichael Kruse   }
477ce9617f4SMichael Kruse }
478ce9617f4SMichael Kruse 
4790446d81eSMichael Kruse /// Remove writes that just write the same value already stored in the
4800446d81eSMichael Kruse /// element.
removeRedundantWrites()48123753c60SMichael Kruse void SimplifyImpl::removeRedundantWrites() {
4820446d81eSMichael Kruse   for (auto &Stmt : *S) {
483bc88a78cSMichael Kruse     SmallDenseMap<Value *, isl::set> ValueSets;
484bc88a78cSMichael Kruse     auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
485bc88a78cSMichael Kruse       assert(V);
486bc88a78cSMichael Kruse       isl::set &Result = ValueSets[V];
487bc88a78cSMichael Kruse       if (Result.is_null()) {
48800fd43b3SPhilip Pfaffe         isl_ctx *Ctx = S->getIslCtx().get();
489deb00cf0SPengxuan Zheng         std::string Name = getIslCompatibleName(
490deb00cf0SPengxuan Zheng             "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames);
491da3e8c4bSTobias Grosser         isl::id Id = isl::manage(isl_id_alloc(Ctx, Name.c_str(), V));
492bc88a78cSMichael Kruse         Result = isl::set::universe(
493bc88a78cSMichael Kruse             isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
4940446d81eSMichael Kruse       }
495bc88a78cSMichael Kruse       return Result;
496bc88a78cSMichael Kruse     };
4970446d81eSMichael Kruse 
498dcf8d696STobias Grosser     isl::set Domain = Stmt.getDomain();
499b65ccc43STobias Grosser     Domain = Domain.intersect_params(S->getContext());
5000446d81eSMichael Kruse 
501bc88a78cSMichael Kruse     // List of element reads that still have the same value while iterating
502bc88a78cSMichael Kruse     // through the MemoryAccesses.
503bc88a78cSMichael Kruse     // { [Domain[] -> Element[]] -> Val[] }
504bad3ebbaSRiccardo Mori     isl::union_map Known = isl::union_map::empty(S->getIslCtx());
5050446d81eSMichael Kruse 
506bc88a78cSMichael Kruse     SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
507bc88a78cSMichael Kruse     for (MemoryAccess *MA : Accesses) {
508bc88a78cSMichael Kruse       // Is the memory access in a defined order relative to the other
509bc88a78cSMichael Kruse       // accesses? In region statements, only the first and the last accesses
510bc88a78cSMichael Kruse       // have defined order. Execution of those in the middle may depend on
511bc88a78cSMichael Kruse       // runtime conditions an therefore cannot be modified.
512bc88a78cSMichael Kruse       bool IsOrdered =
513bc88a78cSMichael Kruse           Stmt.isBlockStmt() || MA->isOriginalScalarKind() ||
514bc88a78cSMichael Kruse           (!S->getBoxedLoops().size() && MA->getAccessInstruction() &&
515bc88a78cSMichael Kruse            Stmt.getEntryBlock() == MA->getAccessInstruction()->getParent());
5160446d81eSMichael Kruse 
517bc88a78cSMichael Kruse       isl::map AccRel = MA->getAccessRelation();
518bc88a78cSMichael Kruse       AccRel = AccRel.intersect_domain(Domain);
519bc88a78cSMichael Kruse       isl::set AccRelWrapped = AccRel.wrap();
520bc88a78cSMichael Kruse 
521bc88a78cSMichael Kruse       // Determine whether a write is redundant (stores only values that are
522bc88a78cSMichael Kruse       // already present in the written array elements) and remove it if this
523bc88a78cSMichael Kruse       // is the case.
524bc88a78cSMichael Kruse       if (IsOrdered && MA->isMustWrite() &&
525bc88a78cSMichael Kruse           (isa<StoreInst>(MA->getAccessInstruction()) ||
526bc88a78cSMichael Kruse            MA->isOriginalScalarKind())) {
527bc88a78cSMichael Kruse         Value *StoredVal = MA->tryGetValueStored();
528bc88a78cSMichael Kruse         if (!StoredVal)
529bc88a78cSMichael Kruse           StoredVal = MA->getAccessValue();
530bc88a78cSMichael Kruse 
531bc88a78cSMichael Kruse         if (StoredVal) {
532bc88a78cSMichael Kruse           // Lookup in the set of known values.
533bc88a78cSMichael Kruse           isl::map AccRelStoredVal = isl::map::from_domain_and_range(
534bc88a78cSMichael Kruse               AccRelWrapped, makeValueSet(StoredVal));
535bc88a78cSMichael Kruse           if (isl::union_map(AccRelStoredVal).is_subset(Known)) {
536*601d7eabSKarthika Devi C             POLLY_DEBUG(dbgs() << "Cleanup of " << MA << ":\n");
537*601d7eabSKarthika Devi C             POLLY_DEBUG(dbgs() << "      Scalar: " << *StoredVal << "\n");
538*601d7eabSKarthika Devi C             POLLY_DEBUG(dbgs() << "      AccRel: " << AccRel << "\n");
5390446d81eSMichael Kruse 
540bc88a78cSMichael Kruse             Stmt.removeSingleMemoryAccess(MA);
5410446d81eSMichael Kruse 
5420446d81eSMichael Kruse             RedundantWritesRemoved++;
54306ed5292SMichael Kruse             TotalRedundantWritesRemoved[CallNo]++;
5440446d81eSMichael Kruse           }
5450446d81eSMichael Kruse         }
546bc88a78cSMichael Kruse       }
547bc88a78cSMichael Kruse 
548bc88a78cSMichael Kruse       // Update the know values set.
549bc88a78cSMichael Kruse       if (MA->isRead()) {
550bc88a78cSMichael Kruse         // Loaded values are the currently known values of the array element
551bc88a78cSMichael Kruse         // it was loaded from.
552bc88a78cSMichael Kruse         Value *LoadedVal = MA->getAccessValue();
553bc88a78cSMichael Kruse         if (LoadedVal && IsOrdered) {
554bc88a78cSMichael Kruse           isl::map AccRelVal = isl::map::from_domain_and_range(
555bc88a78cSMichael Kruse               AccRelWrapped, makeValueSet(LoadedVal));
556bc88a78cSMichael Kruse 
557d5ee355fSRiccardo Mori           Known = Known.unite(AccRelVal);
558bc88a78cSMichael Kruse         }
559bc88a78cSMichael Kruse       } else if (MA->isWrite()) {
560bc88a78cSMichael Kruse         // Remove (possibly) overwritten values from the known elements set.
561bc88a78cSMichael Kruse         // We remove all elements of the accessed array to avoid too complex
562bc88a78cSMichael Kruse         // isl sets.
563bc88a78cSMichael Kruse         isl::set AccRelUniv = isl::set::universe(AccRelWrapped.get_space());
564bc88a78cSMichael Kruse         Known = Known.subtract_domain(AccRelUniv);
565bc88a78cSMichael Kruse 
566bc88a78cSMichael Kruse         // At this point, we could add the written value of must-writes.
567bc88a78cSMichael Kruse         // However, writing same values is already handled by
568bc88a78cSMichael Kruse         // coalesceWrites().
569bc88a78cSMichael Kruse       }
570bc88a78cSMichael Kruse     }
571bc88a78cSMichael Kruse   }
572bc88a78cSMichael Kruse }
5730446d81eSMichael Kruse 
5740446d81eSMichael Kruse /// Remove statements without side effects.
removeUnnecessaryStmts()57523753c60SMichael Kruse void SimplifyImpl::removeUnnecessaryStmts() {
5760446d81eSMichael Kruse   auto NumStmtsBefore = S->getSize();
5770446d81eSMichael Kruse   S->simplifySCoP(true);
5780446d81eSMichael Kruse   assert(NumStmtsBefore >= S->getSize());
5790446d81eSMichael Kruse   StmtsRemoved = NumStmtsBefore - S->getSize();
580*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore
5810446d81eSMichael Kruse                      << ") statements\n");
58206ed5292SMichael Kruse   TotalStmtsRemoved[CallNo] += StmtsRemoved;
5830446d81eSMichael Kruse }
5840446d81eSMichael Kruse 
585ab8f0d57SMichael Kruse /// Remove accesses that have an empty domain.
removeEmptyPartialAccesses()58623753c60SMichael Kruse void SimplifyImpl::removeEmptyPartialAccesses() {
587ab8f0d57SMichael Kruse   for (ScopStmt &Stmt : *S) {
588ab8f0d57SMichael Kruse     // Defer the actual removal to not invalidate iterators.
589ab8f0d57SMichael Kruse     SmallVector<MemoryAccess *, 8> DeferredRemove;
590ab8f0d57SMichael Kruse 
591ab8f0d57SMichael Kruse     for (MemoryAccess *MA : Stmt) {
592ab8f0d57SMichael Kruse       if (!MA->isWrite())
593ab8f0d57SMichael Kruse         continue;
594ab8f0d57SMichael Kruse 
595325812acSTobias Grosser       isl::map AccRel = MA->getAccessRelation();
596ab8f0d57SMichael Kruse       if (!AccRel.is_empty().is_true())
597ab8f0d57SMichael Kruse         continue;
598ab8f0d57SMichael Kruse 
599*601d7eabSKarthika Devi C       POLLY_DEBUG(
600349506a9SNicola Zaghen           dbgs() << "Removing " << MA
601ab8f0d57SMichael Kruse                  << " because it's a partial access that never occurs\n");
602ab8f0d57SMichael Kruse       DeferredRemove.push_back(MA);
603ab8f0d57SMichael Kruse     }
604ab8f0d57SMichael Kruse 
605ab8f0d57SMichael Kruse     for (MemoryAccess *MA : DeferredRemove) {
606ab8f0d57SMichael Kruse       Stmt.removeSingleMemoryAccess(MA);
607ab8f0d57SMichael Kruse       EmptyPartialAccessesRemoved++;
60806ed5292SMichael Kruse       TotalEmptyPartialAccessesRemoved[CallNo]++;
609ab8f0d57SMichael Kruse     }
610ab8f0d57SMichael Kruse   }
611ab8f0d57SMichael Kruse }
612ab8f0d57SMichael Kruse 
61322058c3fSMichael Kruse /// Mark all reachable instructions and access, and sweep those that are not
61422058c3fSMichael Kruse /// reachable.
markAndSweep(LoopInfo * LI)61523753c60SMichael Kruse void SimplifyImpl::markAndSweep(LoopInfo *LI) {
61622058c3fSMichael Kruse   DenseSet<MemoryAccess *> UsedMA;
61722058c3fSMichael Kruse   DenseSet<VirtualInstruction> UsedInsts;
61822058c3fSMichael Kruse 
61922058c3fSMichael Kruse   // Get all reachable instructions and accesses.
62022058c3fSMichael Kruse   markReachable(S, LI, UsedInsts, UsedMA);
62122058c3fSMichael Kruse 
62222058c3fSMichael Kruse   // Remove all non-reachable accesses.
62322058c3fSMichael Kruse   // We need get all MemoryAccesses first, in order to not invalidate the
62422058c3fSMichael Kruse   // iterators when removing them.
62522058c3fSMichael Kruse   SmallVector<MemoryAccess *, 64> AllMAs;
62622058c3fSMichael Kruse   for (ScopStmt &Stmt : *S)
62722058c3fSMichael Kruse     AllMAs.append(Stmt.begin(), Stmt.end());
62822058c3fSMichael Kruse 
62922058c3fSMichael Kruse   for (MemoryAccess *MA : AllMAs) {
63022058c3fSMichael Kruse     if (UsedMA.count(MA))
63122058c3fSMichael Kruse       continue;
632*601d7eabSKarthika Devi C     POLLY_DEBUG(dbgs() << "Removing " << MA
633349506a9SNicola Zaghen                        << " because its value is not used\n");
63422058c3fSMichael Kruse     ScopStmt *Stmt = MA->getStatement();
63522058c3fSMichael Kruse     Stmt->removeSingleMemoryAccess(MA);
63622058c3fSMichael Kruse 
63722058c3fSMichael Kruse     DeadAccessesRemoved++;
63806ed5292SMichael Kruse     TotalDeadAccessesRemoved[CallNo]++;
63922058c3fSMichael Kruse   }
64022058c3fSMichael Kruse 
64122058c3fSMichael Kruse   // Remove all non-reachable instructions.
64222058c3fSMichael Kruse   for (ScopStmt &Stmt : *S) {
643420c4863SMichael Kruse     // Note that for region statements, we can only remove the non-terminator
644420c4863SMichael Kruse     // instructions of the entry block. All other instructions are not in the
645420c4863SMichael Kruse     // instructions list, but implicitly always part of the statement.
646cedd7a74SMichael Kruse 
64722058c3fSMichael Kruse     SmallVector<Instruction *, 32> AllInsts(Stmt.insts_begin(),
64822058c3fSMichael Kruse                                             Stmt.insts_end());
64922058c3fSMichael Kruse     SmallVector<Instruction *, 32> RemainInsts;
65022058c3fSMichael Kruse 
65122058c3fSMichael Kruse     for (Instruction *Inst : AllInsts) {
65222058c3fSMichael Kruse       auto It = UsedInsts.find({&Stmt, Inst});
65322058c3fSMichael Kruse       if (It == UsedInsts.end()) {
654*601d7eabSKarthika Devi C         POLLY_DEBUG(dbgs() << "Removing "; Inst->print(dbgs());
65522058c3fSMichael Kruse                     dbgs() << " because it is not used\n");
65622058c3fSMichael Kruse         DeadInstructionsRemoved++;
65706ed5292SMichael Kruse         TotalDeadInstructionsRemoved[CallNo]++;
65822058c3fSMichael Kruse         continue;
65922058c3fSMichael Kruse       }
66022058c3fSMichael Kruse 
66122058c3fSMichael Kruse       RemainInsts.push_back(Inst);
66222058c3fSMichael Kruse 
66322058c3fSMichael Kruse       // If instructions appear multiple times, keep only the first.
66422058c3fSMichael Kruse       UsedInsts.erase(It);
66522058c3fSMichael Kruse     }
66622058c3fSMichael Kruse 
66722058c3fSMichael Kruse     // Set the new instruction list to be only those we did not remove.
66822058c3fSMichael Kruse     Stmt.setInstructions(RemainInsts);
66922058c3fSMichael Kruse   }
67022058c3fSMichael Kruse }
67122058c3fSMichael Kruse 
6720446d81eSMichael Kruse /// Print simplification statistics to @p OS.
printStatistics(llvm::raw_ostream & OS,int Indent) const67323753c60SMichael Kruse void SimplifyImpl::printStatistics(llvm::raw_ostream &OS, int Indent) const {
6740446d81eSMichael Kruse   OS.indent(Indent) << "Statistics {\n";
6756983741eSMichael Kruse   OS.indent(Indent + 4) << "Empty domains removed: " << EmptyDomainsRemoved
6766983741eSMichael Kruse                         << '\n';
677deb00cf0SPengxuan Zheng   OS.indent(Indent + 4) << "Overwrites removed: " << OverwritesRemoved << '\n';
678ce9617f4SMichael Kruse   OS.indent(Indent + 4) << "Partial writes coalesced: " << WritesCoalesced
679ce9617f4SMichael Kruse                         << "\n";
6800446d81eSMichael Kruse   OS.indent(Indent + 4) << "Redundant writes removed: "
6810446d81eSMichael Kruse                         << RedundantWritesRemoved << "\n";
6826c8f91b9SMichael Kruse   OS.indent(Indent + 4) << "Accesses with empty domains removed: "
683ab8f0d57SMichael Kruse                         << EmptyPartialAccessesRemoved << "\n";
68422058c3fSMichael Kruse   OS.indent(Indent + 4) << "Dead accesses removed: " << DeadAccessesRemoved
68522058c3fSMichael Kruse                         << '\n';
68622058c3fSMichael Kruse   OS.indent(Indent + 4) << "Dead instructions removed: "
68722058c3fSMichael Kruse                         << DeadInstructionsRemoved << '\n';
6880446d81eSMichael Kruse   OS.indent(Indent + 4) << "Stmts removed: " << StmtsRemoved << "\n";
6890446d81eSMichael Kruse   OS.indent(Indent) << "}\n";
6900446d81eSMichael Kruse }
6910446d81eSMichael Kruse 
6920446d81eSMichael Kruse /// Print the current state of all MemoryAccesses to @p OS.
printAccesses(llvm::raw_ostream & OS,int Indent) const69323753c60SMichael Kruse void SimplifyImpl::printAccesses(llvm::raw_ostream &OS, int Indent) const {
6940446d81eSMichael Kruse   OS.indent(Indent) << "After accesses {\n";
6950446d81eSMichael Kruse   for (auto &Stmt : *S) {
6960446d81eSMichael Kruse     OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
6970446d81eSMichael Kruse     for (auto *MA : Stmt)
6980446d81eSMichael Kruse       MA->print(OS);
6990446d81eSMichael Kruse   }
7000446d81eSMichael Kruse   OS.indent(Indent) << "}\n";
7010446d81eSMichael Kruse }
7020446d81eSMichael Kruse 
run(Scop & S,LoopInfo * LI)70323753c60SMichael Kruse void SimplifyImpl::run(Scop &S, LoopInfo *LI) {
70423753c60SMichael Kruse   // Must not have run before.
70523753c60SMichael Kruse   assert(!this->S);
706629f9185SMichael Kruse   assert(!isModified());
7070446d81eSMichael Kruse 
7080446d81eSMichael Kruse   // Prepare processing of this SCoP.
7090446d81eSMichael Kruse   this->S = &S;
71006ed5292SMichael Kruse   ScopsProcessed[CallNo]++;
7110446d81eSMichael Kruse 
712*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removing statements that are never executed...\n");
7136983741eSMichael Kruse   removeEmptyDomainStmts();
7146983741eSMichael Kruse 
715*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removing partial writes that never happen...\n");
71634a77780SMichael Kruse   removeEmptyPartialAccesses();
71734a77780SMichael Kruse 
718*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removing overwrites...\n");
719f263610bSMichael Kruse   removeOverwrites();
720f263610bSMichael Kruse 
721*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Coalesce partial writes...\n");
722ce9617f4SMichael Kruse   coalesceWrites();
723ce9617f4SMichael Kruse 
724*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removing redundant writes...\n");
7250446d81eSMichael Kruse   removeRedundantWrites();
7260446d81eSMichael Kruse 
727*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Cleanup unused accesses...\n");
72822058c3fSMichael Kruse   markAndSweep(LI);
72922058c3fSMichael Kruse 
730*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Removing statements without side effects...\n");
7318e1280b8STobias Grosser   removeUnnecessaryStmts();
7320446d81eSMichael Kruse 
7330446d81eSMichael Kruse   if (isModified())
73406ed5292SMichael Kruse     ScopsModified[CallNo]++;
735*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "\nFinal Scop:\n");
736*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << S);
7370446d81eSMichael Kruse 
73806ed5292SMichael Kruse   auto ScopStats = S.getStatistics();
73906ed5292SMichael Kruse   NumValueWrites[CallNo] += ScopStats.NumValueWrites;
74006ed5292SMichael Kruse   NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops;
74106ed5292SMichael Kruse   NumPHIWrites[CallNo] += ScopStats.NumPHIWrites;
74206ed5292SMichael Kruse   NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops;
74306ed5292SMichael Kruse   NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites;
74406ed5292SMichael Kruse   NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops;
7450446d81eSMichael Kruse }
7460446d81eSMichael Kruse 
printScop(raw_ostream & OS,Scop & S) const74723753c60SMichael Kruse void SimplifyImpl::printScop(raw_ostream &OS, Scop &S) const {
7480446d81eSMichael Kruse   assert(&S == this->S &&
7490446d81eSMichael Kruse          "Can only print analysis for the last processed SCoP");
7500446d81eSMichael Kruse   printStatistics(OS);
7510446d81eSMichael Kruse 
7520446d81eSMichael Kruse   if (!isModified()) {
7530446d81eSMichael Kruse     OS << "SCoP could not be simplified\n";
7540446d81eSMichael Kruse     return;
7550446d81eSMichael Kruse   }
7560446d81eSMichael Kruse   printAccesses(OS);
7570446d81eSMichael Kruse }
7580446d81eSMichael Kruse 
759bd93df93SMichael Kruse class SimplifyWrapperPass final : public ScopPass {
760deb00cf0SPengxuan Zheng public:
761deb00cf0SPengxuan Zheng   static char ID;
76223753c60SMichael Kruse   int CallNo;
763ccdc271aSKazu Hirata   std::optional<SimplifyImpl> Impl;
764deb00cf0SPengxuan Zheng 
SimplifyWrapperPass(int CallNo=0)76523753c60SMichael Kruse   explicit SimplifyWrapperPass(int CallNo = 0) : ScopPass(ID), CallNo(CallNo) {}
766deb00cf0SPengxuan Zheng 
getAnalysisUsage(AnalysisUsage & AU) const7673f3930a4SKazu Hirata   void getAnalysisUsage(AnalysisUsage &AU) const override {
768deb00cf0SPengxuan Zheng     AU.addRequiredTransitive<ScopInfoRegionPass>();
769deb00cf0SPengxuan Zheng     AU.addRequired<LoopInfoWrapperPass>();
770deb00cf0SPengxuan Zheng     AU.setPreservesAll();
771deb00cf0SPengxuan Zheng   }
772deb00cf0SPengxuan Zheng 
runOnScop(Scop & S)7733f3930a4SKazu Hirata   bool runOnScop(Scop &S) override {
77423753c60SMichael Kruse     LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
77523753c60SMichael Kruse 
77623753c60SMichael Kruse     Impl.emplace(CallNo);
77723753c60SMichael Kruse     Impl->run(S, LI);
77823753c60SMichael Kruse 
77923753c60SMichael Kruse     return false;
780deb00cf0SPengxuan Zheng   }
781deb00cf0SPengxuan Zheng 
printScop(raw_ostream & OS,Scop & S) const7823f3930a4SKazu Hirata   void printScop(raw_ostream &OS, Scop &S) const override {
78323753c60SMichael Kruse     if (Impl)
78423753c60SMichael Kruse       Impl->printScop(OS, S);
785deb00cf0SPengxuan Zheng   }
786deb00cf0SPengxuan Zheng 
releaseMemory()7873f3930a4SKazu Hirata   void releaseMemory() override { Impl.reset(); }
7880446d81eSMichael Kruse };
7890446d81eSMichael Kruse 
79013f758a8SMichael Kruse char SimplifyWrapperPass::ID;
7910446d81eSMichael Kruse 
79223753c60SMichael Kruse static llvm::PreservedAnalyses
runSimplifyUsingNPM(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U,int CallNo,raw_ostream * OS)79323753c60SMichael Kruse runSimplifyUsingNPM(Scop &S, ScopAnalysisManager &SAM,
79423753c60SMichael Kruse                     ScopStandardAnalysisResults &SAR, SPMUpdater &U, int CallNo,
79523753c60SMichael Kruse                     raw_ostream *OS) {
79623753c60SMichael Kruse   SimplifyImpl Impl(CallNo);
79723753c60SMichael Kruse   Impl.run(S, &SAR.LI);
79823753c60SMichael Kruse   if (OS) {
79923753c60SMichael Kruse     *OS << "Printing analysis 'Polly - Simplify' for region: '" << S.getName()
80023753c60SMichael Kruse         << "' in function '" << S.getFunction().getName() << "':\n";
80123753c60SMichael Kruse     Impl.printScop(*OS, S);
80223753c60SMichael Kruse   }
80323753c60SMichael Kruse 
80423753c60SMichael Kruse   if (!Impl.isModified())
805deb00cf0SPengxuan Zheng     return llvm::PreservedAnalyses::all();
806deb00cf0SPengxuan Zheng 
80713f758a8SMichael Kruse   PreservedAnalyses PA;
80813f758a8SMichael Kruse   PA.preserveSet<AllAnalysesOn<Module>>();
80913f758a8SMichael Kruse   PA.preserveSet<AllAnalysesOn<Function>>();
81013f758a8SMichael Kruse   PA.preserveSet<AllAnalysesOn<Loop>>();
81113f758a8SMichael Kruse   return PA;
812deb00cf0SPengxuan Zheng }
813deb00cf0SPengxuan Zheng 
81423753c60SMichael Kruse } // anonymous namespace
81523753c60SMichael Kruse 
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)81623753c60SMichael Kruse llvm::PreservedAnalyses SimplifyPass::run(Scop &S, ScopAnalysisManager &SAM,
81723753c60SMichael Kruse                                           ScopStandardAnalysisResults &SAR,
81823753c60SMichael Kruse                                           SPMUpdater &U) {
81923753c60SMichael Kruse   return runSimplifyUsingNPM(S, SAM, SAR, U, CallNo, nullptr);
82023753c60SMichael Kruse }
82123753c60SMichael Kruse 
822deb00cf0SPengxuan Zheng llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)823deb00cf0SPengxuan Zheng SimplifyPrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
824deb00cf0SPengxuan Zheng                          ScopStandardAnalysisResults &SAR, SPMUpdater &U) {
82523753c60SMichael Kruse   return runSimplifyUsingNPM(S, SAM, SAR, U, CallNo, &OS);
826deb00cf0SPengxuan Zheng }
827deb00cf0SPengxuan Zheng 
getAccessesInOrder(ScopStmt & Stmt)82823753c60SMichael Kruse SmallVector<MemoryAccess *, 32> polly::getAccessesInOrder(ScopStmt &Stmt) {
829327e9ecbSTobias Grosser   SmallVector<MemoryAccess *, 32> Accesses;
830327e9ecbSTobias Grosser 
831327e9ecbSTobias Grosser   for (MemoryAccess *MemAcc : Stmt)
832327e9ecbSTobias Grosser     if (isImplicitRead(MemAcc))
833327e9ecbSTobias Grosser       Accesses.push_back(MemAcc);
834327e9ecbSTobias Grosser 
835327e9ecbSTobias Grosser   for (MemoryAccess *MemAcc : Stmt)
836327e9ecbSTobias Grosser     if (isExplicitAccess(MemAcc))
837327e9ecbSTobias Grosser       Accesses.push_back(MemAcc);
838327e9ecbSTobias Grosser 
839327e9ecbSTobias Grosser   for (MemoryAccess *MemAcc : Stmt)
840327e9ecbSTobias Grosser     if (isImplicitWrite(MemAcc))
841327e9ecbSTobias Grosser       Accesses.push_back(MemAcc);
842327e9ecbSTobias Grosser 
843327e9ecbSTobias Grosser   return Accesses;
844327e9ecbSTobias Grosser }
845327e9ecbSTobias Grosser 
createSimplifyWrapperPass(int CallNo)84613f758a8SMichael Kruse Pass *polly::createSimplifyWrapperPass(int CallNo) {
84713f758a8SMichael Kruse   return new SimplifyWrapperPass(CallNo);
848deb00cf0SPengxuan Zheng }
8490446d81eSMichael Kruse 
85013f758a8SMichael Kruse INITIALIZE_PASS_BEGIN(SimplifyWrapperPass, "polly-simplify", "Polly - Simplify",
851deb00cf0SPengxuan Zheng                       false, false)
85222058c3fSMichael Kruse INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
85313f758a8SMichael Kruse INITIALIZE_PASS_END(SimplifyWrapperPass, "polly-simplify", "Polly - Simplify",
854deb00cf0SPengxuan Zheng                     false, false)
8555c028081SMichael Kruse 
8565c028081SMichael Kruse //===----------------------------------------------------------------------===//
8575c028081SMichael Kruse 
8585c028081SMichael Kruse namespace {
8595c028081SMichael Kruse /// Print result from SimplifyWrapperPass.
860bd93df93SMichael Kruse class SimplifyPrinterLegacyPass final : public ScopPass {
8615c028081SMichael Kruse public:
8625c028081SMichael Kruse   static char ID;
8635c028081SMichael Kruse 
SimplifyPrinterLegacyPass()8645c028081SMichael Kruse   SimplifyPrinterLegacyPass() : SimplifyPrinterLegacyPass(outs()) {}
SimplifyPrinterLegacyPass(llvm::raw_ostream & OS)8655c028081SMichael Kruse   explicit SimplifyPrinterLegacyPass(llvm::raw_ostream &OS)
8665c028081SMichael Kruse       : ScopPass(ID), OS(OS) {}
8675c028081SMichael Kruse 
runOnScop(Scop & S)8685c028081SMichael Kruse   bool runOnScop(Scop &S) override {
8695c028081SMichael Kruse     SimplifyWrapperPass &P = getAnalysis<SimplifyWrapperPass>();
8705c028081SMichael Kruse 
8715c028081SMichael Kruse     OS << "Printing analysis '" << P.getPassName() << "' for region: '"
8725c028081SMichael Kruse        << S.getRegion().getNameStr() << "' in function '"
8735c028081SMichael Kruse        << S.getFunction().getName() << "':\n";
8745c028081SMichael Kruse     P.printScop(OS, S);
8755c028081SMichael Kruse 
8765c028081SMichael Kruse     return false;
8775c028081SMichael Kruse   }
8785c028081SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const8795c028081SMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
8805c028081SMichael Kruse     ScopPass::getAnalysisUsage(AU);
8815c028081SMichael Kruse     AU.addRequired<SimplifyWrapperPass>();
8825c028081SMichael Kruse     AU.setPreservesAll();
8835c028081SMichael Kruse   }
8845c028081SMichael Kruse 
8855c028081SMichael Kruse private:
8865c028081SMichael Kruse   llvm::raw_ostream &OS;
8875c028081SMichael Kruse };
8885c028081SMichael Kruse 
8895c028081SMichael Kruse char SimplifyPrinterLegacyPass::ID = 0;
8905c028081SMichael Kruse } // namespace
8915c028081SMichael Kruse 
createSimplifyPrinterLegacyPass(raw_ostream & OS)8925c028081SMichael Kruse Pass *polly::createSimplifyPrinterLegacyPass(raw_ostream &OS) {
8935c028081SMichael Kruse   return new SimplifyPrinterLegacyPass(OS);
8945c028081SMichael Kruse }
8955c028081SMichael Kruse 
8965c028081SMichael Kruse INITIALIZE_PASS_BEGIN(SimplifyPrinterLegacyPass, "polly-print-simplify",
8975c028081SMichael Kruse                       "Polly - Print Simplify actions", false, false)
8985c028081SMichael Kruse INITIALIZE_PASS_DEPENDENCY(SimplifyWrapperPass)
8995c028081SMichael Kruse INITIALIZE_PASS_END(SimplifyPrinterLegacyPass, "polly-print-simplify",
9005c028081SMichael Kruse                     "Polly - Print Simplify actions", false, false)
901