1 //===------ Simplify.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 // Simplify a SCoP by removing unnecessary statements and accesses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "polly/Simplify.h" 14 #include "polly/ScopInfo.h" 15 #include "polly/ScopPass.h" 16 #include "polly/Support/GICHelper.h" 17 #include "polly/Support/ISLOStream.h" 18 #include "polly/Support/ISLTools.h" 19 #include "polly/Support/VirtualInstruction.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/InitializePasses.h" 22 #include "llvm/Support/Debug.h" 23 #define DEBUG_TYPE "polly-simplify" 24 25 using namespace llvm; 26 using namespace polly; 27 28 namespace { 29 30 #define TWO_STATISTICS(VARNAME, DESC) \ 31 static llvm::Statistic VARNAME[2] = { \ 32 {DEBUG_TYPE, #VARNAME "0", DESC " (first)"}, \ 33 {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}} 34 35 /// Number of max disjuncts we allow in removeOverwrites(). This is to avoid 36 /// that the analysis of accesses in a statement is becoming too complex. Chosen 37 /// to be relatively small because all the common cases should access only few 38 /// array elements per statement. 39 static int const SimplifyMaxDisjuncts = 4; 40 41 TWO_STATISTICS(ScopsProcessed, "Number of SCoPs processed"); 42 TWO_STATISTICS(ScopsModified, "Number of SCoPs simplified"); 43 44 TWO_STATISTICS(TotalEmptyDomainsRemoved, 45 "Number of statement with empty domains removed in any SCoP"); 46 TWO_STATISTICS(TotalOverwritesRemoved, "Number of removed overwritten writes"); 47 TWO_STATISTICS(TotalWritesCoalesced, "Number of writes coalesced with another"); 48 TWO_STATISTICS(TotalRedundantWritesRemoved, 49 "Number of writes of same value removed in any SCoP"); 50 TWO_STATISTICS(TotalEmptyPartialAccessesRemoved, 51 "Number of empty partial accesses removed"); 52 TWO_STATISTICS(TotalDeadAccessesRemoved, "Number of dead accesses removed"); 53 TWO_STATISTICS(TotalDeadInstructionsRemoved, 54 "Number of unused instructions removed"); 55 TWO_STATISTICS(TotalStmtsRemoved, "Number of statements removed in any SCoP"); 56 57 TWO_STATISTICS(NumValueWrites, "Number of scalar value writes after Simplify"); 58 TWO_STATISTICS( 59 NumValueWritesInLoops, 60 "Number of scalar value writes nested in affine loops after Simplify"); 61 TWO_STATISTICS(NumPHIWrites, 62 "Number of scalar phi writes after the first simplification"); 63 TWO_STATISTICS( 64 NumPHIWritesInLoops, 65 "Number of scalar phi writes nested in affine loops after Simplify"); 66 TWO_STATISTICS(NumSingletonWrites, "Number of singleton writes after Simplify"); 67 TWO_STATISTICS( 68 NumSingletonWritesInLoops, 69 "Number of singleton writes nested in affine loops after Simplify"); 70 71 static bool isImplicitRead(MemoryAccess *MA) { 72 return MA->isRead() && MA->isOriginalScalarKind(); 73 } 74 75 static bool isExplicitAccess(MemoryAccess *MA) { 76 return MA->isOriginalArrayKind(); 77 } 78 79 static bool isImplicitWrite(MemoryAccess *MA) { 80 return MA->isWrite() && MA->isOriginalScalarKind(); 81 } 82 83 /// Like isl::union_map::add_map, but may also return an underapproximated 84 /// result if getting too complex. 85 /// 86 /// This is implemented by adding disjuncts to the results until the limit is 87 /// reached. 88 static isl::union_map underapproximatedAddMap(isl::union_map UMap, 89 isl::map Map) { 90 if (UMap.is_null() || Map.is_null()) 91 return {}; 92 93 isl::map PrevMap = UMap.extract_map(Map.get_space()); 94 95 // Fast path: If known that we cannot exceed the disjunct limit, just add 96 // them. 97 if (isl_map_n_basic_map(PrevMap.get()) + isl_map_n_basic_map(Map.get()) <= 98 SimplifyMaxDisjuncts) 99 return UMap.add_map(Map); 100 101 isl::map Result = isl::map::empty(PrevMap.get_space()); 102 for (isl::basic_map BMap : PrevMap.get_basic_map_list()) { 103 if (Result.n_basic_map() > SimplifyMaxDisjuncts) 104 break; 105 Result = Result.unite(BMap); 106 } 107 for (isl::basic_map BMap : Map.get_basic_map_list()) { 108 if (isl_map_n_basic_map(Result.get()) > SimplifyMaxDisjuncts) 109 break; 110 Result = Result.unite(BMap); 111 } 112 113 isl::union_map UResult = 114 UMap.subtract(isl::map::universe(PrevMap.get_space())); 115 UResult.add_map(Result); 116 117 return UResult; 118 } 119 } // namespace 120 121 /// Return whether at least one simplification has been applied. 122 bool SimplifyVisitor::isModified() const { 123 return EmptyDomainsRemoved > 0 || OverwritesRemoved > 0 || 124 WritesCoalesced > 0 || RedundantWritesRemoved > 0 || 125 EmptyPartialAccessesRemoved > 0 || DeadAccessesRemoved > 0 || 126 DeadInstructionsRemoved > 0 || StmtsRemoved > 0; 127 } 128 129 /// Remove statements that are never executed due to their domains being 130 /// empty. 131 /// 132 /// In contrast to Scop::simplifySCoP, this removes based on the SCoP's 133 /// effective domain, i.e. including the SCoP's context as used by some other 134 /// simplification methods in this pass. This is necessary because the 135 /// analysis on empty domains is unreliable, e.g. remove a scalar value 136 /// definition MemoryAccesses, but not its use. 137 void SimplifyVisitor::removeEmptyDomainStmts() { 138 size_t NumStmtsBefore = S->getSize(); 139 140 S->removeStmts([](ScopStmt &Stmt) -> bool { 141 auto EffectiveDomain = 142 Stmt.getDomain().intersect_params(Stmt.getParent()->getContext()); 143 return EffectiveDomain.is_empty(); 144 }); 145 146 assert(NumStmtsBefore >= S->getSize()); 147 EmptyDomainsRemoved = NumStmtsBefore - S->getSize(); 148 LLVM_DEBUG(dbgs() << "Removed " << EmptyDomainsRemoved << " (of " 149 << NumStmtsBefore << ") statements with empty domains \n"); 150 TotalEmptyDomainsRemoved[CallNo] += EmptyDomainsRemoved; 151 } 152 153 /// Remove writes that are overwritten unconditionally later in the same 154 /// statement. 155 /// 156 /// There must be no read of the same value between the write (that is to be 157 /// removed) and the overwrite. 158 void SimplifyVisitor::removeOverwrites() { 159 for (auto &Stmt : *S) { 160 isl::set Domain = Stmt.getDomain(); 161 isl::union_map WillBeOverwritten = 162 isl::union_map::empty(S->getParamSpace()); 163 164 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt)); 165 166 // Iterate in reverse order, so the overwrite comes before the write that 167 // is to be removed. 168 for (auto *MA : reverse(Accesses)) { 169 170 // In region statements, the explicit accesses can be in blocks that are 171 // can be executed in any order. We therefore process only the implicit 172 // writes and stop after that. 173 if (Stmt.isRegionStmt() && isExplicitAccess(MA)) 174 break; 175 176 auto AccRel = MA->getAccessRelation(); 177 AccRel = AccRel.intersect_domain(Domain); 178 AccRel = AccRel.intersect_params(S->getContext()); 179 180 // If a value is read in-between, do not consider it as overwritten. 181 if (MA->isRead()) { 182 // Invalidate all overwrites for the array it accesses to avoid too 183 // complex isl sets. 184 isl::map AccRelUniv = isl::map::universe(AccRel.get_space()); 185 WillBeOverwritten = WillBeOverwritten.subtract(AccRelUniv); 186 continue; 187 } 188 189 // If all of a write's elements are overwritten, remove it. 190 isl::union_map AccRelUnion = AccRel; 191 if (AccRelUnion.is_subset(WillBeOverwritten)) { 192 LLVM_DEBUG(dbgs() << "Removing " << MA 193 << " which will be overwritten anyway\n"); 194 195 Stmt.removeSingleMemoryAccess(MA); 196 OverwritesRemoved++; 197 TotalOverwritesRemoved[CallNo]++; 198 } 199 200 // Unconditional writes overwrite other values. 201 if (MA->isMustWrite()) { 202 // Avoid too complex isl sets. If necessary, throw away some of the 203 // knowledge. 204 WillBeOverwritten = underapproximatedAddMap(WillBeOverwritten, AccRel); 205 } 206 } 207 } 208 } 209 210 /// Combine writes that write the same value if possible. 211 /// 212 /// This function is able to combine: 213 /// - Partial writes with disjoint domain. 214 /// - Writes that write to the same array element. 215 /// 216 /// In all cases, both writes must write the same values. 217 void SimplifyVisitor::coalesceWrites() { 218 for (auto &Stmt : *S) { 219 isl::set Domain = Stmt.getDomain().intersect_params(S->getContext()); 220 221 // We let isl do the lookup for the same-value condition. For this, we 222 // wrap llvm::Value into an isl::set such that isl can do the lookup in 223 // its hashtable implementation. llvm::Values are only compared within a 224 // ScopStmt, so the map can be local to this scope. TODO: Refactor with 225 // ZoneAlgorithm::makeValueSet() 226 SmallDenseMap<Value *, isl::set> ValueSets; 227 auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set { 228 assert(V); 229 isl::set &Result = ValueSets[V]; 230 if (Result.is_null()) { 231 isl::ctx Ctx = S->getIslCtx(); 232 std::string Name = getIslCompatibleName( 233 "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames); 234 isl::id Id = isl::id::alloc(Ctx, Name, V); 235 Result = isl::set::universe( 236 isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id)); 237 } 238 return Result; 239 }; 240 241 // List of all eligible (for coalescing) writes of the future. 242 // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] } 243 isl::union_map FutureWrites = isl::union_map::empty(S->getParamSpace()); 244 245 // Iterate over accesses from the last to the first. 246 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt)); 247 for (MemoryAccess *MA : reverse(Accesses)) { 248 // In region statements, the explicit accesses can be in blocks that can 249 // be executed in any order. We therefore process only the implicit 250 // writes and stop after that. 251 if (Stmt.isRegionStmt() && isExplicitAccess(MA)) 252 break; 253 254 // { Domain[] -> Element[] } 255 isl::map AccRel = MA->getLatestAccessRelation().intersect_domain(Domain); 256 257 // { [Domain[] -> Element[]] } 258 isl::set AccRelWrapped = AccRel.wrap(); 259 260 // { Value[] } 261 isl::set ValSet; 262 263 if (MA->isMustWrite() && (MA->isOriginalScalarKind() || 264 isa<StoreInst>(MA->getAccessInstruction()))) { 265 // Normally, tryGetValueStored() should be used to determine which 266 // element is written, but it can return nullptr; For PHI accesses, 267 // getAccessValue() returns the PHI instead of the PHI's incoming 268 // value. In this case, where we only compare values of a single 269 // statement, this is fine, because within a statement, a PHI in a 270 // successor block has always the same value as the incoming write. We 271 // still preferably use the incoming value directly so we also catch 272 // direct uses of that. 273 Value *StoredVal = MA->tryGetValueStored(); 274 if (!StoredVal) 275 StoredVal = MA->getAccessValue(); 276 ValSet = makeValueSet(StoredVal); 277 278 // { Domain[] } 279 isl::set AccDomain = AccRel.domain(); 280 281 // Parts of the statement's domain that is not written by this access. 282 isl::set UndefDomain = Domain.subtract(AccDomain); 283 284 // { Element[] } 285 isl::set ElementUniverse = 286 isl::set::universe(AccRel.get_space().range()); 287 288 // { Domain[] -> Element[] } 289 isl::map UndefAnything = 290 isl::map::from_domain_and_range(UndefDomain, ElementUniverse); 291 292 // We are looking a compatible write access. The other write can 293 // access these elements... 294 isl::map AllowedAccesses = AccRel.unite(UndefAnything); 295 296 // ... and must write the same value. 297 // { [Domain[] -> Element[]] -> Value[] } 298 isl::map Filter = 299 isl::map::from_domain_and_range(AllowedAccesses.wrap(), ValSet); 300 301 // Lookup future write that fulfills these conditions. 302 // { [[Domain[] -> Element[]] -> Value[]] -> MemoryAccess[] } 303 isl::union_map Filtered = 304 FutureWrites.uncurry().intersect_domain(Filter.wrap()); 305 306 // Iterate through the candidates. 307 for (isl::map Map : Filtered.get_map_list()) { 308 MemoryAccess *OtherMA = (MemoryAccess *)Map.get_space() 309 .get_tuple_id(isl::dim::out) 310 .get_user(); 311 312 isl::map OtherAccRel = 313 OtherMA->getLatestAccessRelation().intersect_domain(Domain); 314 315 // The filter only guaranteed that some of OtherMA's accessed 316 // elements are allowed. Verify that it only accesses allowed 317 // elements. Otherwise, continue with the next candidate. 318 if (!OtherAccRel.is_subset(AllowedAccesses).is_true()) 319 continue; 320 321 // The combined access relation. 322 // { Domain[] -> Element[] } 323 isl::map NewAccRel = AccRel.unite(OtherAccRel); 324 simplify(NewAccRel); 325 326 // Carry out the coalescing. 327 Stmt.removeSingleMemoryAccess(MA); 328 OtherMA->setNewAccessRelation(NewAccRel); 329 330 // We removed MA, OtherMA takes its role. 331 MA = OtherMA; 332 333 TotalWritesCoalesced[CallNo]++; 334 WritesCoalesced++; 335 336 // Don't look for more candidates. 337 break; 338 } 339 } 340 341 // Two writes cannot be coalesced if there is another access (to some of 342 // the written elements) between them. Remove all visited write accesses 343 // from the list of eligible writes. Don't just remove the accessed 344 // elements, but any MemoryAccess that touches any of the invalidated 345 // elements. 346 SmallPtrSet<MemoryAccess *, 2> TouchedAccesses; 347 for (isl::map Map : 348 FutureWrites.intersect_domain(AccRelWrapped).get_map_list()) { 349 MemoryAccess *MA = (MemoryAccess *)Map.get_space() 350 .range() 351 .unwrap() 352 .get_tuple_id(isl::dim::out) 353 .get_user(); 354 TouchedAccesses.insert(MA); 355 } 356 isl::union_map NewFutureWrites = 357 isl::union_map::empty(FutureWrites.get_space()); 358 for (isl::map FutureWrite : FutureWrites.get_map_list()) { 359 MemoryAccess *MA = (MemoryAccess *)FutureWrite.get_space() 360 .range() 361 .unwrap() 362 .get_tuple_id(isl::dim::out) 363 .get_user(); 364 if (!TouchedAccesses.count(MA)) 365 NewFutureWrites = NewFutureWrites.add_map(FutureWrite); 366 } 367 FutureWrites = NewFutureWrites; 368 369 if (MA->isMustWrite() && !ValSet.is_null()) { 370 // { MemoryAccess[] } 371 auto AccSet = 372 isl::set::universe(isl::space(S->getIslCtx(), 0, 0) 373 .set_tuple_id(isl::dim::set, MA->getId())); 374 375 // { Val[] -> MemoryAccess[] } 376 isl::map ValAccSet = isl::map::from_domain_and_range(ValSet, AccSet); 377 378 // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] } 379 isl::map AccRelValAcc = 380 isl::map::from_domain_and_range(AccRelWrapped, ValAccSet.wrap()); 381 FutureWrites = FutureWrites.add_map(AccRelValAcc); 382 } 383 } 384 } 385 } 386 387 /// Remove writes that just write the same value already stored in the 388 /// element. 389 void SimplifyVisitor::removeRedundantWrites() { 390 for (auto &Stmt : *S) { 391 SmallDenseMap<Value *, isl::set> ValueSets; 392 auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set { 393 assert(V); 394 isl::set &Result = ValueSets[V]; 395 if (Result.is_null()) { 396 isl_ctx *Ctx = S->getIslCtx().get(); 397 std::string Name = getIslCompatibleName( 398 "Val", V, ValueSets.size() - 1, std::string(), UseInstructionNames); 399 isl::id Id = isl::manage(isl_id_alloc(Ctx, Name.c_str(), V)); 400 Result = isl::set::universe( 401 isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id)); 402 } 403 return Result; 404 }; 405 406 isl::set Domain = Stmt.getDomain(); 407 Domain = Domain.intersect_params(S->getContext()); 408 409 // List of element reads that still have the same value while iterating 410 // through the MemoryAccesses. 411 // { [Domain[] -> Element[]] -> Val[] } 412 isl::union_map Known = isl::union_map::empty(S->getParamSpace()); 413 414 SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt)); 415 for (MemoryAccess *MA : Accesses) { 416 // Is the memory access in a defined order relative to the other 417 // accesses? In region statements, only the first and the last accesses 418 // have defined order. Execution of those in the middle may depend on 419 // runtime conditions an therefore cannot be modified. 420 bool IsOrdered = 421 Stmt.isBlockStmt() || MA->isOriginalScalarKind() || 422 (!S->getBoxedLoops().size() && MA->getAccessInstruction() && 423 Stmt.getEntryBlock() == MA->getAccessInstruction()->getParent()); 424 425 isl::map AccRel = MA->getAccessRelation(); 426 AccRel = AccRel.intersect_domain(Domain); 427 isl::set AccRelWrapped = AccRel.wrap(); 428 429 // Determine whether a write is redundant (stores only values that are 430 // already present in the written array elements) and remove it if this 431 // is the case. 432 if (IsOrdered && MA->isMustWrite() && 433 (isa<StoreInst>(MA->getAccessInstruction()) || 434 MA->isOriginalScalarKind())) { 435 Value *StoredVal = MA->tryGetValueStored(); 436 if (!StoredVal) 437 StoredVal = MA->getAccessValue(); 438 439 if (StoredVal) { 440 // Lookup in the set of known values. 441 isl::map AccRelStoredVal = isl::map::from_domain_and_range( 442 AccRelWrapped, makeValueSet(StoredVal)); 443 if (isl::union_map(AccRelStoredVal).is_subset(Known)) { 444 LLVM_DEBUG(dbgs() << "Cleanup of " << MA << ":\n"); 445 LLVM_DEBUG(dbgs() << " Scalar: " << *StoredVal << "\n"); 446 LLVM_DEBUG(dbgs() << " AccRel: " << AccRel << "\n"); 447 448 Stmt.removeSingleMemoryAccess(MA); 449 450 RedundantWritesRemoved++; 451 TotalRedundantWritesRemoved[CallNo]++; 452 } 453 } 454 } 455 456 // Update the know values set. 457 if (MA->isRead()) { 458 // Loaded values are the currently known values of the array element 459 // it was loaded from. 460 Value *LoadedVal = MA->getAccessValue(); 461 if (LoadedVal && IsOrdered) { 462 isl::map AccRelVal = isl::map::from_domain_and_range( 463 AccRelWrapped, makeValueSet(LoadedVal)); 464 465 Known = Known.add_map(AccRelVal); 466 } 467 } else if (MA->isWrite()) { 468 // Remove (possibly) overwritten values from the known elements set. 469 // We remove all elements of the accessed array to avoid too complex 470 // isl sets. 471 isl::set AccRelUniv = isl::set::universe(AccRelWrapped.get_space()); 472 Known = Known.subtract_domain(AccRelUniv); 473 474 // At this point, we could add the written value of must-writes. 475 // However, writing same values is already handled by 476 // coalesceWrites(). 477 } 478 } 479 } 480 } 481 482 /// Remove statements without side effects. 483 void SimplifyVisitor::removeUnnecessaryStmts() { 484 auto NumStmtsBefore = S->getSize(); 485 S->simplifySCoP(true); 486 assert(NumStmtsBefore >= S->getSize()); 487 StmtsRemoved = NumStmtsBefore - S->getSize(); 488 LLVM_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore 489 << ") statements\n"); 490 TotalStmtsRemoved[CallNo] += StmtsRemoved; 491 } 492 493 /// Remove accesses that have an empty domain. 494 void SimplifyVisitor::removeEmptyPartialAccesses() { 495 for (ScopStmt &Stmt : *S) { 496 // Defer the actual removal to not invalidate iterators. 497 SmallVector<MemoryAccess *, 8> DeferredRemove; 498 499 for (MemoryAccess *MA : Stmt) { 500 if (!MA->isWrite()) 501 continue; 502 503 isl::map AccRel = MA->getAccessRelation(); 504 if (!AccRel.is_empty().is_true()) 505 continue; 506 507 LLVM_DEBUG( 508 dbgs() << "Removing " << MA 509 << " because it's a partial access that never occurs\n"); 510 DeferredRemove.push_back(MA); 511 } 512 513 for (MemoryAccess *MA : DeferredRemove) { 514 Stmt.removeSingleMemoryAccess(MA); 515 EmptyPartialAccessesRemoved++; 516 TotalEmptyPartialAccessesRemoved[CallNo]++; 517 } 518 } 519 } 520 521 /// Mark all reachable instructions and access, and sweep those that are not 522 /// reachable. 523 void SimplifyVisitor::markAndSweep(LoopInfo *LI) { 524 DenseSet<MemoryAccess *> UsedMA; 525 DenseSet<VirtualInstruction> UsedInsts; 526 527 // Get all reachable instructions and accesses. 528 markReachable(S, LI, UsedInsts, UsedMA); 529 530 // Remove all non-reachable accesses. 531 // We need get all MemoryAccesses first, in order to not invalidate the 532 // iterators when removing them. 533 SmallVector<MemoryAccess *, 64> AllMAs; 534 for (ScopStmt &Stmt : *S) 535 AllMAs.append(Stmt.begin(), Stmt.end()); 536 537 for (MemoryAccess *MA : AllMAs) { 538 if (UsedMA.count(MA)) 539 continue; 540 LLVM_DEBUG(dbgs() << "Removing " << MA 541 << " because its value is not used\n"); 542 ScopStmt *Stmt = MA->getStatement(); 543 Stmt->removeSingleMemoryAccess(MA); 544 545 DeadAccessesRemoved++; 546 TotalDeadAccessesRemoved[CallNo]++; 547 } 548 549 // Remove all non-reachable instructions. 550 for (ScopStmt &Stmt : *S) { 551 // Note that for region statements, we can only remove the non-terminator 552 // instructions of the entry block. All other instructions are not in the 553 // instructions list, but implicitly always part of the statement. 554 555 SmallVector<Instruction *, 32> AllInsts(Stmt.insts_begin(), 556 Stmt.insts_end()); 557 SmallVector<Instruction *, 32> RemainInsts; 558 559 for (Instruction *Inst : AllInsts) { 560 auto It = UsedInsts.find({&Stmt, Inst}); 561 if (It == UsedInsts.end()) { 562 LLVM_DEBUG(dbgs() << "Removing "; Inst->print(dbgs()); 563 dbgs() << " because it is not used\n"); 564 DeadInstructionsRemoved++; 565 TotalDeadInstructionsRemoved[CallNo]++; 566 continue; 567 } 568 569 RemainInsts.push_back(Inst); 570 571 // If instructions appear multiple times, keep only the first. 572 UsedInsts.erase(It); 573 } 574 575 // Set the new instruction list to be only those we did not remove. 576 Stmt.setInstructions(RemainInsts); 577 } 578 } 579 580 /// Print simplification statistics to @p OS. 581 void SimplifyVisitor::printStatistics(llvm::raw_ostream &OS, int Indent) const { 582 OS.indent(Indent) << "Statistics {\n"; 583 OS.indent(Indent + 4) << "Empty domains removed: " << EmptyDomainsRemoved 584 << '\n'; 585 OS.indent(Indent + 4) << "Overwrites removed: " << OverwritesRemoved << '\n'; 586 OS.indent(Indent + 4) << "Partial writes coalesced: " << WritesCoalesced 587 << "\n"; 588 OS.indent(Indent + 4) << "Redundant writes removed: " 589 << RedundantWritesRemoved << "\n"; 590 OS.indent(Indent + 4) << "Accesses with empty domains removed: " 591 << EmptyPartialAccessesRemoved << "\n"; 592 OS.indent(Indent + 4) << "Dead accesses removed: " << DeadAccessesRemoved 593 << '\n'; 594 OS.indent(Indent + 4) << "Dead instructions removed: " 595 << DeadInstructionsRemoved << '\n'; 596 OS.indent(Indent + 4) << "Stmts removed: " << StmtsRemoved << "\n"; 597 OS.indent(Indent) << "}\n"; 598 } 599 600 /// Print the current state of all MemoryAccesses to @p OS. 601 void SimplifyVisitor::printAccesses(llvm::raw_ostream &OS, int Indent) const { 602 OS.indent(Indent) << "After accesses {\n"; 603 for (auto &Stmt : *S) { 604 OS.indent(Indent + 4) << Stmt.getBaseName() << "\n"; 605 for (auto *MA : Stmt) 606 MA->print(OS); 607 } 608 OS.indent(Indent) << "}\n"; 609 } 610 611 bool SimplifyVisitor::visit(Scop &S, LoopInfo *LI) { 612 // Reset statistics of last processed SCoP. 613 releaseMemory(); 614 assert(!isModified()); 615 616 // Prepare processing of this SCoP. 617 this->S = &S; 618 ScopsProcessed[CallNo]++; 619 620 LLVM_DEBUG(dbgs() << "Removing statements that are never executed...\n"); 621 removeEmptyDomainStmts(); 622 623 LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n"); 624 removeEmptyPartialAccesses(); 625 626 LLVM_DEBUG(dbgs() << "Removing overwrites...\n"); 627 removeOverwrites(); 628 629 LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n"); 630 coalesceWrites(); 631 632 LLVM_DEBUG(dbgs() << "Removing redundant writes...\n"); 633 removeRedundantWrites(); 634 635 LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n"); 636 markAndSweep(LI); 637 638 LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n"); 639 removeUnnecessaryStmts(); 640 641 if (isModified()) 642 ScopsModified[CallNo]++; 643 LLVM_DEBUG(dbgs() << "\nFinal Scop:\n"); 644 LLVM_DEBUG(dbgs() << S); 645 646 auto ScopStats = S.getStatistics(); 647 NumValueWrites[CallNo] += ScopStats.NumValueWrites; 648 NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops; 649 NumPHIWrites[CallNo] += ScopStats.NumPHIWrites; 650 NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops; 651 NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites; 652 NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops; 653 654 return false; 655 } 656 657 void SimplifyVisitor::printScop(raw_ostream &OS, Scop &S) const { 658 assert(&S == this->S && 659 "Can only print analysis for the last processed SCoP"); 660 printStatistics(OS); 661 662 if (!isModified()) { 663 OS << "SCoP could not be simplified\n"; 664 return; 665 } 666 printAccesses(OS); 667 } 668 669 void SimplifyVisitor::releaseMemory() { 670 S = nullptr; 671 672 EmptyDomainsRemoved = 0; 673 OverwritesRemoved = 0; 674 WritesCoalesced = 0; 675 RedundantWritesRemoved = 0; 676 EmptyPartialAccessesRemoved = 0; 677 DeadAccessesRemoved = 0; 678 DeadInstructionsRemoved = 0; 679 StmtsRemoved = 0; 680 } 681 682 namespace { 683 class SimplifyLegacyPass : public ScopPass { 684 public: 685 static char ID; 686 SimplifyVisitor Imp; 687 688 explicit SimplifyLegacyPass(int CallNo = 0) : ScopPass(ID), Imp(CallNo) {} 689 690 virtual void getAnalysisUsage(AnalysisUsage &AU) const override { 691 AU.addRequiredTransitive<ScopInfoRegionPass>(); 692 AU.addRequired<LoopInfoWrapperPass>(); 693 AU.setPreservesAll(); 694 } 695 696 virtual bool runOnScop(Scop &S) override { 697 return Imp.visit(S, &getAnalysis<LoopInfoWrapperPass>().getLoopInfo()); 698 } 699 700 virtual void printScop(raw_ostream &OS, Scop &S) const override { 701 Imp.printScop(OS, S); 702 } 703 704 virtual void releaseMemory() override { Imp.releaseMemory(); } 705 }; 706 707 char SimplifyLegacyPass::ID; 708 } // anonymous namespace 709 710 namespace polly { 711 llvm::PreservedAnalyses SimplifyPass::run(Scop &S, ScopAnalysisManager &SAM, 712 ScopStandardAnalysisResults &SAR, 713 SPMUpdater &U) { 714 if (!Imp.visit(S, &SAR.LI)) 715 return llvm::PreservedAnalyses::all(); 716 717 return llvm::PreservedAnalyses::none(); 718 } 719 720 llvm::PreservedAnalyses 721 SimplifyPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, 722 ScopStandardAnalysisResults &SAR, SPMUpdater &U) { 723 bool Changed = Imp.visit(S, &SAR.LI); 724 Imp.printScop(OS, S); 725 726 if (!Changed) 727 return llvm::PreservedAnalyses::all(); 728 729 return llvm::PreservedAnalyses::none(); 730 } 731 732 SmallVector<MemoryAccess *, 32> getAccessesInOrder(ScopStmt &Stmt) { 733 734 SmallVector<MemoryAccess *, 32> Accesses; 735 736 for (MemoryAccess *MemAcc : Stmt) 737 if (isImplicitRead(MemAcc)) 738 Accesses.push_back(MemAcc); 739 740 for (MemoryAccess *MemAcc : Stmt) 741 if (isExplicitAccess(MemAcc)) 742 Accesses.push_back(MemAcc); 743 744 for (MemoryAccess *MemAcc : Stmt) 745 if (isImplicitWrite(MemAcc)) 746 Accesses.push_back(MemAcc); 747 748 return Accesses; 749 } 750 } // namespace polly 751 752 Pass *polly::createSimplifyPass(int CallNo) { 753 return new SimplifyLegacyPass(CallNo); 754 } 755 756 INITIALIZE_PASS_BEGIN(SimplifyLegacyPass, "polly-simplify", "Polly - Simplify", 757 false, false) 758 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 759 INITIALIZE_PASS_END(SimplifyLegacyPass, "polly-simplify", "Polly - Simplify", 760 false, false) 761