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