xref: /llvm-project/polly/lib/Support/VirtualInstruction.cpp (revision 716360367fbdabac2c374c19b8746f4de49a5599)
1 //===------ VirtualInstruction.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 // Tools for determining which instructions are within a statement and the
10 // nature of their operands.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "polly/Support/VirtualInstruction.h"
15 
16 using namespace polly;
17 using namespace llvm;
18 
19 VirtualUse VirtualUse::create(Scop *S, const Use &U, LoopInfo *LI,
20                               bool Virtual) {
21   auto *UserBB = getUseBlock(U);
22   Loop *UserScope = LI->getLoopFor(UserBB);
23   Instruction *UI = dyn_cast<Instruction>(U.getUser());
24   ScopStmt *UserStmt = S->getStmtFor(UI);
25 
26   // Uses by PHI nodes are always reading values written by other statements,
27   // except it is within a region statement.
28   if (PHINode *PHI = dyn_cast<PHINode>(UI)) {
29     // Handle PHI in exit block.
30     if (S->getRegion().getExit() == PHI->getParent())
31       return VirtualUse(UserStmt, U.get(), Inter, nullptr, nullptr);
32 
33     if (UserStmt->getEntryBlock() != PHI->getParent())
34       return VirtualUse(UserStmt, U.get(), Intra, nullptr, nullptr);
35 
36     // The MemoryAccess is expected to be set if @p Virtual is true.
37     MemoryAccess *IncomingMA = nullptr;
38     if (Virtual) {
39       if (const ScopArrayInfo *SAI =
40               S->getScopArrayInfoOrNull(PHI, MemoryKind::PHI)) {
41         IncomingMA = S->getPHIRead(SAI);
42         assert(IncomingMA->getStatement() == UserStmt);
43       }
44     }
45 
46     return VirtualUse(UserStmt, U.get(), Inter, nullptr, IncomingMA);
47   }
48 
49   return create(S, UserStmt, UserScope, U.get(), Virtual);
50 }
51 
52 VirtualUse VirtualUse::create(Scop *S, ScopStmt *UserStmt, Loop *UserScope,
53                               Value *Val, bool Virtual) {
54   assert(!isa<StoreInst>(Val) && "a StoreInst cannot be used");
55 
56   if (isa<BasicBlock>(Val))
57     return VirtualUse(UserStmt, Val, Block, nullptr, nullptr);
58 
59   if (isa<llvm::Constant>(Val) || isa<MetadataAsValue>(Val) ||
60       isa<InlineAsm>(Val))
61     return VirtualUse(UserStmt, Val, Constant, nullptr, nullptr);
62 
63   // Is the value synthesizable? If the user has been pruned
64   // (UserStmt == nullptr), it is either not used anywhere or is synthesizable.
65   // We assume synthesizable which practically should have the same effect.
66   auto *SE = S->getSE();
67   if (SE->isSCEVable(Val->getType())) {
68     const SCEV *ScevExpr = SE->getSCEVAtScope(Val, UserScope);
69     if (!UserStmt || canSynthesize(Val, *UserStmt->getParent(), SE, UserScope))
70       return VirtualUse(UserStmt, Val, Synthesizable, ScevExpr, nullptr);
71   }
72 
73   // FIXME: Inconsistency between lookupInvariantEquivClass and
74   // getRequiredInvariantLoads. Querying one of them should be enough.
75   auto &RIL = S->getRequiredInvariantLoads();
76   if (S->lookupInvariantEquivClass(Val) || RIL.count(dyn_cast<LoadInst>(Val)))
77     return VirtualUse(UserStmt, Val, Hoisted, nullptr, nullptr);
78 
79   // ReadOnly uses may have MemoryAccesses that we want to associate with the
80   // use. This is why we look for a MemoryAccess here already.
81   MemoryAccess *InputMA = nullptr;
82   if (UserStmt && Virtual)
83     InputMA = UserStmt->lookupValueReadOf(Val);
84 
85   // Uses are read-only if they have been defined before the SCoP, i.e., they
86   // cannot be written to inside the SCoP. Arguments are defined before any
87   // instructions, hence also before the SCoP. If the user has been pruned
88   // (UserStmt == nullptr) and is not SCEVable, assume it is read-only as it is
89   // neither an intra- nor an inter-use.
90   if (!UserStmt || isa<Argument>(Val))
91     return VirtualUse(UserStmt, Val, ReadOnly, nullptr, InputMA);
92 
93   auto Inst = cast<Instruction>(Val);
94   if (!S->contains(Inst))
95     return VirtualUse(UserStmt, Val, ReadOnly, nullptr, InputMA);
96 
97   // A use is inter-statement if either it is defined in another statement, or
98   // there is a MemoryAccess that reads its value that has been written by
99   // another statement.
100   if (InputMA || (!Virtual && UserStmt != S->getStmtFor(Inst)))
101     return VirtualUse(UserStmt, Val, Inter, nullptr, InputMA);
102 
103   return VirtualUse(UserStmt, Val, Intra, nullptr, nullptr);
104 }
105 
106 void VirtualUse::print(raw_ostream &OS, bool Reproducible) const {
107   OS << "User: [" << User->getBaseName() << "] ";
108   switch (Kind) {
109   case VirtualUse::Constant:
110     OS << "Constant Op:";
111     break;
112   case VirtualUse::Block:
113     OS << "BasicBlock Op:";
114     break;
115   case VirtualUse::Synthesizable:
116     OS << "Synthesizable Op:";
117     break;
118   case VirtualUse::Hoisted:
119     OS << "Hoisted load Op:";
120     break;
121   case VirtualUse::ReadOnly:
122     OS << "Read-Only Op:";
123     break;
124   case VirtualUse::Intra:
125     OS << "Intra Op:";
126     break;
127   case VirtualUse::Inter:
128     OS << "Inter Op:";
129     break;
130   }
131 
132   if (Val) {
133     OS << ' ';
134     if (Reproducible)
135       OS << '"' << Val->getName() << '"';
136     else
137       Val->print(OS, true);
138   }
139   if (ScevExpr) {
140     OS << ' ';
141     ScevExpr->print(OS);
142   }
143   if (InputMA && !Reproducible)
144     OS << ' ' << InputMA;
145 }
146 
147 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
148 LLVM_DUMP_METHOD void VirtualUse::dump() const {
149   print(errs(), false);
150   errs() << '\n';
151 }
152 #endif
153 
154 void VirtualInstruction::print(raw_ostream &OS, bool Reproducible) const {
155   if (!Stmt || !Inst) {
156     OS << "[null VirtualInstruction]";
157     return;
158   }
159 
160   OS << "[" << Stmt->getBaseName() << "]";
161   Inst->print(OS, !Reproducible);
162 }
163 
164 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
165 LLVM_DUMP_METHOD void VirtualInstruction::dump() const {
166   print(errs(), false);
167   errs() << '\n';
168 }
169 #endif
170 
171 /// Return true if @p Inst cannot be removed, even if it is nowhere referenced.
172 static bool isRoot(const Instruction *Inst) {
173   // The store is handled by its MemoryAccess. The load must be reached from the
174   // roots in order to be marked as used.
175   if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
176     return false;
177 
178   // Terminator instructions (in region statements) are required for control
179   // flow.
180   if (Inst->isTerminator())
181     return true;
182 
183   // Writes to memory must be honored.
184   if (Inst->mayWriteToMemory())
185     return true;
186 
187   return false;
188 }
189 
190 /// Return true for MemoryAccesses that cannot be removed because it represents
191 /// an llvm::Value that is used after the SCoP.
192 static bool isEscaping(MemoryAccess *MA) {
193   assert(MA->isOriginalValueKind());
194   Scop *S = MA->getStatement()->getParent();
195   return S->isEscaping(cast<Instruction>(MA->getAccessValue()));
196 }
197 
198 /// Add non-removable virtual instructions in @p Stmt to @p RootInsts.
199 static void
200 addInstructionRoots(ScopStmt *Stmt,
201                     SmallVectorImpl<VirtualInstruction> &RootInsts) {
202   if (!Stmt->isBlockStmt()) {
203     // In region statements the terminator statement and all statements that
204     // are not in the entry block cannot be eliminated and consequently must
205     // be roots.
206     RootInsts.emplace_back(Stmt,
207                            Stmt->getRegion()->getEntry()->getTerminator());
208     for (BasicBlock *BB : Stmt->getRegion()->blocks())
209       if (Stmt->getRegion()->getEntry() != BB)
210         for (Instruction &Inst : *BB)
211           RootInsts.emplace_back(Stmt, &Inst);
212     return;
213   }
214 
215   for (Instruction *Inst : Stmt->getInstructions())
216     if (isRoot(Inst))
217       RootInsts.emplace_back(Stmt, Inst);
218 }
219 
220 /// Add non-removable memory accesses in @p Stmt to @p RootInsts.
221 ///
222 /// @param Local If true, all writes are assumed to escape. markAndSweep
223 /// algorithms can use this to be applicable to a single ScopStmt only without
224 /// the risk of removing definitions required by other statements.
225 ///              If false, only writes for SCoP-escaping values are roots.  This
226 ///              is global mode, where such writes must be marked by theirs uses
227 ///              in order to be reachable.
228 static void addAccessRoots(ScopStmt *Stmt,
229                            SmallVectorImpl<MemoryAccess *> &RootAccs,
230                            bool Local) {
231   for (auto *MA : *Stmt) {
232     if (!MA->isWrite())
233       continue;
234 
235     // Writes to arrays are always used.
236     if (MA->isLatestArrayKind())
237       RootAccs.push_back(MA);
238 
239     // Values are roots if they are escaping.
240     else if (MA->isLatestValueKind()) {
241       if (Local || isEscaping(MA))
242         RootAccs.push_back(MA);
243     }
244 
245     // Exit phis are, by definition, escaping.
246     else if (MA->isLatestExitPHIKind())
247       RootAccs.push_back(MA);
248 
249     // phi writes are only roots if we are not visiting the statement
250     // containing the PHINode.
251     else if (Local && MA->isLatestPHIKind())
252       RootAccs.push_back(MA);
253   }
254 }
255 
256 /// Determine all instruction and access roots.
257 static void addRoots(ScopStmt *Stmt,
258                      SmallVectorImpl<VirtualInstruction> &RootInsts,
259                      SmallVectorImpl<MemoryAccess *> &RootAccs, bool Local) {
260   addInstructionRoots(Stmt, RootInsts);
261   addAccessRoots(Stmt, RootAccs, Local);
262 }
263 
264 /// Mark accesses and instructions as used if they are reachable from a root,
265 /// walking the operand trees.
266 ///
267 /// @param S              The SCoP to walk.
268 /// @param LI             The LoopInfo Analysis.
269 /// @param RootInsts      List of root instructions.
270 /// @param RootAccs       List of root accesses.
271 /// @param UsesInsts[out] Receives all reachable instructions, including the
272 /// roots.
273 /// @param UsedAccs[out]  Receives all reachable accesses, including the roots.
274 /// @param OnlyLocal      If non-nullptr, restricts walking to a single
275 /// statement.
276 static void walkReachable(Scop *S, LoopInfo *LI,
277                           ArrayRef<VirtualInstruction> RootInsts,
278                           ArrayRef<MemoryAccess *> RootAccs,
279                           DenseSet<VirtualInstruction> &UsedInsts,
280                           DenseSet<MemoryAccess *> &UsedAccs,
281                           ScopStmt *OnlyLocal = nullptr) {
282   UsedInsts.clear();
283   UsedAccs.clear();
284 
285   SmallVector<VirtualInstruction, 32> WorklistInsts;
286   SmallVector<MemoryAccess *, 32> WorklistAccs;
287 
288   WorklistInsts.append(RootInsts.begin(), RootInsts.end());
289   WorklistAccs.append(RootAccs.begin(), RootAccs.end());
290 
291   auto AddToWorklist = [&](VirtualUse VUse) {
292     switch (VUse.getKind()) {
293     case VirtualUse::Block:
294     case VirtualUse::Constant:
295     case VirtualUse::Synthesizable:
296     case VirtualUse::Hoisted:
297       break;
298     case VirtualUse::ReadOnly:
299       // Read-only scalars only have MemoryAccesses if ModelReadOnlyScalars is
300       // enabled.
301       if (!VUse.getMemoryAccess())
302         break;
303       [[fallthrough]];
304     case VirtualUse::Inter:
305       assert(VUse.getMemoryAccess());
306       WorklistAccs.push_back(VUse.getMemoryAccess());
307       break;
308     case VirtualUse::Intra:
309       WorklistInsts.emplace_back(VUse.getUser(),
310                                  cast<Instruction>(VUse.getValue()));
311       break;
312     }
313   };
314 
315   while (true) {
316     // We have two worklists to process: Only when the MemoryAccess worklist is
317     // empty, we process the instruction worklist.
318 
319     while (!WorklistAccs.empty()) {
320       auto *Acc = WorklistAccs.pop_back_val();
321 
322       ScopStmt *Stmt = Acc->getStatement();
323       if (OnlyLocal && Stmt != OnlyLocal)
324         continue;
325 
326       auto Inserted = UsedAccs.insert(Acc);
327       if (!Inserted.second)
328         continue;
329 
330       if (Acc->isRead()) {
331         const ScopArrayInfo *SAI = Acc->getScopArrayInfo();
332 
333         if (Acc->isLatestValueKind()) {
334           MemoryAccess *DefAcc = S->getValueDef(SAI);
335 
336           // Accesses to read-only values do not have a definition.
337           if (DefAcc)
338             WorklistAccs.push_back(S->getValueDef(SAI));
339         }
340 
341         if (Acc->isLatestAnyPHIKind()) {
342           auto IncomingMAs = S->getPHIIncomings(SAI);
343           WorklistAccs.append(IncomingMAs.begin(), IncomingMAs.end());
344         }
345       }
346 
347       if (Acc->isWrite()) {
348         if (Acc->isOriginalValueKind() ||
349             (Acc->isOriginalArrayKind() && Acc->getAccessValue())) {
350           Loop *Scope = Stmt->getSurroundingLoop();
351           VirtualUse VUse =
352               VirtualUse::create(S, Stmt, Scope, Acc->getAccessValue(), true);
353           AddToWorklist(VUse);
354         }
355 
356         if (Acc->isOriginalAnyPHIKind()) {
357           for (auto Incoming : Acc->getIncoming()) {
358             VirtualUse VUse = VirtualUse::create(
359                 S, Stmt, LI->getLoopFor(Incoming.first), Incoming.second, true);
360             AddToWorklist(VUse);
361           }
362         }
363 
364         if (Acc->isOriginalArrayKind())
365           WorklistInsts.emplace_back(Stmt, Acc->getAccessInstruction());
366       }
367     }
368 
369     // If both worklists are empty, stop walking.
370     if (WorklistInsts.empty())
371       break;
372 
373     VirtualInstruction VInst = WorklistInsts.pop_back_val();
374     ScopStmt *Stmt = VInst.getStmt();
375     Instruction *Inst = VInst.getInstruction();
376 
377     // Do not process statements other than the local.
378     if (OnlyLocal && Stmt != OnlyLocal)
379       continue;
380 
381     auto InsertResult = UsedInsts.insert(VInst);
382     if (!InsertResult.second)
383       continue;
384 
385     // Add all operands to the worklists.
386     PHINode *PHI = dyn_cast<PHINode>(Inst);
387     if (PHI && PHI->getParent() == Stmt->getEntryBlock()) {
388       if (MemoryAccess *PHIRead = Stmt->lookupPHIReadOf(PHI))
389         WorklistAccs.push_back(PHIRead);
390     } else {
391       for (VirtualUse VUse : VInst.operands())
392         AddToWorklist(VUse);
393     }
394 
395     // If there is an array access, also add its MemoryAccesses to the worklist.
396     const MemoryAccessList *Accs = Stmt->lookupArrayAccessesFor(Inst);
397     if (!Accs)
398       continue;
399 
400     for (MemoryAccess *Acc : *Accs)
401       WorklistAccs.push_back(Acc);
402   }
403 }
404 
405 void polly::markReachable(Scop *S, LoopInfo *LI,
406                           DenseSet<VirtualInstruction> &UsedInsts,
407                           DenseSet<MemoryAccess *> &UsedAccs,
408                           ScopStmt *OnlyLocal) {
409   SmallVector<VirtualInstruction, 32> RootInsts;
410   SmallVector<MemoryAccess *, 32> RootAccs;
411 
412   if (OnlyLocal) {
413     addRoots(OnlyLocal, RootInsts, RootAccs, true);
414   } else {
415     for (auto &Stmt : *S)
416       addRoots(&Stmt, RootInsts, RootAccs, false);
417   }
418 
419   walkReachable(S, LI, RootInsts, RootAccs, UsedInsts, UsedAccs, OnlyLocal);
420 }
421