10b57cec5SDimitry Andric //==- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation --==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the generic AliasAnalysis interface which is used as the 100b57cec5SDimitry Andric // common interface used by all clients and implementations of alias analysis. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // This file also implements the default version of the AliasAnalysis interface 130b57cec5SDimitry Andric // that is to be used when no other implementation is specified. This does some 140b57cec5SDimitry Andric // simple tests that detect obvious cases: two different global pointers cannot 150b57cec5SDimitry Andric // alias, a global cannot alias a malloc, two different mallocs cannot alias, 160b57cec5SDimitry Andric // etc. 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric // This alias analysis implementation really isn't very good for anything, but 190b57cec5SDimitry Andric // it is very fast, and makes a nice clean default implementation. Because it 200b57cec5SDimitry Andric // handles lots of little corner cases, other, more complex, alias analysis 210b57cec5SDimitry Andric // implementations may choose to rely on this pass to resolve these simple and 220b57cec5SDimitry Andric // easy cases. 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 27e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/CaptureTracking.h" 300b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 310b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h" 320b57cec5SDimitry Andric #include "llvm/Analysis/ObjCARCAliasAnalysis.h" 330b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" 340b57cec5SDimitry Andric #include "llvm/Analysis/ScopedNoAliasAA.h" 350b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 360b57cec5SDimitry Andric #include "llvm/Analysis/TypeBasedAliasAnalysis.h" 370b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 380b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 390b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 400b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 410b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 420b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 430b57cec5SDimitry Andric #include "llvm/IR/Type.h" 440b57cec5SDimitry Andric #include "llvm/IR/Value.h" 45480093f4SDimitry Andric #include "llvm/InitializePasses.h" 460b57cec5SDimitry Andric #include "llvm/Pass.h" 470b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h" 480b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 490b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 500b57cec5SDimitry Andric #include <algorithm> 510b57cec5SDimitry Andric #include <cassert> 520b57cec5SDimitry Andric #include <functional> 530b57cec5SDimitry Andric #include <iterator> 540b57cec5SDimitry Andric 55e8d8bef9SDimitry Andric #define DEBUG_TYPE "aa" 56e8d8bef9SDimitry Andric 570b57cec5SDimitry Andric using namespace llvm; 580b57cec5SDimitry Andric 59e8d8bef9SDimitry Andric STATISTIC(NumNoAlias, "Number of NoAlias results"); 60e8d8bef9SDimitry Andric STATISTIC(NumMayAlias, "Number of MayAlias results"); 61e8d8bef9SDimitry Andric STATISTIC(NumMustAlias, "Number of MustAlias results"); 62e8d8bef9SDimitry Andric 63fe6060f1SDimitry Andric namespace llvm { 640b57cec5SDimitry Andric /// Allow disabling BasicAA from the AA results. This is particularly useful 650b57cec5SDimitry Andric /// when testing to isolate a single AA implementation. 66e8d8bef9SDimitry Andric cl::opt<bool> DisableBasicAA("disable-basic-aa", cl::Hidden, cl::init(false)); 67fe6060f1SDimitry Andric } // namespace llvm 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric #ifndef NDEBUG 70fe6060f1SDimitry Andric /// Print a trace of alias analysis queries and their results. 71fe6060f1SDimitry Andric static cl::opt<bool> EnableAATrace("aa-trace", cl::Hidden, cl::init(false)); 72fe6060f1SDimitry Andric #else 73fe6060f1SDimitry Andric static const bool EnableAATrace = false; 74fe6060f1SDimitry Andric #endif 750b57cec5SDimitry Andric 76*6e516c87SDimitry Andric AAResults::AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {} 77*6e516c87SDimitry Andric 780b57cec5SDimitry Andric AAResults::AAResults(AAResults &&Arg) 79bdd1243dSDimitry Andric : TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {} 800b57cec5SDimitry Andric 81bdd1243dSDimitry Andric AAResults::~AAResults() {} 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA, 840b57cec5SDimitry Andric FunctionAnalysisManager::Invalidator &Inv) { 850b57cec5SDimitry Andric // AAResults preserves the AAManager by default, due to the stateless nature 860b57cec5SDimitry Andric // of AliasAnalysis. There is no need to check whether it has been preserved 870b57cec5SDimitry Andric // explicitly. Check if any module dependency was invalidated and caused the 880b57cec5SDimitry Andric // AAManager to be invalidated. Invalidate ourselves in that case. 890b57cec5SDimitry Andric auto PAC = PA.getChecker<AAManager>(); 900b57cec5SDimitry Andric if (!PAC.preservedWhenStateless()) 910b57cec5SDimitry Andric return true; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Check if any of the function dependencies were invalidated, and invalidate 940b57cec5SDimitry Andric // ourselves in that case. 950b57cec5SDimitry Andric for (AnalysisKey *ID : AADeps) 960b57cec5SDimitry Andric if (Inv.invalidate(ID, F, PA)) 970b57cec5SDimitry Andric return true; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric // Everything we depend on is still fine, so are we. Nothing to invalidate. 1000b57cec5SDimitry Andric return false; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1040b57cec5SDimitry Andric // Default chaining methods 1050b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric AliasResult AAResults::alias(const MemoryLocation &LocA, 1080b57cec5SDimitry Andric const MemoryLocation &LocB) { 109bdd1243dSDimitry Andric SimpleAAQueryInfo AAQIP(*this); 110bdd1243dSDimitry Andric return alias(LocA, LocB, AAQIP, nullptr); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric AliasResult AAResults::alias(const MemoryLocation &LocA, 114bdd1243dSDimitry Andric const MemoryLocation &LocB, AAQueryInfo &AAQI, 115bdd1243dSDimitry Andric const Instruction *CtxI) { 116fe6060f1SDimitry Andric AliasResult Result = AliasResult::MayAlias; 117e8d8bef9SDimitry Andric 118fe6060f1SDimitry Andric if (EnableAATrace) { 119fe6060f1SDimitry Andric for (unsigned I = 0; I < AAQI.Depth; ++I) 120fe6060f1SDimitry Andric dbgs() << " "; 121fe6060f1SDimitry Andric dbgs() << "Start " << *LocA.Ptr << " @ " << LocA.Size << ", " 122fe6060f1SDimitry Andric << *LocB.Ptr << " @ " << LocB.Size << "\n"; 123fe6060f1SDimitry Andric } 124fe6060f1SDimitry Andric 125fe6060f1SDimitry Andric AAQI.Depth++; 1260b57cec5SDimitry Andric for (const auto &AA : AAs) { 127bdd1243dSDimitry Andric Result = AA->alias(LocA, LocB, AAQI, CtxI); 128fe6060f1SDimitry Andric if (Result != AliasResult::MayAlias) 129e8d8bef9SDimitry Andric break; 1300b57cec5SDimitry Andric } 131fe6060f1SDimitry Andric AAQI.Depth--; 132e8d8bef9SDimitry Andric 133fe6060f1SDimitry Andric if (EnableAATrace) { 134fe6060f1SDimitry Andric for (unsigned I = 0; I < AAQI.Depth; ++I) 135fe6060f1SDimitry Andric dbgs() << " "; 136fe6060f1SDimitry Andric dbgs() << "End " << *LocA.Ptr << " @ " << LocA.Size << ", " 137fe6060f1SDimitry Andric << *LocB.Ptr << " @ " << LocB.Size << " = " << Result << "\n"; 138fe6060f1SDimitry Andric } 139fe6060f1SDimitry Andric 140fe6060f1SDimitry Andric if (AAQI.Depth == 0) { 141fe6060f1SDimitry Andric if (Result == AliasResult::NoAlias) 142e8d8bef9SDimitry Andric ++NumNoAlias; 143fe6060f1SDimitry Andric else if (Result == AliasResult::MustAlias) 144e8d8bef9SDimitry Andric ++NumMustAlias; 145e8d8bef9SDimitry Andric else 146e8d8bef9SDimitry Andric ++NumMayAlias; 147e8d8bef9SDimitry Andric } 148e8d8bef9SDimitry Andric return Result; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 151bdd1243dSDimitry Andric ModRefInfo AAResults::getModRefInfoMask(const MemoryLocation &Loc, 152bdd1243dSDimitry Andric bool IgnoreLocals) { 153bdd1243dSDimitry Andric SimpleAAQueryInfo AAQIP(*this); 154bdd1243dSDimitry Andric return getModRefInfoMask(Loc, AAQIP, IgnoreLocals); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 157bdd1243dSDimitry Andric ModRefInfo AAResults::getModRefInfoMask(const MemoryLocation &Loc, 158bdd1243dSDimitry Andric AAQueryInfo &AAQI, bool IgnoreLocals) { 1590b57cec5SDimitry Andric ModRefInfo Result = ModRefInfo::ModRef; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric for (const auto &AA : AAs) { 162bdd1243dSDimitry Andric Result &= AA->getModRefInfoMask(Loc, AAQI, IgnoreLocals); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 1650b57cec5SDimitry Andric if (isNoModRef(Result)) 1660b57cec5SDimitry Andric return ModRefInfo::NoModRef; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric return Result; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 172bdd1243dSDimitry Andric ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) { 173bdd1243dSDimitry Andric ModRefInfo Result = ModRefInfo::ModRef; 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric for (const auto &AA : AAs) { 176bdd1243dSDimitry Andric Result &= AA->getArgModRefInfo(Call, ArgIdx); 177bdd1243dSDimitry Andric 178bdd1243dSDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 179bdd1243dSDimitry Andric if (isNoModRef(Result)) 180bdd1243dSDimitry Andric return ModRefInfo::NoModRef; 181bdd1243dSDimitry Andric } 182bdd1243dSDimitry Andric 183bdd1243dSDimitry Andric return Result; 184bdd1243dSDimitry Andric } 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric ModRefInfo AAResults::getModRefInfo(const Instruction *I, 187bdd1243dSDimitry Andric const CallBase *Call2) { 188bdd1243dSDimitry Andric SimpleAAQueryInfo AAQIP(*this); 1890b57cec5SDimitry Andric return getModRefInfo(I, Call2, AAQIP); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 192bdd1243dSDimitry Andric ModRefInfo AAResults::getModRefInfo(const Instruction *I, const CallBase *Call2, 1930b57cec5SDimitry Andric AAQueryInfo &AAQI) { 1940b57cec5SDimitry Andric // We may have two calls. 1950b57cec5SDimitry Andric if (const auto *Call1 = dyn_cast<CallBase>(I)) { 1960b57cec5SDimitry Andric // Check if the two calls modify the same memory. 1970b57cec5SDimitry Andric return getModRefInfo(Call1, Call2, AAQI); 198349cc55cSDimitry Andric } 1990b57cec5SDimitry Andric // If this is a fence, just return ModRef. 200349cc55cSDimitry Andric if (I->isFenceLike()) 2010b57cec5SDimitry Andric return ModRefInfo::ModRef; 2020b57cec5SDimitry Andric // Otherwise, check if the call modifies or references the 2030b57cec5SDimitry Andric // location this memory access defines. The best we can say 2040b57cec5SDimitry Andric // is that if the call references what this instruction 2050b57cec5SDimitry Andric // defines, it must be clobbered by this location. 2060b57cec5SDimitry Andric const MemoryLocation DefLoc = MemoryLocation::get(I); 2070b57cec5SDimitry Andric ModRefInfo MR = getModRefInfo(Call2, DefLoc, AAQI); 2080b57cec5SDimitry Andric if (isModOrRefSet(MR)) 209bdd1243dSDimitry Andric return ModRefInfo::ModRef; 2100b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const CallBase *Call, 2140b57cec5SDimitry Andric const MemoryLocation &Loc, 2150b57cec5SDimitry Andric AAQueryInfo &AAQI) { 2160b57cec5SDimitry Andric ModRefInfo Result = ModRefInfo::ModRef; 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric for (const auto &AA : AAs) { 219bdd1243dSDimitry Andric Result &= AA->getModRefInfo(Call, Loc, AAQI); 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 2220b57cec5SDimitry Andric if (isNoModRef(Result)) 2230b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // Try to refine the mod-ref info further using other API entry points to the 2270b57cec5SDimitry Andric // aggregate set of AA results. 228bdd1243dSDimitry Andric 229bdd1243dSDimitry Andric // We can completely ignore inaccessible memory here, because MemoryLocations 230bdd1243dSDimitry Andric // can only reference accessible memory. 231bdd1243dSDimitry Andric auto ME = getMemoryEffects(Call, AAQI) 23206c3fb27SDimitry Andric .getWithoutLoc(IRMemLocation::InaccessibleMem); 233bdd1243dSDimitry Andric if (ME.doesNotAccessMemory()) 2340b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2350b57cec5SDimitry Andric 23606c3fb27SDimitry Andric ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem); 23706c3fb27SDimitry Andric ModRefInfo OtherMR = ME.getWithoutLoc(IRMemLocation::ArgMem).getModRef(); 238bdd1243dSDimitry Andric if ((ArgMR | OtherMR) != OtherMR) { 239bdd1243dSDimitry Andric // Refine the modref info for argument memory. We only bother to do this 240bdd1243dSDimitry Andric // if ArgMR is not a subset of OtherMR, otherwise this won't have an impact 241bdd1243dSDimitry Andric // on the final result. 2420b57cec5SDimitry Andric ModRefInfo AllArgsMask = ModRefInfo::NoModRef; 2430eae32dcSDimitry Andric for (const auto &I : llvm::enumerate(Call->args())) { 2440eae32dcSDimitry Andric const Value *Arg = I.value(); 2450b57cec5SDimitry Andric if (!Arg->getType()->isPointerTy()) 2460b57cec5SDimitry Andric continue; 2470eae32dcSDimitry Andric unsigned ArgIdx = I.index(); 248bdd1243dSDimitry Andric MemoryLocation ArgLoc = MemoryLocation::getForArgument(Call, ArgIdx, TLI); 249bdd1243dSDimitry Andric AliasResult ArgAlias = alias(ArgLoc, Loc, AAQI, Call); 250bdd1243dSDimitry Andric if (ArgAlias != AliasResult::NoAlias) 251bdd1243dSDimitry Andric AllArgsMask |= getArgModRefInfo(Call, ArgIdx); 2520b57cec5SDimitry Andric } 253bdd1243dSDimitry Andric ArgMR &= AllArgsMask; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 256bdd1243dSDimitry Andric Result &= ArgMR | OtherMR; 257bdd1243dSDimitry Andric 258bdd1243dSDimitry Andric // Apply the ModRef mask. This ensures that if Loc is a constant memory 259bdd1243dSDimitry Andric // location, we take into account the fact that the call definitely could not 2600b57cec5SDimitry Andric // modify the memory location. 261bdd1243dSDimitry Andric if (!isNoModRef(Result)) 262bdd1243dSDimitry Andric Result &= getModRefInfoMask(Loc); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric return Result; 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const CallBase *Call1, 2680b57cec5SDimitry Andric const CallBase *Call2, AAQueryInfo &AAQI) { 2690b57cec5SDimitry Andric ModRefInfo Result = ModRefInfo::ModRef; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric for (const auto &AA : AAs) { 272bdd1243dSDimitry Andric Result &= AA->getModRefInfo(Call1, Call2, AAQI); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 2750b57cec5SDimitry Andric if (isNoModRef(Result)) 2760b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Try to refine the mod-ref info further using other API entry points to the 2800b57cec5SDimitry Andric // aggregate set of AA results. 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // If Call1 or Call2 are readnone, they don't interact. 283bdd1243dSDimitry Andric auto Call1B = getMemoryEffects(Call1, AAQI); 284bdd1243dSDimitry Andric if (Call1B.doesNotAccessMemory()) 2850b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2860b57cec5SDimitry Andric 287bdd1243dSDimitry Andric auto Call2B = getMemoryEffects(Call2, AAQI); 288bdd1243dSDimitry Andric if (Call2B.doesNotAccessMemory()) 2890b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // If they both only read from memory, there is no dependence. 292bdd1243dSDimitry Andric if (Call1B.onlyReadsMemory() && Call2B.onlyReadsMemory()) 2930b57cec5SDimitry Andric return ModRefInfo::NoModRef; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // If Call1 only reads memory, the only dependence on Call2 can be 2960b57cec5SDimitry Andric // from Call1 reading memory written by Call2. 297bdd1243dSDimitry Andric if (Call1B.onlyReadsMemory()) 298bdd1243dSDimitry Andric Result &= ModRefInfo::Ref; 299bdd1243dSDimitry Andric else if (Call1B.onlyWritesMemory()) 300bdd1243dSDimitry Andric Result &= ModRefInfo::Mod; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // If Call2 only access memory through arguments, accumulate the mod/ref 3030b57cec5SDimitry Andric // information from Call1's references to the memory referenced by 3040b57cec5SDimitry Andric // Call2's arguments. 305bdd1243dSDimitry Andric if (Call2B.onlyAccessesArgPointees()) { 306bdd1243dSDimitry Andric if (!Call2B.doesAccessArgPointees()) 3070b57cec5SDimitry Andric return ModRefInfo::NoModRef; 3080b57cec5SDimitry Andric ModRefInfo R = ModRefInfo::NoModRef; 3090b57cec5SDimitry Andric for (auto I = Call2->arg_begin(), E = Call2->arg_end(); I != E; ++I) { 3100b57cec5SDimitry Andric const Value *Arg = *I; 3110b57cec5SDimitry Andric if (!Arg->getType()->isPointerTy()) 3120b57cec5SDimitry Andric continue; 3130b57cec5SDimitry Andric unsigned Call2ArgIdx = std::distance(Call2->arg_begin(), I); 3140b57cec5SDimitry Andric auto Call2ArgLoc = 3150b57cec5SDimitry Andric MemoryLocation::getForArgument(Call2, Call2ArgIdx, TLI); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric // ArgModRefC2 indicates what Call2 might do to Call2ArgLoc, and the 3180b57cec5SDimitry Andric // dependence of Call1 on that location is the inverse: 3190b57cec5SDimitry Andric // - If Call2 modifies location, dependence exists if Call1 reads or 3200b57cec5SDimitry Andric // writes. 3210b57cec5SDimitry Andric // - If Call2 only reads location, dependence exists if Call1 writes. 3220b57cec5SDimitry Andric ModRefInfo ArgModRefC2 = getArgModRefInfo(Call2, Call2ArgIdx); 3230b57cec5SDimitry Andric ModRefInfo ArgMask = ModRefInfo::NoModRef; 3240b57cec5SDimitry Andric if (isModSet(ArgModRefC2)) 3250b57cec5SDimitry Andric ArgMask = ModRefInfo::ModRef; 3260b57cec5SDimitry Andric else if (isRefSet(ArgModRefC2)) 3270b57cec5SDimitry Andric ArgMask = ModRefInfo::Mod; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric // ModRefC1 indicates what Call1 might do to Call2ArgLoc, and we use 3300b57cec5SDimitry Andric // above ArgMask to update dependence info. 331bdd1243dSDimitry Andric ArgMask &= getModRefInfo(Call1, Call2ArgLoc, AAQI); 3320b57cec5SDimitry Andric 333bdd1243dSDimitry Andric R = (R | ArgMask) & Result; 334bdd1243dSDimitry Andric if (R == Result) 3350b57cec5SDimitry Andric break; 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 338bdd1243dSDimitry Andric return R; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // If Call1 only accesses memory through arguments, check if Call2 references 3420b57cec5SDimitry Andric // any of the memory referenced by Call1's arguments. If not, return NoModRef. 343bdd1243dSDimitry Andric if (Call1B.onlyAccessesArgPointees()) { 344bdd1243dSDimitry Andric if (!Call1B.doesAccessArgPointees()) 3450b57cec5SDimitry Andric return ModRefInfo::NoModRef; 3460b57cec5SDimitry Andric ModRefInfo R = ModRefInfo::NoModRef; 3470b57cec5SDimitry Andric for (auto I = Call1->arg_begin(), E = Call1->arg_end(); I != E; ++I) { 3480b57cec5SDimitry Andric const Value *Arg = *I; 3490b57cec5SDimitry Andric if (!Arg->getType()->isPointerTy()) 3500b57cec5SDimitry Andric continue; 3510b57cec5SDimitry Andric unsigned Call1ArgIdx = std::distance(Call1->arg_begin(), I); 3520b57cec5SDimitry Andric auto Call1ArgLoc = 3530b57cec5SDimitry Andric MemoryLocation::getForArgument(Call1, Call1ArgIdx, TLI); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric // ArgModRefC1 indicates what Call1 might do to Call1ArgLoc; if Call1 3560b57cec5SDimitry Andric // might Mod Call1ArgLoc, then we care about either a Mod or a Ref by 3570b57cec5SDimitry Andric // Call2. If Call1 might Ref, then we care only about a Mod by Call2. 3580b57cec5SDimitry Andric ModRefInfo ArgModRefC1 = getArgModRefInfo(Call1, Call1ArgIdx); 359e8d8bef9SDimitry Andric ModRefInfo ModRefC2 = getModRefInfo(Call2, Call1ArgLoc, AAQI); 3600b57cec5SDimitry Andric if ((isModSet(ArgModRefC1) && isModOrRefSet(ModRefC2)) || 3610b57cec5SDimitry Andric (isRefSet(ArgModRefC1) && isModSet(ModRefC2))) 362bdd1243dSDimitry Andric R = (R | ArgModRefC1) & Result; 3630b57cec5SDimitry Andric 364bdd1243dSDimitry Andric if (R == Result) 3650b57cec5SDimitry Andric break; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 368bdd1243dSDimitry Andric return R; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric return Result; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 374bdd1243dSDimitry Andric MemoryEffects AAResults::getMemoryEffects(const CallBase *Call, 375bdd1243dSDimitry Andric AAQueryInfo &AAQI) { 376bdd1243dSDimitry Andric MemoryEffects Result = MemoryEffects::unknown(); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric for (const auto &AA : AAs) { 379bdd1243dSDimitry Andric Result &= AA->getMemoryEffects(Call, AAQI); 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 382bdd1243dSDimitry Andric if (Result.doesNotAccessMemory()) 3830b57cec5SDimitry Andric return Result; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric return Result; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 389bdd1243dSDimitry Andric MemoryEffects AAResults::getMemoryEffects(const CallBase *Call) { 390bdd1243dSDimitry Andric SimpleAAQueryInfo AAQI(*this); 391bdd1243dSDimitry Andric return getMemoryEffects(Call, AAQI); 392bdd1243dSDimitry Andric } 393bdd1243dSDimitry Andric 394bdd1243dSDimitry Andric MemoryEffects AAResults::getMemoryEffects(const Function *F) { 395bdd1243dSDimitry Andric MemoryEffects Result = MemoryEffects::unknown(); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric for (const auto &AA : AAs) { 398bdd1243dSDimitry Andric Result &= AA->getMemoryEffects(F); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric // Early-exit the moment we reach the bottom of the lattice. 401bdd1243dSDimitry Andric if (Result.doesNotAccessMemory()) 4020b57cec5SDimitry Andric return Result; 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric return Result; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, AliasResult AR) { 4090b57cec5SDimitry Andric switch (AR) { 410fe6060f1SDimitry Andric case AliasResult::NoAlias: 4110b57cec5SDimitry Andric OS << "NoAlias"; 4120b57cec5SDimitry Andric break; 413fe6060f1SDimitry Andric case AliasResult::MustAlias: 4140b57cec5SDimitry Andric OS << "MustAlias"; 4150b57cec5SDimitry Andric break; 416fe6060f1SDimitry Andric case AliasResult::MayAlias: 4170b57cec5SDimitry Andric OS << "MayAlias"; 4180b57cec5SDimitry Andric break; 419fe6060f1SDimitry Andric case AliasResult::PartialAlias: 4200b57cec5SDimitry Andric OS << "PartialAlias"; 421fe6060f1SDimitry Andric if (AR.hasOffset()) 422fe6060f1SDimitry Andric OS << " (off " << AR.getOffset() << ")"; 4230b57cec5SDimitry Andric break; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric return OS; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 428bdd1243dSDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, ModRefInfo MR) { 429bdd1243dSDimitry Andric switch (MR) { 430bdd1243dSDimitry Andric case ModRefInfo::NoModRef: 431bdd1243dSDimitry Andric OS << "NoModRef"; 432bdd1243dSDimitry Andric break; 433bdd1243dSDimitry Andric case ModRefInfo::Ref: 434bdd1243dSDimitry Andric OS << "Ref"; 435bdd1243dSDimitry Andric break; 436bdd1243dSDimitry Andric case ModRefInfo::Mod: 437bdd1243dSDimitry Andric OS << "Mod"; 438bdd1243dSDimitry Andric break; 439bdd1243dSDimitry Andric case ModRefInfo::ModRef: 440bdd1243dSDimitry Andric OS << "ModRef"; 441bdd1243dSDimitry Andric break; 442bdd1243dSDimitry Andric } 443bdd1243dSDimitry Andric return OS; 444bdd1243dSDimitry Andric } 445bdd1243dSDimitry Andric 446bdd1243dSDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) { 44706c3fb27SDimitry Andric for (IRMemLocation Loc : MemoryEffects::locations()) { 448bdd1243dSDimitry Andric switch (Loc) { 44906c3fb27SDimitry Andric case IRMemLocation::ArgMem: 450bdd1243dSDimitry Andric OS << "ArgMem: "; 451bdd1243dSDimitry Andric break; 45206c3fb27SDimitry Andric case IRMemLocation::InaccessibleMem: 453bdd1243dSDimitry Andric OS << "InaccessibleMem: "; 454bdd1243dSDimitry Andric break; 45506c3fb27SDimitry Andric case IRMemLocation::Other: 456bdd1243dSDimitry Andric OS << "Other: "; 457bdd1243dSDimitry Andric break; 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric OS << ME.getModRef(Loc) << ", "; 460bdd1243dSDimitry Andric } 461bdd1243dSDimitry Andric return OS; 462bdd1243dSDimitry Andric } 463bdd1243dSDimitry Andric 4640b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4650b57cec5SDimitry Andric // Helper method implementation 4660b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const LoadInst *L, 4690b57cec5SDimitry Andric const MemoryLocation &Loc, 4700b57cec5SDimitry Andric AAQueryInfo &AAQI) { 4710b57cec5SDimitry Andric // Be conservative in the face of atomic. 4720b57cec5SDimitry Andric if (isStrongerThan(L->getOrdering(), AtomicOrdering::Unordered)) 4730b57cec5SDimitry Andric return ModRefInfo::ModRef; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric // If the load address doesn't alias the given address, it doesn't read 4760b57cec5SDimitry Andric // or write the specified memory. 4770b57cec5SDimitry Andric if (Loc.Ptr) { 478bdd1243dSDimitry Andric AliasResult AR = alias(MemoryLocation::get(L), Loc, AAQI, L); 479fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 4800b57cec5SDimitry Andric return ModRefInfo::NoModRef; 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric // Otherwise, a load just reads. 4830b57cec5SDimitry Andric return ModRefInfo::Ref; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const StoreInst *S, 4870b57cec5SDimitry Andric const MemoryLocation &Loc, 4880b57cec5SDimitry Andric AAQueryInfo &AAQI) { 4890b57cec5SDimitry Andric // Be conservative in the face of atomic. 4900b57cec5SDimitry Andric if (isStrongerThan(S->getOrdering(), AtomicOrdering::Unordered)) 4910b57cec5SDimitry Andric return ModRefInfo::ModRef; 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric if (Loc.Ptr) { 494bdd1243dSDimitry Andric AliasResult AR = alias(MemoryLocation::get(S), Loc, AAQI, S); 4950b57cec5SDimitry Andric // If the store address cannot alias the pointer in question, then the 4960b57cec5SDimitry Andric // specified memory cannot be modified by the store. 497fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 4980b57cec5SDimitry Andric return ModRefInfo::NoModRef; 4990b57cec5SDimitry Andric 500bdd1243dSDimitry Andric // Examine the ModRef mask. If Mod isn't present, then return NoModRef. 501bdd1243dSDimitry Andric // This ensures that if Loc is a constant memory location, we take into 502bdd1243dSDimitry Andric // account the fact that the store definitely could not modify the memory 503bdd1243dSDimitry Andric // location. 504bdd1243dSDimitry Andric if (!isModSet(getModRefInfoMask(Loc))) 5050b57cec5SDimitry Andric return ModRefInfo::NoModRef; 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Otherwise, a store just writes. 5090b57cec5SDimitry Andric return ModRefInfo::Mod; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const FenceInst *S, 5130b57cec5SDimitry Andric const MemoryLocation &Loc, 5140b57cec5SDimitry Andric AAQueryInfo &AAQI) { 515bdd1243dSDimitry Andric // All we know about a fence instruction is what we get from the ModRef 516bdd1243dSDimitry Andric // mask: if Loc is a constant memory location, the fence definitely could 517bdd1243dSDimitry Andric // not modify it. 518bdd1243dSDimitry Andric if (Loc.Ptr) 519bdd1243dSDimitry Andric return getModRefInfoMask(Loc); 5200b57cec5SDimitry Andric return ModRefInfo::ModRef; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const VAArgInst *V, 5240b57cec5SDimitry Andric const MemoryLocation &Loc, 5250b57cec5SDimitry Andric AAQueryInfo &AAQI) { 5260b57cec5SDimitry Andric if (Loc.Ptr) { 527bdd1243dSDimitry Andric AliasResult AR = alias(MemoryLocation::get(V), Loc, AAQI, V); 5280b57cec5SDimitry Andric // If the va_arg address cannot alias the pointer in question, then the 5290b57cec5SDimitry Andric // specified memory cannot be accessed by the va_arg. 530fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 5310b57cec5SDimitry Andric return ModRefInfo::NoModRef; 5320b57cec5SDimitry Andric 533bdd1243dSDimitry Andric // If the pointer is a pointer to invariant memory, then it could not have 5340b57cec5SDimitry Andric // been modified by this va_arg. 535bdd1243dSDimitry Andric return getModRefInfoMask(Loc, AAQI); 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric // Otherwise, a va_arg reads and writes. 5390b57cec5SDimitry Andric return ModRefInfo::ModRef; 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad, 5430b57cec5SDimitry Andric const MemoryLocation &Loc, 5440b57cec5SDimitry Andric AAQueryInfo &AAQI) { 5450b57cec5SDimitry Andric if (Loc.Ptr) { 546bdd1243dSDimitry Andric // If the pointer is a pointer to invariant memory, 5470b57cec5SDimitry Andric // then it could not have been modified by this catchpad. 548bdd1243dSDimitry Andric return getModRefInfoMask(Loc, AAQI); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric // Otherwise, a catchpad reads and writes. 5520b57cec5SDimitry Andric return ModRefInfo::ModRef; 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet, 5560b57cec5SDimitry Andric const MemoryLocation &Loc, 5570b57cec5SDimitry Andric AAQueryInfo &AAQI) { 5580b57cec5SDimitry Andric if (Loc.Ptr) { 559bdd1243dSDimitry Andric // If the pointer is a pointer to invariant memory, 5600b57cec5SDimitry Andric // then it could not have been modified by this catchpad. 561bdd1243dSDimitry Andric return getModRefInfoMask(Loc, AAQI); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric // Otherwise, a catchret reads and writes. 5650b57cec5SDimitry Andric return ModRefInfo::ModRef; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX, 5690b57cec5SDimitry Andric const MemoryLocation &Loc, 5700b57cec5SDimitry Andric AAQueryInfo &AAQI) { 5710b57cec5SDimitry Andric // Acquire/Release cmpxchg has properties that matter for arbitrary addresses. 5720b57cec5SDimitry Andric if (isStrongerThanMonotonic(CX->getSuccessOrdering())) 5730b57cec5SDimitry Andric return ModRefInfo::ModRef; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric if (Loc.Ptr) { 576bdd1243dSDimitry Andric AliasResult AR = alias(MemoryLocation::get(CX), Loc, AAQI, CX); 5770b57cec5SDimitry Andric // If the cmpxchg address does not alias the location, it does not access 5780b57cec5SDimitry Andric // it. 579fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 5800b57cec5SDimitry Andric return ModRefInfo::NoModRef; 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric return ModRefInfo::ModRef; 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW, 5870b57cec5SDimitry Andric const MemoryLocation &Loc, 5880b57cec5SDimitry Andric AAQueryInfo &AAQI) { 5890b57cec5SDimitry Andric // Acquire/Release atomicrmw has properties that matter for arbitrary addresses. 5900b57cec5SDimitry Andric if (isStrongerThanMonotonic(RMW->getOrdering())) 5910b57cec5SDimitry Andric return ModRefInfo::ModRef; 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric if (Loc.Ptr) { 594bdd1243dSDimitry Andric AliasResult AR = alias(MemoryLocation::get(RMW), Loc, AAQI, RMW); 5950b57cec5SDimitry Andric // If the atomicrmw address does not alias the location, it does not access 5960b57cec5SDimitry Andric // it. 597fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 5980b57cec5SDimitry Andric return ModRefInfo::NoModRef; 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric return ModRefInfo::ModRef; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 604e8d8bef9SDimitry Andric ModRefInfo AAResults::getModRefInfo(const Instruction *I, 605bdd1243dSDimitry Andric const std::optional<MemoryLocation> &OptLoc, 606e8d8bef9SDimitry Andric AAQueryInfo &AAQIP) { 607bdd1243dSDimitry Andric if (OptLoc == std::nullopt) { 608bdd1243dSDimitry Andric if (const auto *Call = dyn_cast<CallBase>(I)) 609bdd1243dSDimitry Andric return getMemoryEffects(Call, AAQIP).getModRef(); 610e8d8bef9SDimitry Andric } 611e8d8bef9SDimitry Andric 61281ad6265SDimitry Andric const MemoryLocation &Loc = OptLoc.value_or(MemoryLocation()); 613e8d8bef9SDimitry Andric 614e8d8bef9SDimitry Andric switch (I->getOpcode()) { 615e8d8bef9SDimitry Andric case Instruction::VAArg: 616e8d8bef9SDimitry Andric return getModRefInfo((const VAArgInst *)I, Loc, AAQIP); 617e8d8bef9SDimitry Andric case Instruction::Load: 618e8d8bef9SDimitry Andric return getModRefInfo((const LoadInst *)I, Loc, AAQIP); 619e8d8bef9SDimitry Andric case Instruction::Store: 620e8d8bef9SDimitry Andric return getModRefInfo((const StoreInst *)I, Loc, AAQIP); 621e8d8bef9SDimitry Andric case Instruction::Fence: 622e8d8bef9SDimitry Andric return getModRefInfo((const FenceInst *)I, Loc, AAQIP); 623e8d8bef9SDimitry Andric case Instruction::AtomicCmpXchg: 624e8d8bef9SDimitry Andric return getModRefInfo((const AtomicCmpXchgInst *)I, Loc, AAQIP); 625e8d8bef9SDimitry Andric case Instruction::AtomicRMW: 626e8d8bef9SDimitry Andric return getModRefInfo((const AtomicRMWInst *)I, Loc, AAQIP); 627e8d8bef9SDimitry Andric case Instruction::Call: 6280eae32dcSDimitry Andric case Instruction::CallBr: 629e8d8bef9SDimitry Andric case Instruction::Invoke: 6300eae32dcSDimitry Andric return getModRefInfo((const CallBase *)I, Loc, AAQIP); 631e8d8bef9SDimitry Andric case Instruction::CatchPad: 632e8d8bef9SDimitry Andric return getModRefInfo((const CatchPadInst *)I, Loc, AAQIP); 633e8d8bef9SDimitry Andric case Instruction::CatchRet: 634e8d8bef9SDimitry Andric return getModRefInfo((const CatchReturnInst *)I, Loc, AAQIP); 635e8d8bef9SDimitry Andric default: 6360eae32dcSDimitry Andric assert(!I->mayReadOrWriteMemory() && 6370eae32dcSDimitry Andric "Unhandled memory access instruction!"); 638e8d8bef9SDimitry Andric return ModRefInfo::NoModRef; 639e8d8bef9SDimitry Andric } 640e8d8bef9SDimitry Andric } 641e8d8bef9SDimitry Andric 6420b57cec5SDimitry Andric /// Return information about whether a particular call site modifies 6430b57cec5SDimitry Andric /// or reads the specified memory location \p MemLoc before instruction \p I 6445ffd83dbSDimitry Andric /// in a BasicBlock. 6450b57cec5SDimitry Andric /// FIXME: this is really just shoring-up a deficiency in alias analysis. 6460b57cec5SDimitry Andric /// BasicAA isn't willing to spend linear time determining whether an alloca 6470b57cec5SDimitry Andric /// was captured before or after this particular call, while we are. However, 6480b57cec5SDimitry Andric /// with a smarter AA in place, this test is just wasting compile time. 6490b57cec5SDimitry Andric ModRefInfo AAResults::callCapturesBefore(const Instruction *I, 6500b57cec5SDimitry Andric const MemoryLocation &MemLoc, 651fe6060f1SDimitry Andric DominatorTree *DT, 652fe6060f1SDimitry Andric AAQueryInfo &AAQI) { 6530b57cec5SDimitry Andric if (!DT) 6540b57cec5SDimitry Andric return ModRefInfo::ModRef; 6550b57cec5SDimitry Andric 656e8d8bef9SDimitry Andric const Value *Object = getUnderlyingObject(MemLoc.Ptr); 657fe6060f1SDimitry Andric if (!isIdentifiedFunctionLocal(Object)) 6580b57cec5SDimitry Andric return ModRefInfo::ModRef; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric const auto *Call = dyn_cast<CallBase>(I); 6610b57cec5SDimitry Andric if (!Call || Call == Object) 6620b57cec5SDimitry Andric return ModRefInfo::ModRef; 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric if (PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true, 6650b57cec5SDimitry Andric /* StoreCaptures */ true, I, DT, 6665ffd83dbSDimitry Andric /* include Object */ true)) 6670b57cec5SDimitry Andric return ModRefInfo::ModRef; 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric unsigned ArgNo = 0; 6700b57cec5SDimitry Andric ModRefInfo R = ModRefInfo::NoModRef; 6710b57cec5SDimitry Andric // Set flag only if no May found and all operands processed. 6720b57cec5SDimitry Andric for (auto CI = Call->data_operands_begin(), CE = Call->data_operands_end(); 6730b57cec5SDimitry Andric CI != CE; ++CI, ++ArgNo) { 6740b57cec5SDimitry Andric // Only look at the no-capture or byval pointer arguments. If this 6750b57cec5SDimitry Andric // pointer were passed to arguments that were neither of these, then it 6760b57cec5SDimitry Andric // couldn't be no-capture. 6770b57cec5SDimitry Andric if (!(*CI)->getType()->isPointerTy() || 678349cc55cSDimitry Andric (!Call->doesNotCapture(ArgNo) && ArgNo < Call->arg_size() && 6790b57cec5SDimitry Andric !Call->isByValArgument(ArgNo))) 6800b57cec5SDimitry Andric continue; 6810b57cec5SDimitry Andric 682bdd1243dSDimitry Andric AliasResult AR = 683bdd1243dSDimitry Andric alias(MemoryLocation::getBeforeOrAfter(*CI), 684bdd1243dSDimitry Andric MemoryLocation::getBeforeOrAfter(Object), AAQI, Call); 6850b57cec5SDimitry Andric // If this is a no-capture pointer argument, see if we can tell that it 6860b57cec5SDimitry Andric // is impossible to alias the pointer we're checking. If not, we have to 6870b57cec5SDimitry Andric // assume that the call could touch the pointer, even though it doesn't 6880b57cec5SDimitry Andric // escape. 689fe6060f1SDimitry Andric if (AR == AliasResult::NoAlias) 6900b57cec5SDimitry Andric continue; 6910b57cec5SDimitry Andric if (Call->doesNotAccessMemory(ArgNo)) 6920b57cec5SDimitry Andric continue; 6930b57cec5SDimitry Andric if (Call->onlyReadsMemory(ArgNo)) { 6940b57cec5SDimitry Andric R = ModRefInfo::Ref; 6950b57cec5SDimitry Andric continue; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric return ModRefInfo::ModRef; 6980b57cec5SDimitry Andric } 699bdd1243dSDimitry Andric return R; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric /// canBasicBlockModify - Return true if it is possible for execution of the 7030b57cec5SDimitry Andric /// specified basic block to modify the location Loc. 7040b57cec5SDimitry Andric /// 7050b57cec5SDimitry Andric bool AAResults::canBasicBlockModify(const BasicBlock &BB, 7060b57cec5SDimitry Andric const MemoryLocation &Loc) { 7070b57cec5SDimitry Andric return canInstructionRangeModRef(BB.front(), BB.back(), Loc, ModRefInfo::Mod); 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric /// canInstructionRangeModRef - Return true if it is possible for the 7110b57cec5SDimitry Andric /// execution of the specified instructions to mod\ref (according to the 7120b57cec5SDimitry Andric /// mode) the location Loc. The instructions to consider are all 7130b57cec5SDimitry Andric /// of the instructions in the range of [I1,I2] INCLUSIVE. 7140b57cec5SDimitry Andric /// I1 and I2 must be in the same basic block. 7150b57cec5SDimitry Andric bool AAResults::canInstructionRangeModRef(const Instruction &I1, 7160b57cec5SDimitry Andric const Instruction &I2, 7170b57cec5SDimitry Andric const MemoryLocation &Loc, 7180b57cec5SDimitry Andric const ModRefInfo Mode) { 7190b57cec5SDimitry Andric assert(I1.getParent() == I2.getParent() && 7200b57cec5SDimitry Andric "Instructions not in same basic block!"); 7210b57cec5SDimitry Andric BasicBlock::const_iterator I = I1.getIterator(); 7220b57cec5SDimitry Andric BasicBlock::const_iterator E = I2.getIterator(); 7230b57cec5SDimitry Andric ++E; // Convert from inclusive to exclusive range. 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric for (; I != E; ++I) // Check every instruction in range 726bdd1243dSDimitry Andric if (isModOrRefSet(getModRefInfo(&*I, Loc) & Mode)) 7270b57cec5SDimitry Andric return true; 7280b57cec5SDimitry Andric return false; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // Provide a definition for the root virtual destructor. 7320b57cec5SDimitry Andric AAResults::Concept::~Concept() = default; 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric // Provide a definition for the static object used to identify passes. 7350b57cec5SDimitry Andric AnalysisKey AAManager::Key; 7360b57cec5SDimitry Andric 737480093f4SDimitry Andric ExternalAAWrapperPass::ExternalAAWrapperPass() : ImmutablePass(ID) { 738480093f4SDimitry Andric initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry()); 739480093f4SDimitry Andric } 740480093f4SDimitry Andric 741480093f4SDimitry Andric ExternalAAWrapperPass::ExternalAAWrapperPass(CallbackT CB) 742480093f4SDimitry Andric : ImmutablePass(ID), CB(std::move(CB)) { 743480093f4SDimitry Andric initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry()); 744480093f4SDimitry Andric } 745480093f4SDimitry Andric 7460b57cec5SDimitry Andric char ExternalAAWrapperPass::ID = 0; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric INITIALIZE_PASS(ExternalAAWrapperPass, "external-aa", "External Alias Analysis", 7490b57cec5SDimitry Andric false, true) 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric ImmutablePass * 7520b57cec5SDimitry Andric llvm::createExternalAAWrapperPass(ExternalAAWrapperPass::CallbackT Callback) { 7530b57cec5SDimitry Andric return new ExternalAAWrapperPass(std::move(Callback)); 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric AAResultsWrapperPass::AAResultsWrapperPass() : FunctionPass(ID) { 7570b57cec5SDimitry Andric initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric char AAResultsWrapperPass::ID = 0; 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AAResultsWrapperPass, "aa", 7630b57cec5SDimitry Andric "Function Alias Analysis Results", false, true) 7640b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass) 7650b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ExternalAAWrapperPass) 7660b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) 7670b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass) 7680b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScopedNoAliasAAWrapperPass) 7690b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TypeBasedAAWrapperPass) 7700b57cec5SDimitry Andric INITIALIZE_PASS_END(AAResultsWrapperPass, "aa", 7710b57cec5SDimitry Andric "Function Alias Analysis Results", false, true) 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric /// Run the wrapper pass to rebuild an aggregation over known AA passes. 7740b57cec5SDimitry Andric /// 7750b57cec5SDimitry Andric /// This is the legacy pass manager's interface to the new-style AA results 7760b57cec5SDimitry Andric /// aggregation object. Because this is somewhat shoe-horned into the legacy 7770b57cec5SDimitry Andric /// pass manager, we hard code all the specific alias analyses available into 7780b57cec5SDimitry Andric /// it. While the particular set enabled is configured via commandline flags, 7790b57cec5SDimitry Andric /// adding a new alias analysis to LLVM will require adding support for it to 7800b57cec5SDimitry Andric /// this list. 7810b57cec5SDimitry Andric bool AAResultsWrapperPass::runOnFunction(Function &F) { 7820b57cec5SDimitry Andric // NB! This *must* be reset before adding new AA results to the new 7830b57cec5SDimitry Andric // AAResults object because in the legacy pass manager, each instance 7840b57cec5SDimitry Andric // of these will refer to the *same* immutable analyses, registering and 7850b57cec5SDimitry Andric // unregistering themselves with them. We need to carefully tear down the 7860b57cec5SDimitry Andric // previous object first, in this case replacing it with an empty one, before 7870b57cec5SDimitry Andric // registering new results. 7880b57cec5SDimitry Andric AAR.reset( 7898bcb0991SDimitry Andric new AAResults(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F))); 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric // BasicAA is always available for function analyses. Also, we add it first 7920b57cec5SDimitry Andric // so that it can trump TBAA results when it proves MustAlias. 7930b57cec5SDimitry Andric // FIXME: TBAA should have an explicit mode to support this and then we 7940b57cec5SDimitry Andric // should reconsider the ordering here. 7950b57cec5SDimitry Andric if (!DisableBasicAA) 7960b57cec5SDimitry Andric AAR->addAAResult(getAnalysis<BasicAAWrapperPass>().getResult()); 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric // Populate the results with the currently available AAs. 7990b57cec5SDimitry Andric if (auto *WrapperPass = getAnalysisIfAvailable<ScopedNoAliasAAWrapperPass>()) 8000b57cec5SDimitry Andric AAR->addAAResult(WrapperPass->getResult()); 8010b57cec5SDimitry Andric if (auto *WrapperPass = getAnalysisIfAvailable<TypeBasedAAWrapperPass>()) 8020b57cec5SDimitry Andric AAR->addAAResult(WrapperPass->getResult()); 8030b57cec5SDimitry Andric if (auto *WrapperPass = getAnalysisIfAvailable<GlobalsAAWrapperPass>()) 8040b57cec5SDimitry Andric AAR->addAAResult(WrapperPass->getResult()); 8050b57cec5SDimitry Andric if (auto *WrapperPass = getAnalysisIfAvailable<SCEVAAWrapperPass>()) 8060b57cec5SDimitry Andric AAR->addAAResult(WrapperPass->getResult()); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // If available, run an external AA providing callback over the results as 8090b57cec5SDimitry Andric // well. 8100b57cec5SDimitry Andric if (auto *WrapperPass = getAnalysisIfAvailable<ExternalAAWrapperPass>()) 8110b57cec5SDimitry Andric if (WrapperPass->CB) 8120b57cec5SDimitry Andric WrapperPass->CB(*this, F, *AAR); 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric // Analyses don't mutate the IR, so return false. 8150b57cec5SDimitry Andric return false; 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 8190b57cec5SDimitry Andric AU.setPreservesAll(); 820e8d8bef9SDimitry Andric AU.addRequiredTransitive<BasicAAWrapperPass>(); 821e8d8bef9SDimitry Andric AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>(); 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric // We also need to mark all the alias analysis passes we will potentially 8240b57cec5SDimitry Andric // probe in runOnFunction as used here to ensure the legacy pass manager 8250b57cec5SDimitry Andric // preserves them. This hard coding of lists of alias analyses is specific to 8260b57cec5SDimitry Andric // the legacy pass manager. 8270b57cec5SDimitry Andric AU.addUsedIfAvailable<ScopedNoAliasAAWrapperPass>(); 8280b57cec5SDimitry Andric AU.addUsedIfAvailable<TypeBasedAAWrapperPass>(); 8290b57cec5SDimitry Andric AU.addUsedIfAvailable<GlobalsAAWrapperPass>(); 8300b57cec5SDimitry Andric AU.addUsedIfAvailable<SCEVAAWrapperPass>(); 831480093f4SDimitry Andric AU.addUsedIfAvailable<ExternalAAWrapperPass>(); 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 834e8d8bef9SDimitry Andric AAManager::Result AAManager::run(Function &F, FunctionAnalysisManager &AM) { 835e8d8bef9SDimitry Andric Result R(AM.getResult<TargetLibraryAnalysis>(F)); 836e8d8bef9SDimitry Andric for (auto &Getter : ResultGetters) 837e8d8bef9SDimitry Andric (*Getter)(F, AM, R); 838e8d8bef9SDimitry Andric return R; 839e8d8bef9SDimitry Andric } 840e8d8bef9SDimitry Andric 8410b57cec5SDimitry Andric bool llvm::isNoAliasCall(const Value *V) { 8420b57cec5SDimitry Andric if (const auto *Call = dyn_cast<CallBase>(V)) 8430b57cec5SDimitry Andric return Call->hasRetAttr(Attribute::NoAlias); 8440b57cec5SDimitry Andric return false; 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 847e8d8bef9SDimitry Andric static bool isNoAliasOrByValArgument(const Value *V) { 8480b57cec5SDimitry Andric if (const Argument *A = dyn_cast<Argument>(V)) 849e8d8bef9SDimitry Andric return A->hasNoAliasAttr() || A->hasByValAttr(); 8500b57cec5SDimitry Andric return false; 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric bool llvm::isIdentifiedObject(const Value *V) { 8540b57cec5SDimitry Andric if (isa<AllocaInst>(V)) 8550b57cec5SDimitry Andric return true; 8560b57cec5SDimitry Andric if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V)) 8570b57cec5SDimitry Andric return true; 8580b57cec5SDimitry Andric if (isNoAliasCall(V)) 8590b57cec5SDimitry Andric return true; 860e8d8bef9SDimitry Andric if (isNoAliasOrByValArgument(V)) 861e8d8bef9SDimitry Andric return true; 8620b57cec5SDimitry Andric return false; 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric bool llvm::isIdentifiedFunctionLocal(const Value *V) { 866e8d8bef9SDimitry Andric return isa<AllocaInst>(V) || isNoAliasCall(V) || isNoAliasOrByValArgument(V); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 86981ad6265SDimitry Andric bool llvm::isEscapeSource(const Value *V) { 87081ad6265SDimitry Andric if (auto *CB = dyn_cast<CallBase>(V)) 87181ad6265SDimitry Andric return !isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(CB, 87281ad6265SDimitry Andric true); 87381ad6265SDimitry Andric 87481ad6265SDimitry Andric // The load case works because isNonEscapingLocalObject considers all 87581ad6265SDimitry Andric // stores to be escapes (it passes true for the StoreCaptures argument 87681ad6265SDimitry Andric // to PointerMayBeCaptured). 87781ad6265SDimitry Andric if (isa<LoadInst>(V)) 87881ad6265SDimitry Andric return true; 87981ad6265SDimitry Andric 88081ad6265SDimitry Andric // The inttoptr case works because isNonEscapingLocalObject considers all 88181ad6265SDimitry Andric // means of converting or equating a pointer to an int (ptrtoint, ptr store 88281ad6265SDimitry Andric // which could be followed by an integer load, ptr<->int compare) as 88381ad6265SDimitry Andric // escaping, and objects located at well-known addresses via platform-specific 88481ad6265SDimitry Andric // means cannot be considered non-escaping local objects. 88581ad6265SDimitry Andric if (isa<IntToPtrInst>(V)) 88681ad6265SDimitry Andric return true; 88781ad6265SDimitry Andric 8887a6dacacSDimitry Andric // Same for inttoptr constant expressions. 8897a6dacacSDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(V)) 8907a6dacacSDimitry Andric if (CE->getOpcode() == Instruction::IntToPtr) 8917a6dacacSDimitry Andric return true; 8927a6dacacSDimitry Andric 89381ad6265SDimitry Andric return false; 89481ad6265SDimitry Andric } 89581ad6265SDimitry Andric 89604eeddc0SDimitry Andric bool llvm::isNotVisibleOnUnwind(const Value *Object, 89704eeddc0SDimitry Andric bool &RequiresNoCaptureBeforeUnwind) { 89804eeddc0SDimitry Andric RequiresNoCaptureBeforeUnwind = false; 89904eeddc0SDimitry Andric 90004eeddc0SDimitry Andric // Alloca goes out of scope on unwind. 90104eeddc0SDimitry Andric if (isa<AllocaInst>(Object)) 90204eeddc0SDimitry Andric return true; 90304eeddc0SDimitry Andric 90404eeddc0SDimitry Andric // Byval goes out of scope on unwind. 90504eeddc0SDimitry Andric if (auto *A = dyn_cast<Argument>(Object)) 9065f757f3fSDimitry Andric return A->hasByValAttr() || A->hasAttribute(Attribute::DeadOnUnwind); 90704eeddc0SDimitry Andric 90804eeddc0SDimitry Andric // A noalias return is not accessible from any other code. If the pointer 90904eeddc0SDimitry Andric // does not escape prior to the unwind, then the caller cannot access the 91004eeddc0SDimitry Andric // memory either. 91104eeddc0SDimitry Andric if (isNoAliasCall(Object)) { 91204eeddc0SDimitry Andric RequiresNoCaptureBeforeUnwind = true; 91304eeddc0SDimitry Andric return true; 91404eeddc0SDimitry Andric } 91504eeddc0SDimitry Andric 91604eeddc0SDimitry Andric return false; 91704eeddc0SDimitry Andric } 9185f757f3fSDimitry Andric 9195f757f3fSDimitry Andric // We don't consider globals as writable: While the physical memory is writable, 9205f757f3fSDimitry Andric // we may not have provenance to perform the write. 9215f757f3fSDimitry Andric bool llvm::isWritableObject(const Value *Object, 9225f757f3fSDimitry Andric bool &ExplicitlyDereferenceableOnly) { 9235f757f3fSDimitry Andric ExplicitlyDereferenceableOnly = false; 9245f757f3fSDimitry Andric 9255f757f3fSDimitry Andric // TODO: Alloca might not be writable after its lifetime ends. 9265f757f3fSDimitry Andric // See https://github.com/llvm/llvm-project/issues/51838. 9275f757f3fSDimitry Andric if (isa<AllocaInst>(Object)) 9285f757f3fSDimitry Andric return true; 9295f757f3fSDimitry Andric 9305f757f3fSDimitry Andric if (auto *A = dyn_cast<Argument>(Object)) { 9315f757f3fSDimitry Andric if (A->hasAttribute(Attribute::Writable)) { 9325f757f3fSDimitry Andric ExplicitlyDereferenceableOnly = true; 9335f757f3fSDimitry Andric return true; 9345f757f3fSDimitry Andric } 9355f757f3fSDimitry Andric 9365f757f3fSDimitry Andric return A->hasByValAttr(); 9375f757f3fSDimitry Andric } 9385f757f3fSDimitry Andric 9395f757f3fSDimitry Andric // TODO: Noalias shouldn't imply writability, this should check for an 9405f757f3fSDimitry Andric // allocator function instead. 9415f757f3fSDimitry Andric return isNoAliasCall(Object); 9425f757f3fSDimitry Andric } 943