1 //===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// 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 // This file implements the AliasSetTracker and AliasSet classes. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Analysis/AliasSetTracker.h" 14 #include "llvm/ADT/SetVector.h" 15 #include "llvm/ADT/StringExtras.h" 16 #include "llvm/Analysis/AliasAnalysis.h" 17 #include "llvm/Analysis/GuardUtils.h" 18 #include "llvm/Analysis/MemoryLocation.h" 19 #include "llvm/Config/llvm-config.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/InstIterator.h" 22 #include "llvm/IR/Instructions.h" 23 #include "llvm/IR/IntrinsicInst.h" 24 #include "llvm/IR/PassManager.h" 25 #include "llvm/IR/PatternMatch.h" 26 #include "llvm/IR/Value.h" 27 #include "llvm/InitializePasses.h" 28 #include "llvm/Pass.h" 29 #include "llvm/Support/AtomicOrdering.h" 30 #include "llvm/Support/CommandLine.h" 31 #include "llvm/Support/Compiler.h" 32 #include "llvm/Support/Debug.h" 33 #include "llvm/Support/ErrorHandling.h" 34 #include "llvm/Support/raw_ostream.h" 35 36 using namespace llvm; 37 38 static cl::opt<unsigned> SaturationThreshold( 39 "alias-set-saturation-threshold", cl::Hidden, cl::init(250), 40 cl::desc("The maximum total number of memory locations alias " 41 "sets may contain before degradation")); 42 43 /// mergeSetIn - Merge the specified alias set into this alias set. 44 void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST, 45 BatchAAResults &BatchAA) { 46 assert(!AS.Forward && "Alias set is already forwarding!"); 47 assert(!Forward && "This set is a forwarding set!!"); 48 49 // Update the alias and access types of this set... 50 Access |= AS.Access; 51 Alias |= AS.Alias; 52 53 if (Alias == SetMustAlias) { 54 // Check that these two merged sets really are must aliases. If we cannot 55 // find a must-alias pair between them, this set becomes a may alias. 56 if (!any_of(MemoryLocs, [&](const MemoryLocation &MemLoc) { 57 return any_of(AS.MemoryLocs, [&](const MemoryLocation &ASMemLoc) { 58 return BatchAA.isMustAlias(MemLoc, ASMemLoc); 59 }); 60 })) 61 Alias = SetMayAlias; 62 } 63 64 // Merge the list of constituent memory locations... 65 if (MemoryLocs.empty()) { 66 std::swap(MemoryLocs, AS.MemoryLocs); 67 } else { 68 append_range(MemoryLocs, AS.MemoryLocs); 69 AS.MemoryLocs.clear(); 70 } 71 72 bool ASHadUnknownInsts = !AS.UnknownInsts.empty(); 73 if (UnknownInsts.empty()) { // Merge call sites... 74 if (ASHadUnknownInsts) { 75 std::swap(UnknownInsts, AS.UnknownInsts); 76 addRef(); 77 } 78 } else if (ASHadUnknownInsts) { 79 llvm::append_range(UnknownInsts, AS.UnknownInsts); 80 AS.UnknownInsts.clear(); 81 } 82 83 AS.Forward = this; // Forward across AS now... 84 addRef(); // AS is now pointing to us... 85 86 if (ASHadUnknownInsts) 87 AS.dropRef(AST); 88 } 89 90 void AliasSetTracker::removeAliasSet(AliasSet *AS) { 91 if (AliasSet *Fwd = AS->Forward) { 92 Fwd->dropRef(*this); 93 AS->Forward = nullptr; 94 } else // Update TotalAliasSetSize only if not forwarding. 95 TotalAliasSetSize -= AS->size(); 96 97 AliasSets.erase(AS); 98 // If we've removed the saturated alias set, set saturated marker back to 99 // nullptr and ensure this tracker is empty. 100 if (AS == AliasAnyAS) { 101 AliasAnyAS = nullptr; 102 assert(AliasSets.empty() && "Tracker not empty"); 103 } 104 } 105 106 void AliasSet::removeFromTracker(AliasSetTracker &AST) { 107 assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); 108 AST.removeAliasSet(this); 109 } 110 111 void AliasSet::addMemoryLocation(AliasSetTracker &AST, 112 const MemoryLocation &MemLoc, 113 bool KnownMustAlias) { 114 if (isMustAlias() && !KnownMustAlias) { 115 // If we cannot find a must-alias with any of the existing MemoryLocs, we 116 // must downgrade to may-alias. 117 if (!any_of(MemoryLocs, [&](const MemoryLocation &ASMemLoc) { 118 return AST.getAliasAnalysis().isMustAlias(MemLoc, ASMemLoc); 119 })) 120 Alias = SetMayAlias; 121 } 122 123 // Add it to the end of the list... 124 MemoryLocs.push_back(MemLoc); 125 126 AST.TotalAliasSetSize++; 127 } 128 129 void AliasSet::addUnknownInst(Instruction *I, BatchAAResults &AA) { 130 if (UnknownInsts.empty()) 131 addRef(); 132 UnknownInsts.emplace_back(I); 133 134 // Guards are marked as modifying memory for control flow modelling purposes, 135 // but don't actually modify any specific memory location. 136 using namespace PatternMatch; 137 bool MayWriteMemory = I->mayWriteToMemory() && !isGuard(I) && 138 !(I->use_empty() && match(I, m_Intrinsic<Intrinsic::invariant_start>())); 139 if (!MayWriteMemory) { 140 Alias = SetMayAlias; 141 Access |= RefAccess; 142 return; 143 } 144 145 // FIXME: This should use mod/ref information to make this not suck so bad 146 Alias = SetMayAlias; 147 Access = ModRefAccess; 148 } 149 150 /// aliasesMemoryLocation - If the specified memory location "may" (or must) 151 /// alias one of the members in the set return the appropriate AliasResult. 152 /// Otherwise return NoAlias. 153 /// 154 AliasResult AliasSet::aliasesMemoryLocation(const MemoryLocation &MemLoc, 155 BatchAAResults &AA) const { 156 if (AliasAny) 157 return AliasResult::MayAlias; 158 159 // Check all of the memory locations in the set... 160 for (const auto &ASMemLoc : MemoryLocs) { 161 AliasResult AR = AA.alias(MemLoc, ASMemLoc); 162 if (AR != AliasResult::NoAlias) 163 return AR; 164 } 165 166 // Check the unknown instructions... 167 for (Instruction *Inst : UnknownInsts) 168 if (isModOrRefSet(AA.getModRefInfo(Inst, MemLoc))) 169 return AliasResult::MayAlias; 170 171 return AliasResult::NoAlias; 172 } 173 174 ModRefInfo AliasSet::aliasesUnknownInst(const Instruction *Inst, 175 BatchAAResults &AA) const { 176 177 if (AliasAny) 178 return ModRefInfo::ModRef; 179 180 if (!Inst->mayReadOrWriteMemory()) 181 return ModRefInfo::NoModRef; 182 183 for (Instruction *UnknownInst : UnknownInsts) { 184 const auto *C1 = dyn_cast<CallBase>(UnknownInst); 185 const auto *C2 = dyn_cast<CallBase>(Inst); 186 if (!C1 || !C2 || isModOrRefSet(AA.getModRefInfo(C1, C2)) || 187 isModOrRefSet(AA.getModRefInfo(C2, C1))) { 188 // TODO: Could be more precise, but not really useful right now. 189 return ModRefInfo::ModRef; 190 } 191 } 192 193 ModRefInfo MR = ModRefInfo::NoModRef; 194 for (const auto &ASMemLoc : MemoryLocs) { 195 MR |= AA.getModRefInfo(Inst, ASMemLoc); 196 if (isModAndRefSet(MR)) 197 return MR; 198 } 199 200 return MR; 201 } 202 203 AliasSet::PointerVector AliasSet::getPointers() const { 204 SmallSetVector<const Value *, 8> Pointers; 205 for (const MemoryLocation &MemLoc : MemoryLocs) 206 Pointers.insert(MemLoc.Ptr); 207 return Pointers.takeVector(); 208 } 209 210 void AliasSetTracker::clear() { 211 PointerMap.clear(); 212 AliasSets.clear(); 213 } 214 215 /// mergeAliasSetsForMemoryLocation - Given a memory location, merge all alias 216 /// sets that may alias it. Return the unified set, or nullptr if no aliasing 217 /// set was found. A known existing alias set for the pointer value of the 218 /// memory location can be passed in (or nullptr if not available). MustAliasAll 219 /// is updated to true/false if the memory location is found to MustAlias all 220 /// the sets it merged. 221 AliasSet *AliasSetTracker::mergeAliasSetsForMemoryLocation( 222 const MemoryLocation &MemLoc, AliasSet *PtrAS, bool &MustAliasAll) { 223 AliasSet *FoundSet = nullptr; 224 MustAliasAll = true; 225 for (AliasSet &AS : llvm::make_early_inc_range(*this)) { 226 if (AS.Forward) 227 continue; 228 229 // An alias set that already contains a memory location with the same 230 // pointer value is directly assumed to MustAlias; we bypass the AA query in 231 // this case. 232 // Note: it is not guaranteed that AA would always provide the same result; 233 // a known exception are undef pointer values, where alias(undef, undef) is 234 // NoAlias, while we treat it as MustAlias. 235 if (&AS != PtrAS) { 236 AliasResult AR = AS.aliasesMemoryLocation(MemLoc, AA); 237 if (AR == AliasResult::NoAlias) 238 continue; 239 240 if (AR != AliasResult::MustAlias) 241 MustAliasAll = false; 242 } 243 244 if (!FoundSet) { 245 // If this is the first alias set ptr can go into, remember it. 246 FoundSet = &AS; 247 } else { 248 // Otherwise, we must merge the sets. 249 FoundSet->mergeSetIn(AS, *this, AA); 250 } 251 } 252 253 return FoundSet; 254 } 255 256 AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) { 257 AliasSet *FoundSet = nullptr; 258 for (AliasSet &AS : llvm::make_early_inc_range(*this)) { 259 if (AS.Forward || !isModOrRefSet(AS.aliasesUnknownInst(Inst, AA))) 260 continue; 261 if (!FoundSet) { 262 // If this is the first alias set ptr can go into, remember it. 263 FoundSet = &AS; 264 } else { 265 // Otherwise, we must merge the sets. 266 FoundSet->mergeSetIn(AS, *this, AA); 267 } 268 } 269 return FoundSet; 270 } 271 272 AliasSet &AliasSetTracker::getAliasSetFor(const MemoryLocation &MemLoc) { 273 // The alias sets are indexed with a map from the memory locations' pointer 274 // values. If the memory location is already registered, we can find it in the 275 // alias set associated with its pointer. 276 AliasSet *&MapEntry = PointerMap[MemLoc.Ptr]; 277 if (MapEntry) { 278 collapseForwardingIn(MapEntry); 279 if (is_contained(MapEntry->MemoryLocs, MemLoc)) 280 return *MapEntry; 281 } 282 283 AliasSet *AS; 284 bool MustAliasAll = false; 285 if (AliasAnyAS) { 286 // At this point, the AST is saturated, so we only have one active alias 287 // set. That means we already know which alias set we want to return, and 288 // just need to add the memory location to that set to keep the data 289 // structure consistent. 290 // This, of course, means that we will never need a merge here. 291 AS = AliasAnyAS; 292 } else if (AliasSet *AliasAS = mergeAliasSetsForMemoryLocation( 293 MemLoc, MapEntry, MustAliasAll)) { 294 // Add it to the alias set it aliases. 295 AS = AliasAS; 296 } else { 297 // Otherwise create a new alias set to hold the new memory location. 298 AliasSets.push_back(AS = new AliasSet()); 299 MustAliasAll = true; 300 } 301 302 // Register memory location in selected alias set. 303 AS->addMemoryLocation(*this, MemLoc, MustAliasAll); 304 // Register selected alias set in pointer map (or ensure it is consistent with 305 // earlier map entry after taking into account new merging). 306 if (MapEntry) { 307 collapseForwardingIn(MapEntry); 308 assert(MapEntry == AS && "Memory locations with same pointer value cannot " 309 "be in different alias sets"); 310 } else { 311 AS->addRef(); 312 MapEntry = AS; 313 } 314 return *AS; 315 } 316 317 void AliasSetTracker::add(const MemoryLocation &Loc) { 318 addMemoryLocation(Loc, AliasSet::NoAccess); 319 } 320 321 void AliasSetTracker::add(LoadInst *LI) { 322 if (isStrongerThanMonotonic(LI->getOrdering())) 323 return addUnknown(LI); 324 addMemoryLocation(MemoryLocation::get(LI), AliasSet::RefAccess); 325 } 326 327 void AliasSetTracker::add(StoreInst *SI) { 328 if (isStrongerThanMonotonic(SI->getOrdering())) 329 return addUnknown(SI); 330 addMemoryLocation(MemoryLocation::get(SI), AliasSet::ModAccess); 331 } 332 333 void AliasSetTracker::add(VAArgInst *VAAI) { 334 addMemoryLocation(MemoryLocation::get(VAAI), AliasSet::ModRefAccess); 335 } 336 337 void AliasSetTracker::add(AnyMemSetInst *MSI) { 338 addMemoryLocation(MemoryLocation::getForDest(MSI), AliasSet::ModAccess); 339 } 340 341 void AliasSetTracker::add(AnyMemTransferInst *MTI) { 342 addMemoryLocation(MemoryLocation::getForDest(MTI), AliasSet::ModAccess); 343 addMemoryLocation(MemoryLocation::getForSource(MTI), AliasSet::RefAccess); 344 } 345 346 void AliasSetTracker::addUnknown(Instruction *Inst) { 347 if (isa<DbgInfoIntrinsic>(Inst)) 348 return; // Ignore DbgInfo Intrinsics. 349 350 if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { 351 // These intrinsics will show up as affecting memory, but they are just 352 // markers. 353 switch (II->getIntrinsicID()) { 354 default: 355 break; 356 // FIXME: Add lifetime/invariant intrinsics (See: PR30807). 357 case Intrinsic::assume: 358 case Intrinsic::experimental_noalias_scope_decl: 359 case Intrinsic::sideeffect: 360 case Intrinsic::pseudoprobe: 361 return; 362 } 363 } 364 if (!Inst->mayReadOrWriteMemory()) 365 return; // doesn't alias anything 366 367 if (AliasSet *AS = findAliasSetForUnknownInst(Inst)) { 368 AS->addUnknownInst(Inst, AA); 369 return; 370 } 371 AliasSets.push_back(new AliasSet()); 372 AliasSets.back().addUnknownInst(Inst, AA); 373 } 374 375 void AliasSetTracker::add(Instruction *I) { 376 // Dispatch to one of the other add methods. 377 if (LoadInst *LI = dyn_cast<LoadInst>(I)) 378 return add(LI); 379 if (StoreInst *SI = dyn_cast<StoreInst>(I)) 380 return add(SI); 381 if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I)) 382 return add(VAAI); 383 if (AnyMemSetInst *MSI = dyn_cast<AnyMemSetInst>(I)) 384 return add(MSI); 385 if (AnyMemTransferInst *MTI = dyn_cast<AnyMemTransferInst>(I)) 386 return add(MTI); 387 388 // Handle all calls with known mod/ref sets genericall 389 if (auto *Call = dyn_cast<CallBase>(I)) 390 if (Call->onlyAccessesArgMemory()) { 391 auto getAccessFromModRef = [](ModRefInfo MRI) { 392 if (isRefSet(MRI) && isModSet(MRI)) 393 return AliasSet::ModRefAccess; 394 else if (isModSet(MRI)) 395 return AliasSet::ModAccess; 396 else if (isRefSet(MRI)) 397 return AliasSet::RefAccess; 398 else 399 return AliasSet::NoAccess; 400 }; 401 402 ModRefInfo CallMask = AA.getMemoryEffects(Call).getModRef(); 403 404 // Some intrinsics are marked as modifying memory for control flow 405 // modelling purposes, but don't actually modify any specific memory 406 // location. 407 using namespace PatternMatch; 408 if (Call->use_empty() && 409 match(Call, m_Intrinsic<Intrinsic::invariant_start>())) 410 CallMask &= ModRefInfo::Ref; 411 412 for (auto IdxArgPair : enumerate(Call->args())) { 413 int ArgIdx = IdxArgPair.index(); 414 const Value *Arg = IdxArgPair.value(); 415 if (!Arg->getType()->isPointerTy()) 416 continue; 417 MemoryLocation ArgLoc = 418 MemoryLocation::getForArgument(Call, ArgIdx, nullptr); 419 ModRefInfo ArgMask = AA.getArgModRefInfo(Call, ArgIdx); 420 ArgMask &= CallMask; 421 if (!isNoModRef(ArgMask)) 422 addMemoryLocation(ArgLoc, getAccessFromModRef(ArgMask)); 423 } 424 return; 425 } 426 427 return addUnknown(I); 428 } 429 430 void AliasSetTracker::add(BasicBlock &BB) { 431 for (auto &I : BB) 432 add(&I); 433 } 434 435 void AliasSetTracker::add(const AliasSetTracker &AST) { 436 assert(&AA == &AST.AA && 437 "Merging AliasSetTracker objects with different Alias Analyses!"); 438 439 // Loop over all of the alias sets in AST, adding the members contained 440 // therein into the current alias sets. This can cause alias sets to be 441 // merged together in the current AST. 442 for (const AliasSet &AS : AST) { 443 if (AS.Forward) 444 continue; // Ignore forwarding alias sets 445 446 // If there are any call sites in the alias set, add them to this AST. 447 for (Instruction *Inst : AS.UnknownInsts) 448 add(Inst); 449 450 // Loop over all of the memory locations in this alias set. 451 for (const MemoryLocation &ASMemLoc : AS.MemoryLocs) 452 addMemoryLocation(ASMemLoc, (AliasSet::AccessLattice)AS.Access); 453 } 454 } 455 456 AliasSet &AliasSetTracker::mergeAllAliasSets() { 457 assert(!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold) && 458 "Full merge should happen once, when the saturation threshold is " 459 "reached"); 460 461 // Collect all alias sets, so that we can drop references with impunity 462 // without worrying about iterator invalidation. 463 std::vector<AliasSet *> ASVector; 464 ASVector.reserve(SaturationThreshold); 465 for (AliasSet &AS : *this) 466 ASVector.push_back(&AS); 467 468 // Copy all instructions and memory locations into a new set, and forward all 469 // other sets to it. 470 AliasSets.push_back(new AliasSet()); 471 AliasAnyAS = &AliasSets.back(); 472 AliasAnyAS->Alias = AliasSet::SetMayAlias; 473 AliasAnyAS->Access = AliasSet::ModRefAccess; 474 AliasAnyAS->AliasAny = true; 475 476 for (auto *Cur : ASVector) { 477 // If Cur was already forwarding, just forward to the new AS instead. 478 AliasSet *FwdTo = Cur->Forward; 479 if (FwdTo) { 480 Cur->Forward = AliasAnyAS; 481 AliasAnyAS->addRef(); 482 FwdTo->dropRef(*this); 483 continue; 484 } 485 486 // Otherwise, perform the actual merge. 487 AliasAnyAS->mergeSetIn(*Cur, *this, AA); 488 } 489 490 return *AliasAnyAS; 491 } 492 493 AliasSet &AliasSetTracker::addMemoryLocation(MemoryLocation Loc, 494 AliasSet::AccessLattice E) { 495 AliasSet &AS = getAliasSetFor(Loc); 496 AS.Access |= E; 497 498 if (!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold)) { 499 // The AST is now saturated. From here on, we conservatively consider all 500 // elements to alias each-other. 501 return mergeAllAliasSets(); 502 } 503 504 return AS; 505 } 506 507 //===----------------------------------------------------------------------===// 508 // AliasSet/AliasSetTracker Printing Support 509 //===----------------------------------------------------------------------===// 510 511 void AliasSet::print(raw_ostream &OS) const { 512 OS << " AliasSet[" << (const void*)this << ", " << RefCount << "] "; 513 OS << (Alias == SetMustAlias ? "must" : "may") << " alias, "; 514 switch (Access) { 515 case NoAccess: OS << "No access "; break; 516 case RefAccess: OS << "Ref "; break; 517 case ModAccess: OS << "Mod "; break; 518 case ModRefAccess: OS << "Mod/Ref "; break; 519 default: llvm_unreachable("Bad value for Access!"); 520 } 521 if (Forward) 522 OS << " forwarding to " << (void*)Forward; 523 524 if (!MemoryLocs.empty()) { 525 ListSeparator LS; 526 OS << "Memory locations: "; 527 for (const MemoryLocation &MemLoc : MemoryLocs) { 528 OS << LS; 529 MemLoc.Ptr->printAsOperand(OS << "("); 530 if (MemLoc.Size == LocationSize::afterPointer()) 531 OS << ", unknown after)"; 532 else if (MemLoc.Size == LocationSize::beforeOrAfterPointer()) 533 OS << ", unknown before-or-after)"; 534 else 535 OS << ", " << MemLoc.Size << ")"; 536 } 537 } 538 if (!UnknownInsts.empty()) { 539 ListSeparator LS; 540 OS << "\n " << UnknownInsts.size() << " Unknown instructions: "; 541 for (Instruction *I : UnknownInsts) { 542 OS << LS; 543 if (I->hasName()) 544 I->printAsOperand(OS); 545 else 546 I->print(OS); 547 } 548 } 549 OS << "\n"; 550 } 551 552 void AliasSetTracker::print(raw_ostream &OS) const { 553 OS << "Alias Set Tracker: " << AliasSets.size(); 554 if (AliasAnyAS) 555 OS << " (Saturated)"; 556 OS << " alias sets for " << PointerMap.size() << " pointer values.\n"; 557 for (const AliasSet &AS : *this) 558 AS.print(OS); 559 OS << "\n"; 560 } 561 562 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 563 LLVM_DUMP_METHOD void AliasSet::dump() const { print(dbgs()); } 564 LLVM_DUMP_METHOD void AliasSetTracker::dump() const { print(dbgs()); } 565 #endif 566 567 //===----------------------------------------------------------------------===// 568 // AliasSetPrinter Pass 569 //===----------------------------------------------------------------------===// 570 571 AliasSetsPrinterPass::AliasSetsPrinterPass(raw_ostream &OS) : OS(OS) {} 572 573 PreservedAnalyses AliasSetsPrinterPass::run(Function &F, 574 FunctionAnalysisManager &AM) { 575 auto &AA = AM.getResult<AAManager>(F); 576 BatchAAResults BatchAA(AA); 577 AliasSetTracker Tracker(BatchAA); 578 OS << "Alias sets for function '" << F.getName() << "':\n"; 579 for (Instruction &I : instructions(F)) 580 Tracker.add(&I); 581 Tracker.print(OS); 582 return PreservedAnalyses::all(); 583 } 584