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