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