1*0b57cec5SDimitry Andric //===- BasicAliasAnalysis.h - Stateless, local Alias Analysis ---*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// \file 9*0b57cec5SDimitry Andric /// This is the interface for LLVM's primary stateless and local alias analysis. 10*0b57cec5SDimitry Andric /// 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef LLVM_ANALYSIS_BASICALIASANALYSIS_H 14*0b57cec5SDimitry Andric #define LLVM_ANALYSIS_BASICALIASANALYSIS_H 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 20*0b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 21*0b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 22*0b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h" 23*0b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 24*0b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 25*0b57cec5SDimitry Andric #include "llvm/Pass.h" 26*0b57cec5SDimitry Andric #include <algorithm> 27*0b57cec5SDimitry Andric #include <cstdint> 28*0b57cec5SDimitry Andric #include <memory> 29*0b57cec5SDimitry Andric #include <utility> 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric namespace llvm { 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric struct AAMDNodes; 34*0b57cec5SDimitry Andric class APInt; 35*0b57cec5SDimitry Andric class AssumptionCache; 36*0b57cec5SDimitry Andric class BasicBlock; 37*0b57cec5SDimitry Andric class DataLayout; 38*0b57cec5SDimitry Andric class DominatorTree; 39*0b57cec5SDimitry Andric class Function; 40*0b57cec5SDimitry Andric class GEPOperator; 41*0b57cec5SDimitry Andric class LoopInfo; 42*0b57cec5SDimitry Andric class PHINode; 43*0b57cec5SDimitry Andric class SelectInst; 44*0b57cec5SDimitry Andric class TargetLibraryInfo; 45*0b57cec5SDimitry Andric class PhiValues; 46*0b57cec5SDimitry Andric class Value; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric /// This is the AA result object for the basic, local, and stateless alias 49*0b57cec5SDimitry Andric /// analysis. It implements the AA query interface in an entirely stateless 50*0b57cec5SDimitry Andric /// manner. As one consequence, it is never invalidated due to IR changes. 51*0b57cec5SDimitry Andric /// While it does retain some storage, that is used as an optimization and not 52*0b57cec5SDimitry Andric /// to preserve information from query to query. However it does retain handles 53*0b57cec5SDimitry Andric /// to various other analyses and must be recomputed when those analyses are. 54*0b57cec5SDimitry Andric class BasicAAResult : public AAResultBase<BasicAAResult> { 55*0b57cec5SDimitry Andric friend AAResultBase<BasicAAResult>; 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric const DataLayout &DL; 58*0b57cec5SDimitry Andric const Function &F; 59*0b57cec5SDimitry Andric const TargetLibraryInfo &TLI; 60*0b57cec5SDimitry Andric AssumptionCache &AC; 61*0b57cec5SDimitry Andric DominatorTree *DT; 62*0b57cec5SDimitry Andric LoopInfo *LI; 63*0b57cec5SDimitry Andric PhiValues *PV; 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric public: 66*0b57cec5SDimitry Andric BasicAAResult(const DataLayout &DL, const Function &F, 67*0b57cec5SDimitry Andric const TargetLibraryInfo &TLI, AssumptionCache &AC, 68*0b57cec5SDimitry Andric DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, 69*0b57cec5SDimitry Andric PhiValues *PV = nullptr) 70*0b57cec5SDimitry Andric : AAResultBase(), DL(DL), F(F), TLI(TLI), AC(AC), DT(DT), LI(LI), PV(PV) 71*0b57cec5SDimitry Andric {} 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric BasicAAResult(const BasicAAResult &Arg) 74*0b57cec5SDimitry Andric : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC), 75*0b57cec5SDimitry Andric DT(Arg.DT), LI(Arg.LI), PV(Arg.PV) {} 76*0b57cec5SDimitry Andric BasicAAResult(BasicAAResult &&Arg) 77*0b57cec5SDimitry Andric : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), 78*0b57cec5SDimitry Andric AC(Arg.AC), DT(Arg.DT), LI(Arg.LI), PV(Arg.PV) {} 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric /// Handle invalidation events in the new pass manager. 81*0b57cec5SDimitry Andric bool invalidate(Function &Fn, const PreservedAnalyses &PA, 82*0b57cec5SDimitry Andric FunctionAnalysisManager::Invalidator &Inv); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, 85*0b57cec5SDimitry Andric AAQueryInfo &AAQI); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, 88*0b57cec5SDimitry Andric AAQueryInfo &AAQI); 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, 91*0b57cec5SDimitry Andric AAQueryInfo &AAQI); 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric /// Chases pointers until we find a (constant global) or not. 94*0b57cec5SDimitry Andric bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, 95*0b57cec5SDimitry Andric bool OrLocal); 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric /// Get the location associated with a pointer argument of a callsite. 98*0b57cec5SDimitry Andric ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric /// Returns the behavior when calling the given call site. 101*0b57cec5SDimitry Andric FunctionModRefBehavior getModRefBehavior(const CallBase *Call); 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric /// Returns the behavior when calling the given function. For use when the 104*0b57cec5SDimitry Andric /// call site is not known. 105*0b57cec5SDimitry Andric FunctionModRefBehavior getModRefBehavior(const Function *Fn); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric private: 108*0b57cec5SDimitry Andric // A linear transformation of a Value; this class represents ZExt(SExt(V, 109*0b57cec5SDimitry Andric // SExtBits), ZExtBits) * Scale + Offset. 110*0b57cec5SDimitry Andric struct VariableGEPIndex { 111*0b57cec5SDimitry Andric // An opaque Value - we can't decompose this further. 112*0b57cec5SDimitry Andric const Value *V; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric // We need to track what extensions we've done as we consider the same Value 115*0b57cec5SDimitry Andric // with different extensions as different variables in a GEP's linear 116*0b57cec5SDimitry Andric // expression; 117*0b57cec5SDimitry Andric // e.g.: if V == -1, then sext(x) != zext(x). 118*0b57cec5SDimitry Andric unsigned ZExtBits; 119*0b57cec5SDimitry Andric unsigned SExtBits; 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric APInt Scale; 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric bool operator==(const VariableGEPIndex &Other) const { 124*0b57cec5SDimitry Andric return V == Other.V && ZExtBits == Other.ZExtBits && 125*0b57cec5SDimitry Andric SExtBits == Other.SExtBits && Scale == Other.Scale; 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric bool operator!=(const VariableGEPIndex &Other) const { 129*0b57cec5SDimitry Andric return !operator==(Other); 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric }; 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric // Represents the internal structure of a GEP, decomposed into a base pointer, 134*0b57cec5SDimitry Andric // constant offsets, and variable scaled indices. 135*0b57cec5SDimitry Andric struct DecomposedGEP { 136*0b57cec5SDimitry Andric // Base pointer of the GEP 137*0b57cec5SDimitry Andric const Value *Base; 138*0b57cec5SDimitry Andric // Total constant offset w.r.t the base from indexing into structs 139*0b57cec5SDimitry Andric APInt StructOffset; 140*0b57cec5SDimitry Andric // Total constant offset w.r.t the base from indexing through 141*0b57cec5SDimitry Andric // pointers/arrays/vectors 142*0b57cec5SDimitry Andric APInt OtherOffset; 143*0b57cec5SDimitry Andric // Scaled variable (non-constant) indices. 144*0b57cec5SDimitry Andric SmallVector<VariableGEPIndex, 4> VarIndices; 145*0b57cec5SDimitry Andric }; 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric /// Tracks phi nodes we have visited. 148*0b57cec5SDimitry Andric /// 149*0b57cec5SDimitry Andric /// When interpret "Value" pointer equality as value equality we need to make 150*0b57cec5SDimitry Andric /// sure that the "Value" is not part of a cycle. Otherwise, two uses could 151*0b57cec5SDimitry Andric /// come from different "iterations" of a cycle and see different values for 152*0b57cec5SDimitry Andric /// the same "Value" pointer. 153*0b57cec5SDimitry Andric /// 154*0b57cec5SDimitry Andric /// The following example shows the problem: 155*0b57cec5SDimitry Andric /// %p = phi(%alloca1, %addr2) 156*0b57cec5SDimitry Andric /// %l = load %ptr 157*0b57cec5SDimitry Andric /// %addr1 = gep, %alloca2, 0, %l 158*0b57cec5SDimitry Andric /// %addr2 = gep %alloca2, 0, (%l + 1) 159*0b57cec5SDimitry Andric /// alias(%p, %addr1) -> MayAlias ! 160*0b57cec5SDimitry Andric /// store %l, ... 161*0b57cec5SDimitry Andric SmallPtrSet<const BasicBlock *, 8> VisitedPhiBBs; 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric /// Tracks instructions visited by pointsToConstantMemory. 164*0b57cec5SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric static const Value * 167*0b57cec5SDimitry Andric GetLinearExpression(const Value *V, APInt &Scale, APInt &Offset, 168*0b57cec5SDimitry Andric unsigned &ZExtBits, unsigned &SExtBits, 169*0b57cec5SDimitry Andric const DataLayout &DL, unsigned Depth, AssumptionCache *AC, 170*0b57cec5SDimitry Andric DominatorTree *DT, bool &NSW, bool &NUW); 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric static bool DecomposeGEPExpression(const Value *V, DecomposedGEP &Decomposed, 173*0b57cec5SDimitry Andric const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT); 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp, 176*0b57cec5SDimitry Andric const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject, 177*0b57cec5SDimitry Andric LocationSize ObjectAccessSize); 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric /// A Heuristic for aliasGEP that searches for a constant offset 180*0b57cec5SDimitry Andric /// between the variables. 181*0b57cec5SDimitry Andric /// 182*0b57cec5SDimitry Andric /// GetLinearExpression has some limitations, as generally zext(%x + 1) 183*0b57cec5SDimitry Andric /// != zext(%x) + zext(1) if the arithmetic overflows. GetLinearExpression 184*0b57cec5SDimitry Andric /// will therefore conservatively refuse to decompose these expressions. 185*0b57cec5SDimitry Andric /// However, we know that, for all %x, zext(%x) != zext(%x + 1), even if 186*0b57cec5SDimitry Andric /// the addition overflows. 187*0b57cec5SDimitry Andric bool 188*0b57cec5SDimitry Andric constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices, 189*0b57cec5SDimitry Andric LocationSize V1Size, LocationSize V2Size, 190*0b57cec5SDimitry Andric APInt BaseOffset, AssumptionCache *AC, 191*0b57cec5SDimitry Andric DominatorTree *DT); 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2); 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric void GetIndexDifference(SmallVectorImpl<VariableGEPIndex> &Dest, 196*0b57cec5SDimitry Andric const SmallVectorImpl<VariableGEPIndex> &Src); 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size, 199*0b57cec5SDimitry Andric const AAMDNodes &V1AAInfo, const Value *V2, 200*0b57cec5SDimitry Andric LocationSize V2Size, const AAMDNodes &V2AAInfo, 201*0b57cec5SDimitry Andric const Value *UnderlyingV1, const Value *UnderlyingV2, 202*0b57cec5SDimitry Andric AAQueryInfo &AAQI); 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize, 205*0b57cec5SDimitry Andric const AAMDNodes &PNAAInfo, const Value *V2, 206*0b57cec5SDimitry Andric LocationSize V2Size, const AAMDNodes &V2AAInfo, 207*0b57cec5SDimitry Andric const Value *UnderV2, AAQueryInfo &AAQI); 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize, 210*0b57cec5SDimitry Andric const AAMDNodes &SIAAInfo, const Value *V2, 211*0b57cec5SDimitry Andric LocationSize V2Size, const AAMDNodes &V2AAInfo, 212*0b57cec5SDimitry Andric const Value *UnderV2, AAQueryInfo &AAQI); 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric AliasResult aliasCheck(const Value *V1, LocationSize V1Size, 215*0b57cec5SDimitry Andric AAMDNodes V1AATag, const Value *V2, 216*0b57cec5SDimitry Andric LocationSize V2Size, AAMDNodes V2AATag, 217*0b57cec5SDimitry Andric AAQueryInfo &AAQI, const Value *O1 = nullptr, 218*0b57cec5SDimitry Andric const Value *O2 = nullptr); 219*0b57cec5SDimitry Andric }; 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric /// Analysis pass providing a never-invalidated alias analysis result. 222*0b57cec5SDimitry Andric class BasicAA : public AnalysisInfoMixin<BasicAA> { 223*0b57cec5SDimitry Andric friend AnalysisInfoMixin<BasicAA>; 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric static AnalysisKey Key; 226*0b57cec5SDimitry Andric 227*0b57cec5SDimitry Andric public: 228*0b57cec5SDimitry Andric using Result = BasicAAResult; 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric BasicAAResult run(Function &F, FunctionAnalysisManager &AM); 231*0b57cec5SDimitry Andric }; 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric /// Legacy wrapper pass to provide the BasicAAResult object. 234*0b57cec5SDimitry Andric class BasicAAWrapperPass : public FunctionPass { 235*0b57cec5SDimitry Andric std::unique_ptr<BasicAAResult> Result; 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric virtual void anchor(); 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric public: 240*0b57cec5SDimitry Andric static char ID; 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric BasicAAWrapperPass(); 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric BasicAAResult &getResult() { return *Result; } 245*0b57cec5SDimitry Andric const BasicAAResult &getResult() const { return *Result; } 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric bool runOnFunction(Function &F) override; 248*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 249*0b57cec5SDimitry Andric }; 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric FunctionPass *createBasicAAWrapperPass(); 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric /// A helper for the legacy pass manager to create a \c BasicAAResult object 254*0b57cec5SDimitry Andric /// populated to the best of our ability for a particular function when inside 255*0b57cec5SDimitry Andric /// of a \c ModulePass or a \c CallGraphSCCPass. 256*0b57cec5SDimitry Andric BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F); 257*0b57cec5SDimitry Andric 258*0b57cec5SDimitry Andric /// This class is a functor to be used in legacy module or SCC passes for 259*0b57cec5SDimitry Andric /// computing AA results for a function. We store the results in fields so that 260*0b57cec5SDimitry Andric /// they live long enough to be queried, but we re-use them each time. 261*0b57cec5SDimitry Andric class LegacyAARGetter { 262*0b57cec5SDimitry Andric Pass &P; 263*0b57cec5SDimitry Andric Optional<BasicAAResult> BAR; 264*0b57cec5SDimitry Andric Optional<AAResults> AAR; 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric public: 267*0b57cec5SDimitry Andric LegacyAARGetter(Pass &P) : P(P) {} 268*0b57cec5SDimitry Andric AAResults &operator()(Function &F) { 269*0b57cec5SDimitry Andric BAR.emplace(createLegacyPMBasicAAResult(P, F)); 270*0b57cec5SDimitry Andric AAR.emplace(createLegacyPMAAResults(P, F, *BAR)); 271*0b57cec5SDimitry Andric return *AAR; 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric }; 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric } // end namespace llvm 276*0b57cec5SDimitry Andric 277*0b57cec5SDimitry Andric #endif // LLVM_ANALYSIS_BASICALIASANALYSIS_H 278