blob: 48a652fb35c434e362829cf00eeb693a51ab879c [file] [log] [blame]
Michael Krusea6b2de32017-07-22 14:02:47 +00001//===------ 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
Michael Kruse07e8c362017-07-24 12:43:27 +000016#include "polly/ScopBuilder.h"
Michael Krusea6b2de32017-07-22 14:02:47 +000017#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
25using namespace polly;
26using namespace llvm;
27
28STATISTIC(TotalInstructionsCopied, "Number of copied instructions");
Michael Kruse07e8c362017-07-24 12:43:27 +000029STATISTIC(TotalReadOnlyCopied, "Number of copied read-only accesses");
Michael Krusea6b2de32017-07-22 14:02:47 +000030STATISTIC(TotalForwardedTrees, "Number of forwarded operand trees");
31STATISTIC(TotalModifiedStmts,
32 "Number of statements with at least one forwarded tree");
33
34STATISTIC(ScopsModified, "Number of SCoPs with at least one forwarded tree");
35
36namespace {
37
38/// The state of whether an operand tree was/can be forwarded.
Michael Krused85e3452017-07-24 15:33:53 +000039///
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.
Michael Krusea6b2de32017-07-22 14:02:47 +000043enum ForwardingDecision {
Michael Krused85e3452017-07-24 15:33:53 +000044 /// The root instruction or value cannot be forwarded at all.
Michael Krusea6b2de32017-07-22 14:02:47 +000045 FD_CannotForward,
Michael Krused85e3452017-07-24 15:33:53 +000046
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.
Michael Krusea6b2de32017-07-22 14:02:47 +000059 FD_CanForward,
Michael Krused85e3452017-07-24 15:33:53 +000060
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.
Michael Kruse07e8c362017-07-24 12:43:27 +000063 FD_CanForwardTree,
Michael Krused85e3452017-07-24 15:33:53 +000064
65 /// Used to indicate that a forwarding has be carried out successfully.
Michael Krusea6b2de32017-07-22 14:02:47 +000066 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.
76class ForwardOpTreeImpl {
77private:
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
Michael Kruse07e8c362017-07-24 12:43:27 +000087 /// How many read-only accesses have been copied.
88 int NumReadOnlyCopied = 0;
89
Michael Krusea6b2de32017-07-22 14:02:47 +000090 /// 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';
Michael Kruse07e8c362017-07-24 12:43:27 +0000103 OS.indent(Indent + 4) << "Read-only accesses copied: " << NumReadOnlyCopied
104 << '\n';
Michael Krusea6b2de32017-07-22 14:02:47 +0000105 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 ///
Michael Kruse5b8a9092017-07-24 12:39:46 +0000138 /// @return If DoIt==false, return whether the operand tree can be forwarded.
139 /// If DoIt==true, return FD_DidForward.
Michael Krusea6b2de32017-07-22 14:02:47 +0000140 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:
Michael Krusee5f47062017-07-22 14:30:02 +0000154 case VirtualUse::Hoisted:
Michael Krusea6b2de32017-07-22 14:02:47 +0000155 // These can be used anywhere without special considerations.
156 if (DoIt)
157 return FD_DidForward;
158 return FD_CanForward;
159
160 case VirtualUse::Synthesizable:
161 // Not supported yet.
162 DEBUG(dbgs() << " Cannot forward synthesizable: " << *UseVal << "\n");
163 return FD_CannotForward;
164
Michael Krusea6b2de32017-07-22 14:02:47 +0000165 case VirtualUse::ReadOnly:
Michael Krused85e3452017-07-24 15:33:53 +0000166 // 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.
Michael Kruse07e8c362017-07-24 12:43:27 +0000173 if (!DoIt)
174 return FD_CanForward;
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;
Michael Krusea6b2de32017-07-22 14:02:47 +0000183
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.
Michael Kruse25a68812017-07-24 12:39:41 +0000217 TargetStmt->prependInstruction(Inst);
Michael Krusea6b2de32017-07-22 14:02:47 +0000218 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_CanForward:
Michael Kruse07e8c362017-07-24 12:43:27 +0000231 case FD_CanForwardTree:
Michael Krusea6b2de32017-07-22 14:02:47 +0000232 assert(!DoIt);
233 break;
234
235 case FD_DidForward:
236 assert(DoIt);
237 break;
238 }
239 }
240
241 if (DoIt)
242 return FD_DidForward;
Michael Kruse07e8c362017-07-24 12:43:27 +0000243 return FD_CanForwardTree;
Michael Krusea6b2de32017-07-22 14:02:47 +0000244 }
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);
Michael Kruse07e8c362017-07-24 12:43:27 +0000260 if (Assessment != FD_CanForwardTree)
Michael Krusea6b2de32017-07-22 14:02:47 +0000261 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
271public:
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.
342class ForwardOpTree : public ScopPass {
343private:
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
350public:
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
389char ForwardOpTree::ID;
390} // anonymous namespace
391
392ScopPass *polly::createForwardOpTreePass() { return new ForwardOpTree(); }
393
394INITIALIZE_PASS_BEGIN(ForwardOpTree, "polly-optree",
395 "Polly - Forward operand tree", false, false)
396INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
397INITIALIZE_PASS_END(ForwardOpTree, "polly-optree",
398 "Polly - Forward operand tree", false, false)