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