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::allow_runtime_check: 358 case Intrinsic::allow_ubsan_check: 359 case Intrinsic::assume: 360 case Intrinsic::experimental_noalias_scope_decl: 361 case Intrinsic::sideeffect: 362 case Intrinsic::pseudoprobe: 363 return; 364 } 365 } 366 if (!Inst->mayReadOrWriteMemory()) 367 return; // doesn't alias anything 368 369 if (AliasSet *AS = findAliasSetForUnknownInst(Inst)) { 370 AS->addUnknownInst(Inst, AA); 371 return; 372 } 373 AliasSets.push_back(new AliasSet()); 374 AliasSets.back().addUnknownInst(Inst, AA); 375 } 376 377 void AliasSetTracker::add(Instruction *I) { 378 // Dispatch to one of the other add methods. 379 if (LoadInst *LI = dyn_cast<LoadInst>(I)) 380 return add(LI); 381 if (StoreInst *SI = dyn_cast<StoreInst>(I)) 382 return add(SI); 383 if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I)) 384 return add(VAAI); 385 if (AnyMemSetInst *MSI = dyn_cast<AnyMemSetInst>(I)) 386 return add(MSI); 387 if (AnyMemTransferInst *MTI = dyn_cast<AnyMemTransferInst>(I)) 388 return add(MTI); 389 390 // Handle all calls with known mod/ref sets genericall 391 if (auto *Call = dyn_cast<CallBase>(I)) 392 if (Call->onlyAccessesArgMemory()) { 393 auto getAccessFromModRef = [](ModRefInfo MRI) { 394 if (isRefSet(MRI) && isModSet(MRI)) 395 return AliasSet::ModRefAccess; 396 else if (isModSet(MRI)) 397 return AliasSet::ModAccess; 398 else if (isRefSet(MRI)) 399 return AliasSet::RefAccess; 400 else 401 return AliasSet::NoAccess; 402 }; 403 404 ModRefInfo CallMask = AA.getMemoryEffects(Call).getModRef(); 405 406 // Some intrinsics are marked as modifying memory for control flow 407 // modelling purposes, but don't actually modify any specific memory 408 // location. 409 using namespace PatternMatch; 410 if (Call->use_empty() && 411 match(Call, m_Intrinsic<Intrinsic::invariant_start>())) 412 CallMask &= ModRefInfo::Ref; 413 414 for (auto IdxArgPair : enumerate(Call->args())) { 415 int ArgIdx = IdxArgPair.index(); 416 const Value *Arg = IdxArgPair.value(); 417 if (!Arg->getType()->isPointerTy()) 418 continue; 419 MemoryLocation ArgLoc = 420 MemoryLocation::getForArgument(Call, ArgIdx, nullptr); 421 ModRefInfo ArgMask = AA.getArgModRefInfo(Call, ArgIdx); 422 ArgMask &= CallMask; 423 if (!isNoModRef(ArgMask)) 424 addMemoryLocation(ArgLoc, getAccessFromModRef(ArgMask)); 425 } 426 return; 427 } 428 429 return addUnknown(I); 430 } 431 432 void AliasSetTracker::add(BasicBlock &BB) { 433 for (auto &I : BB) 434 add(&I); 435 } 436 437 void AliasSetTracker::add(const AliasSetTracker &AST) { 438 assert(&AA == &AST.AA && 439 "Merging AliasSetTracker objects with different Alias Analyses!"); 440 441 // Loop over all of the alias sets in AST, adding the members contained 442 // therein into the current alias sets. This can cause alias sets to be 443 // merged together in the current AST. 444 for (const AliasSet &AS : AST) { 445 if (AS.Forward) 446 continue; // Ignore forwarding alias sets 447 448 // If there are any call sites in the alias set, add them to this AST. 449 for (Instruction *Inst : AS.UnknownInsts) 450 add(Inst); 451 452 // Loop over all of the memory locations in this alias set. 453 for (const MemoryLocation &ASMemLoc : AS.MemoryLocs) 454 addMemoryLocation(ASMemLoc, (AliasSet::AccessLattice)AS.Access); 455 } 456 } 457 458 AliasSet &AliasSetTracker::mergeAllAliasSets() { 459 assert(!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold) && 460 "Full merge should happen once, when the saturation threshold is " 461 "reached"); 462 463 // Collect all alias sets, so that we can drop references with impunity 464 // without worrying about iterator invalidation. 465 std::vector<AliasSet *> ASVector; 466 ASVector.reserve(SaturationThreshold); 467 for (AliasSet &AS : *this) 468 ASVector.push_back(&AS); 469 470 // Copy all instructions and memory locations into a new set, and forward all 471 // other sets to it. 472 AliasSets.push_back(new AliasSet()); 473 AliasAnyAS = &AliasSets.back(); 474 AliasAnyAS->Alias = AliasSet::SetMayAlias; 475 AliasAnyAS->Access = AliasSet::ModRefAccess; 476 AliasAnyAS->AliasAny = true; 477 478 for (auto *Cur : ASVector) { 479 // If Cur was already forwarding, just forward to the new AS instead. 480 AliasSet *FwdTo = Cur->Forward; 481 if (FwdTo) { 482 Cur->Forward = AliasAnyAS; 483 AliasAnyAS->addRef(); 484 FwdTo->dropRef(*this); 485 continue; 486 } 487 488 // Otherwise, perform the actual merge. 489 AliasAnyAS->mergeSetIn(*Cur, *this, AA); 490 } 491 492 return *AliasAnyAS; 493 } 494 495 AliasSet &AliasSetTracker::addMemoryLocation(MemoryLocation Loc, 496 AliasSet::AccessLattice E) { 497 AliasSet &AS = getAliasSetFor(Loc); 498 AS.Access |= E; 499 500 if (!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold)) { 501 // The AST is now saturated. From here on, we conservatively consider all 502 // elements to alias each-other. 503 return mergeAllAliasSets(); 504 } 505 506 return AS; 507 } 508 509 //===----------------------------------------------------------------------===// 510 // AliasSet/AliasSetTracker Printing Support 511 //===----------------------------------------------------------------------===// 512 513 void AliasSet::print(raw_ostream &OS) const { 514 OS << " AliasSet[" << (const void*)this << ", " << RefCount << "] "; 515 OS << (Alias == SetMustAlias ? "must" : "may") << " alias, "; 516 switch (Access) { 517 case NoAccess: OS << "No access "; break; 518 case RefAccess: OS << "Ref "; break; 519 case ModAccess: OS << "Mod "; break; 520 case ModRefAccess: OS << "Mod/Ref "; break; 521 default: llvm_unreachable("Bad value for Access!"); 522 } 523 if (Forward) 524 OS << " forwarding to " << (void*)Forward; 525 526 if (!MemoryLocs.empty()) { 527 ListSeparator LS; 528 OS << "Memory locations: "; 529 for (const MemoryLocation &MemLoc : MemoryLocs) { 530 OS << LS; 531 MemLoc.Ptr->printAsOperand(OS << "("); 532 if (MemLoc.Size == LocationSize::afterPointer()) 533 OS << ", unknown after)"; 534 else if (MemLoc.Size == LocationSize::beforeOrAfterPointer()) 535 OS << ", unknown before-or-after)"; 536 else 537 OS << ", " << MemLoc.Size << ")"; 538 } 539 } 540 if (!UnknownInsts.empty()) { 541 ListSeparator LS; 542 OS << "\n " << UnknownInsts.size() << " Unknown instructions: "; 543 for (Instruction *I : UnknownInsts) { 544 OS << LS; 545 if (I->hasName()) 546 I->printAsOperand(OS); 547 else 548 I->print(OS); 549 } 550 } 551 OS << "\n"; 552 } 553 554 void AliasSetTracker::print(raw_ostream &OS) const { 555 OS << "Alias Set Tracker: " << AliasSets.size(); 556 if (AliasAnyAS) 557 OS << " (Saturated)"; 558 OS << " alias sets for " << PointerMap.size() << " pointer values.\n"; 559 for (const AliasSet &AS : *this) 560 AS.print(OS); 561 OS << "\n"; 562 } 563 564 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 565 LLVM_DUMP_METHOD void AliasSet::dump() const { print(dbgs()); } 566 LLVM_DUMP_METHOD void AliasSetTracker::dump() const { print(dbgs()); } 567 #endif 568 569 //===----------------------------------------------------------------------===// 570 // AliasSetPrinter Pass 571 //===----------------------------------------------------------------------===// 572 573 AliasSetsPrinterPass::AliasSetsPrinterPass(raw_ostream &OS) : OS(OS) {} 574 575 PreservedAnalyses AliasSetsPrinterPass::run(Function &F, 576 FunctionAnalysisManager &AM) { 577 auto &AA = AM.getResult<AAManager>(F); 578 BatchAAResults BatchAA(AA); 579 AliasSetTracker Tracker(BatchAA); 580 OS << "Alias sets for function '" << F.getName() << "':\n"; 581 for (Instruction &I : instructions(F)) 582 Tracker.add(&I); 583 Tracker.print(OS); 584 return PreservedAnalyses::all(); 585 } 586