1 //===------ ForwardOpTree.h -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Move instructions between statements.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "polly/ForwardOpTree.h"
15 
16 #include "polly/ScopBuilder.h"
17 #include "polly/ScopInfo.h"
18 #include "polly/ScopPass.h"
19 #include "polly/Support/GICHelper.h"
20 #include "polly/Support/VirtualInstruction.h"
21 #include "llvm/Analysis/ValueTracking.h"
22 
23 #define DEBUG_TYPE "polly-delicm"
24 
25 using namespace polly;
26 using namespace llvm;
27 
28 STATISTIC(TotalInstructionsCopied, "Number of copied instructions");
29 STATISTIC(TotalReadOnlyCopied, "Number of copied read-only accesses");
30 STATISTIC(TotalForwardedTrees, "Number of forwarded operand trees");
31 STATISTIC(TotalModifiedStmts,
32           "Number of statements with at least one forwarded tree");
33 
34 STATISTIC(ScopsModified, "Number of SCoPs with at least one forwarded tree");
35 
36 namespace {
37 
38 /// The state of whether an operand tree was/can be forwarded.
39 ///
40 /// The items apply to an instructions and its operand tree with the instruction
41 /// as the root element. If the value in question is not an instruction in the
42 /// SCoP, it can be a leaf of an instruction's operand tree.
43 enum ForwardingDecision {
44   /// The root instruction or value cannot be forwarded at all.
45   FD_CannotForward,
46 
47   /// The root instruction or value can be forwarded as a leaf of a larger
48   /// operand tree.
49   /// It does not make sense to move the value itself, it would just replace it
50   /// by a use of itself. For instance, a constant "5" used in a statement can
51   /// be forwarded, but it would just replace it by the same constant "5".
52   /// However, it makes sense to move as an operand of
53   ///
54   ///   %add = add 5, 5
55   ///
56   /// where "5" is moved as part of a larger operand tree. "5" would be placed
57   /// (disregarding for a moment that literal constants don't have a location
58   /// and can be used anywhere) into the same statement as %add would.
59   FD_CanForwardLeaf,
60 
61   /// The root instruction can be forwarded in a non-trivial way. This requires
62   /// the operand tree root to be an instruction in some statement.
63   FD_CanForwardTree,
64 
65   /// Used to indicate that a forwarding has be carried out successfully.
66   FD_DidForward,
67 };
68 
69 /// Implementation of operand tree forwarding for a specific SCoP.
70 ///
71 /// For a statement that requires a scalar value (through a value read
72 /// MemoryAccess), see if its operand can be moved into the statement. If so,
73 /// the MemoryAccess is removed and the all the operand tree instructions are
74 /// moved into the statement. All original instructions are left in the source
75 /// statements. The simplification pass can clean these up.
76 class ForwardOpTreeImpl {
77 private:
78   /// The SCoP we are currently processing.
79   Scop *S;
80 
81   /// LoopInfo is required for VirtualUse.
82   LoopInfo *LI;
83 
84   /// How many instructions have been copied to other statements.
85   int NumInstructionsCopied = 0;
86 
87   /// How many read-only accesses have been copied.
88   int NumReadOnlyCopied = 0;
89 
90   /// How many operand trees have been forwarded.
91   int NumForwardedTrees = 0;
92 
93   /// Number of statements with at least one forwarded operand tree.
94   int NumModifiedStmts = 0;
95 
96   /// Whether we carried out at least one change to the SCoP.
97   bool Modified = false;
98 
99   void printStatistics(raw_ostream &OS, int Indent = 0) {
100     OS.indent(Indent) << "Statistics {\n";
101     OS.indent(Indent + 4) << "Instructions copied: " << NumInstructionsCopied
102                           << '\n';
103     OS.indent(Indent + 4) << "Read-only accesses copied: " << NumReadOnlyCopied
104                           << '\n';
105     OS.indent(Indent + 4) << "Operand trees forwarded: " << NumForwardedTrees
106                           << '\n';
107     OS.indent(Indent + 4) << "Statements with forwarded operand trees: "
108                           << NumModifiedStmts << '\n';
109     OS.indent(Indent) << "}\n";
110   }
111 
112   void printStatements(llvm::raw_ostream &OS, int Indent = 0) const {
113     OS.indent(Indent) << "After statements {\n";
114     for (auto &Stmt : *S) {
115       OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
116       for (auto *MA : Stmt)
117         MA->print(OS);
118 
119       OS.indent(Indent + 12);
120       Stmt.printInstructions(OS);
121     }
122     OS.indent(Indent) << "}\n";
123   }
124 
125   /// Determines whether an operand tree can be forwarded or carries out a
126   /// forwarding, depending on the @p DoIt flag.
127   ///
128   /// @param TargetStmt The statement the operand tree will be copied to.
129   /// @param UseVal     The value (usually an instruction) which is root of an
130   ///                   operand tree.
131   /// @param UseStmt    The statement that uses @p UseVal.
132   /// @param UseLoop    The loop @p UseVal is used in.
133   /// @param DoIt       If false, only determine whether an operand tree can be
134   ///                   forwarded. If true, carry out the forwarding. Do not use
135   ///                   DoIt==true if an operand tree is not known to be
136   ///                   forwardable.
137   ///
138   /// @return If DoIt==false, return whether the operand tree can be forwarded.
139   ///         If DoIt==true, return FD_DidForward.
140   ForwardingDecision canForwardTree(ScopStmt *TargetStmt, Value *UseVal,
141                                     ScopStmt *UseStmt, Loop *UseLoop,
142                                     bool DoIt) {
143 
144     // PHis are not yet supported.
145     if (isa<PHINode>(UseVal)) {
146       DEBUG(dbgs() << "    Cannot forward PHI: " << *UseVal << "\n");
147       return FD_CannotForward;
148     }
149 
150     VirtualUse VUse = VirtualUse::create(UseStmt, UseLoop, UseVal, true);
151     switch (VUse.getKind()) {
152     case VirtualUse::Constant:
153     case VirtualUse::Block:
154     case VirtualUse::Hoisted:
155       // These can be used anywhere without special considerations.
156       if (DoIt)
157         return FD_DidForward;
158       return FD_CanForwardLeaf;
159 
160     case VirtualUse::Synthesizable:
161       // Not supported yet.
162       DEBUG(dbgs() << "    Cannot forward synthesizable: " << *UseVal << "\n");
163       return FD_CannotForward;
164 
165     case VirtualUse::ReadOnly:
166       // Note that we cannot return FD_CanForwardTree here. With a operand tree
167       // depth of 0, UseVal is the use in TargetStmt that we try to replace.
168       // With -polly-analyze-read-only-scalars=true we would ensure the
169       // existence of a MemoryAccess (which already exists for a leaf) and be
170       // removed again by tryForwardTree because it's goal is to remove this
171       // scalar MemoryAccess. It interprets FD_CanForwardTree as the permission
172       // to do so.
173       if (!DoIt)
174         return FD_CanForwardLeaf;
175 
176       // If we model read-only scalars, we need to create a MemoryAccess for it.
177       if (ModelReadOnlyScalars)
178         TargetStmt->ensureValueRead(UseVal);
179 
180       NumReadOnlyCopied++;
181       TotalReadOnlyCopied++;
182       return FD_DidForward;
183 
184     case VirtualUse::Intra:
185     case VirtualUse::Inter:
186       auto Inst = cast<Instruction>(UseVal);
187 
188       // Compatible instructions must satisfy the following conditions:
189       // 1. Idempotent (instruction will be copied, not moved; although its
190       //    original instance might be removed by simplification)
191       // 2. Not access memory (There might be memory writes between)
192       // 3. Not cause undefined behaviour (we might copy to a location when the
193       //    original instruction was no executed; this is currently not possible
194       //    because we do not forward PHINodes)
195       // 4. Not leak memory if executed multiple times (I am looking at you,
196       //    malloc!)
197       //
198       // Instruction::mayHaveSideEffects is not sufficient because it considers
199       // malloc to not have side-effects. llvm::isSafeToSpeculativelyExecute is
200       // not sufficient because it allows memory accesses.
201       if (mayBeMemoryDependent(*Inst)) {
202         DEBUG(dbgs() << "    Cannot forward side-effect instruction: " << *Inst
203                      << "\n");
204         return FD_CannotForward;
205       }
206 
207       Loop *DefLoop = LI->getLoopFor(Inst->getParent());
208       ScopStmt *DefStmt = S->getStmtFor(Inst);
209       assert(DefStmt && "Value must be defined somewhere");
210 
211       if (DoIt) {
212         // To ensure the right order, prepend this instruction before its
213         // operands. This ensures that its operands are inserted before the
214         // instruction using them.
215         // TODO: The operand tree is not really a tree, but a DAG. We should be
216         // able to handle DAGs without duplication.
217         TargetStmt->prependInstruction(Inst);
218         NumInstructionsCopied++;
219         TotalInstructionsCopied++;
220       }
221 
222       for (Value *OpVal : Inst->operand_values()) {
223         ForwardingDecision OpDecision =
224             canForwardTree(TargetStmt, OpVal, DefStmt, DefLoop, DoIt);
225         switch (OpDecision) {
226         case FD_CannotForward:
227           assert(!DoIt);
228           return FD_CannotForward;
229 
230         case FD_CanForwardLeaf:
231         case FD_CanForwardTree:
232           assert(!DoIt);
233           break;
234 
235         case FD_DidForward:
236           assert(DoIt);
237           break;
238         }
239       }
240 
241       if (DoIt)
242         return FD_DidForward;
243       return FD_CanForwardTree;
244     }
245 
246     llvm_unreachable("Case unhandled");
247   }
248 
249   /// Try to forward an operand tree rooted in @p RA.
250   bool tryForwardTree(MemoryAccess *RA) {
251     assert(RA->isLatestScalarKind());
252     DEBUG(dbgs() << "Trying to forward operand tree " << RA << "...\n");
253 
254     ScopStmt *Stmt = RA->getStatement();
255     Loop *InLoop = Stmt->getSurroundingLoop();
256 
257     ForwardingDecision Assessment =
258         canForwardTree(Stmt, RA->getAccessValue(), Stmt, InLoop, false);
259     assert(Assessment != FD_DidForward);
260     if (Assessment != FD_CanForwardTree)
261       return false;
262 
263     ForwardingDecision Execution =
264         canForwardTree(Stmt, RA->getAccessValue(), Stmt, InLoop, true);
265     assert(Execution == FD_DidForward);
266 
267     Stmt->removeSingleMemoryAccess(RA);
268     return true;
269   }
270 
271 public:
272   ForwardOpTreeImpl(Scop *S, LoopInfo *LI) : S(S), LI(LI) {}
273 
274   /// Return which SCoP this instance is processing.
275   Scop *getScop() const { return S; }
276 
277   /// Run the algorithm: Use value read accesses as operand tree roots and try
278   /// to forward them into the statement.
279   bool forwardOperandTrees() {
280     for (ScopStmt &Stmt : *S) {
281       // Currently we cannot modify the instruction list of region statements.
282       if (!Stmt.isBlockStmt())
283         continue;
284 
285       bool StmtModified = false;
286 
287       // Because we are modifying the MemoryAccess list, collect them first to
288       // avoid iterator invalidation.
289       SmallVector<MemoryAccess *, 16> Accs;
290       for (MemoryAccess *RA : Stmt) {
291         if (!RA->isRead())
292           continue;
293         if (!RA->isLatestScalarKind())
294           continue;
295 
296         Accs.push_back(RA);
297       }
298 
299       for (MemoryAccess *RA : Accs) {
300         if (tryForwardTree(RA)) {
301           Modified = true;
302           StmtModified = true;
303           NumForwardedTrees++;
304           TotalForwardedTrees++;
305         }
306       }
307 
308       if (StmtModified) {
309         NumModifiedStmts++;
310         TotalModifiedStmts++;
311       }
312     }
313 
314     if (Modified)
315       ScopsModified++;
316     return Modified;
317   }
318 
319   /// Print the pass result, performed transformations and the SCoP after the
320   /// transformation.
321   void print(llvm::raw_ostream &OS, int Indent = 0) {
322     printStatistics(OS, Indent);
323 
324     if (!Modified) {
325       // This line can easily be checked in regression tests.
326       OS << "ForwardOpTree executed, but did not modify anything\n";
327       return;
328     }
329 
330     printStatements(OS, Indent);
331   }
332 };
333 
334 /// Pass that redirects scalar reads to array elements that are known to contain
335 /// the same value.
336 ///
337 /// This reduces the number of scalar accesses and therefore potentially
338 /// increases the freedom of the scheduler. In the ideal case, all reads of a
339 /// scalar definition are redirected (We currently do not care about removing
340 /// the write in this case).  This is also useful for the main DeLICM pass as
341 /// there are less scalars to be mapped.
342 class ForwardOpTree : public ScopPass {
343 private:
344   ForwardOpTree(const ForwardOpTree &) = delete;
345   const ForwardOpTree &operator=(const ForwardOpTree &) = delete;
346 
347   /// The pass implementation, also holding per-scop data.
348   std::unique_ptr<ForwardOpTreeImpl> Impl;
349 
350 public:
351   static char ID;
352 
353   explicit ForwardOpTree() : ScopPass(ID) {}
354 
355   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
356     AU.addRequiredTransitive<ScopInfoRegionPass>();
357     AU.addRequired<LoopInfoWrapperPass>();
358     AU.setPreservesAll();
359   }
360 
361   virtual bool runOnScop(Scop &S) override {
362     // Free resources for previous SCoP's computation, if not yet done.
363     releaseMemory();
364 
365     LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
366     Impl = make_unique<ForwardOpTreeImpl>(&S, &LI);
367 
368     DEBUG(dbgs() << "Forwarding operand trees...\n");
369     Impl->forwardOperandTrees();
370 
371     DEBUG(dbgs() << "\nFinal Scop:\n");
372     DEBUG(dbgs() << S);
373 
374     return false;
375   }
376 
377   virtual void printScop(raw_ostream &OS, Scop &S) const override {
378     if (!Impl)
379       return;
380 
381     assert(Impl->getScop() == &S);
382     Impl->print(OS);
383   }
384 
385   virtual void releaseMemory() override { Impl.reset(); }
386 
387 }; // class ForwardOpTree
388 
389 char ForwardOpTree::ID;
390 } // anonymous namespace
391 
392 ScopPass *polly::createForwardOpTreePass() { return new ForwardOpTree(); }
393 
394 INITIALIZE_PASS_BEGIN(ForwardOpTree, "polly-optree",
395                       "Polly - Forward operand tree", false, false)
396 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
397 INITIALIZE_PASS_END(ForwardOpTree, "polly-optree",
398                     "Polly - Forward operand tree", false, false)
399