10b57cec5SDimitry Andric //===- BasicAliasAnalysis.h - Stateless, local Alias Analysis ---*- C++ -*-===// 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 /// \file 90b57cec5SDimitry Andric /// This is the interface for LLVM's primary stateless and local alias analysis. 100b57cec5SDimitry Andric /// 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_ANALYSIS_BASICALIASANALYSIS_H 140b57cec5SDimitry Andric #define LLVM_ANALYSIS_BASICALIASANALYSIS_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 170b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 180b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 190b57cec5SDimitry Andric #include "llvm/Pass.h" 200b57cec5SDimitry Andric #include <memory> 210b57cec5SDimitry Andric #include <utility> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class AssumptionCache; 260b57cec5SDimitry Andric class DataLayout; 270b57cec5SDimitry Andric class DominatorTree; 280b57cec5SDimitry Andric class Function; 290b57cec5SDimitry Andric class GEPOperator; 300b57cec5SDimitry Andric class PHINode; 310b57cec5SDimitry Andric class SelectInst; 320b57cec5SDimitry Andric class TargetLibraryInfo; 330b57cec5SDimitry Andric class Value; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric /// This is the AA result object for the basic, local, and stateless alias 360b57cec5SDimitry Andric /// analysis. It implements the AA query interface in an entirely stateless 370b57cec5SDimitry Andric /// manner. As one consequence, it is never invalidated due to IR changes. 380b57cec5SDimitry Andric /// While it does retain some storage, that is used as an optimization and not 390b57cec5SDimitry Andric /// to preserve information from query to query. However it does retain handles 400b57cec5SDimitry Andric /// to various other analyses and must be recomputed when those analyses are. 41bdd1243dSDimitry Andric class BasicAAResult : public AAResultBase { 420b57cec5SDimitry Andric const DataLayout &DL; 430b57cec5SDimitry Andric const Function &F; 440b57cec5SDimitry Andric const TargetLibraryInfo &TLI; 450b57cec5SDimitry Andric AssumptionCache &AC; 46*b3edf446SDimitry Andric /// Use getDT() instead of accessing this member directly, in order to 47*b3edf446SDimitry Andric /// respect the AAQI.UseDominatorTree option. 48*b3edf446SDimitry Andric DominatorTree *DT_; 49*b3edf446SDimitry Andric 50*b3edf446SDimitry Andric DominatorTree *getDT(const AAQueryInfo &AAQI) const { 51*b3edf446SDimitry Andric return AAQI.UseDominatorTree ? DT_ : nullptr; 52*b3edf446SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric public: 550b57cec5SDimitry Andric BasicAAResult(const DataLayout &DL, const Function &F, 560b57cec5SDimitry Andric const TargetLibraryInfo &TLI, AssumptionCache &AC, 57bdd1243dSDimitry Andric DominatorTree *DT = nullptr) 58*b3edf446SDimitry Andric : DL(DL), F(F), TLI(TLI), AC(AC), DT_(DT) {} 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric BasicAAResult(const BasicAAResult &Arg) 610b57cec5SDimitry Andric : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC), 62*b3edf446SDimitry Andric DT_(Arg.DT_) {} 630b57cec5SDimitry Andric BasicAAResult(BasicAAResult &&Arg) 640b57cec5SDimitry Andric : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), 65*b3edf446SDimitry Andric AC(Arg.AC), DT_(Arg.DT_) {} 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// Handle invalidation events in the new pass manager. 680b57cec5SDimitry Andric bool invalidate(Function &Fn, const PreservedAnalyses &PA, 690b57cec5SDimitry Andric FunctionAnalysisManager::Invalidator &Inv); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, 72bdd1243dSDimitry Andric AAQueryInfo &AAQI, const Instruction *CtxI); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, 750b57cec5SDimitry Andric AAQueryInfo &AAQI); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, 780b57cec5SDimitry Andric AAQueryInfo &AAQI); 790b57cec5SDimitry Andric 80bdd1243dSDimitry Andric /// Returns a bitmask that should be unconditionally applied to the ModRef 81bdd1243dSDimitry Andric /// info of a memory location. This allows us to eliminate Mod and/or Ref 82bdd1243dSDimitry Andric /// from the ModRef info based on the knowledge that the memory location 83bdd1243dSDimitry Andric /// points to constant and/or locally-invariant memory. 84bdd1243dSDimitry Andric /// 85bdd1243dSDimitry Andric /// If IgnoreLocals is true, then this method returns NoModRef for memory 86bdd1243dSDimitry Andric /// that points to a local alloca. 87bdd1243dSDimitry Andric ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, AAQueryInfo &AAQI, 88bdd1243dSDimitry Andric bool IgnoreLocals = false); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric /// Get the location associated with a pointer argument of a callsite. 910b57cec5SDimitry Andric ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric /// Returns the behavior when calling the given call site. 94bdd1243dSDimitry Andric MemoryEffects getMemoryEffects(const CallBase *Call, AAQueryInfo &AAQI); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// Returns the behavior when calling the given function. For use when the 970b57cec5SDimitry Andric /// call site is not known. 98bdd1243dSDimitry Andric MemoryEffects getMemoryEffects(const Function *Fn); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric private: 101349cc55cSDimitry Andric struct DecomposedGEP; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric /// Tracks instructions visited by pointsToConstantMemory. 1040b57cec5SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 1050b57cec5SDimitry Andric 106e8d8bef9SDimitry Andric static DecomposedGEP 107e8d8bef9SDimitry Andric DecomposeGEPExpression(const Value *V, const DataLayout &DL, 108e8d8bef9SDimitry Andric AssumptionCache *AC, DominatorTree *DT); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// A Heuristic for aliasGEP that searches for a constant offset 1110b57cec5SDimitry Andric /// between the variables. 1120b57cec5SDimitry Andric /// 1130b57cec5SDimitry Andric /// GetLinearExpression has some limitations, as generally zext(%x + 1) 1140b57cec5SDimitry Andric /// != zext(%x) + zext(1) if the arithmetic overflows. GetLinearExpression 1150b57cec5SDimitry Andric /// will therefore conservatively refuse to decompose these expressions. 1160b57cec5SDimitry Andric /// However, we know that, for all %x, zext(%x) != zext(%x + 1), even if 1170b57cec5SDimitry Andric /// the addition overflows. 118bdd1243dSDimitry Andric bool constantOffsetHeuristic(const DecomposedGEP &GEP, LocationSize V1Size, 119349cc55cSDimitry Andric LocationSize V2Size, AssumptionCache *AC, 120bdd1243dSDimitry Andric DominatorTree *DT, const AAQueryInfo &AAQI); 1210b57cec5SDimitry Andric 122bdd1243dSDimitry Andric bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2, 123bdd1243dSDimitry Andric const AAQueryInfo &AAQI); 1240b57cec5SDimitry Andric 125349cc55cSDimitry Andric void subtractDecomposedGEPs(DecomposedGEP &DestGEP, 126bdd1243dSDimitry Andric const DecomposedGEP &SrcGEP, 127bdd1243dSDimitry Andric const AAQueryInfo &AAQI); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size, 130fe6060f1SDimitry Andric const Value *V2, LocationSize V2Size, 1310b57cec5SDimitry Andric const Value *UnderlyingV1, const Value *UnderlyingV2, 1320b57cec5SDimitry Andric AAQueryInfo &AAQI); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize, 135fe6060f1SDimitry Andric const Value *V2, LocationSize V2Size, AAQueryInfo &AAQI); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize, 138fe6060f1SDimitry Andric const Value *V2, LocationSize V2Size, 139e8d8bef9SDimitry Andric AAQueryInfo &AAQI); 1400b57cec5SDimitry Andric 141bdd1243dSDimitry Andric AliasResult aliasCheck(const Value *V1, LocationSize V1Size, const Value *V2, 142bdd1243dSDimitry Andric LocationSize V2Size, AAQueryInfo &AAQI, 143bdd1243dSDimitry Andric const Instruction *CtxI); 144e8d8bef9SDimitry Andric 145e8d8bef9SDimitry Andric AliasResult aliasCheckRecursive(const Value *V1, LocationSize V1Size, 146fe6060f1SDimitry Andric const Value *V2, LocationSize V2Size, 147e8d8bef9SDimitry Andric AAQueryInfo &AAQI, const Value *O1, 148e8d8bef9SDimitry Andric const Value *O2); 1490b57cec5SDimitry Andric }; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric /// Analysis pass providing a never-invalidated alias analysis result. 1520b57cec5SDimitry Andric class BasicAA : public AnalysisInfoMixin<BasicAA> { 1530b57cec5SDimitry Andric friend AnalysisInfoMixin<BasicAA>; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric static AnalysisKey Key; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric public: 1580b57cec5SDimitry Andric using Result = BasicAAResult; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric BasicAAResult run(Function &F, FunctionAnalysisManager &AM); 1610b57cec5SDimitry Andric }; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// Legacy wrapper pass to provide the BasicAAResult object. 1640b57cec5SDimitry Andric class BasicAAWrapperPass : public FunctionPass { 1650b57cec5SDimitry Andric std::unique_ptr<BasicAAResult> Result; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric virtual void anchor(); 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric public: 1700b57cec5SDimitry Andric static char ID; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric BasicAAWrapperPass(); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric BasicAAResult &getResult() { return *Result; } 1750b57cec5SDimitry Andric const BasicAAResult &getResult() const { return *Result; } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric bool runOnFunction(Function &F) override; 1780b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 1790b57cec5SDimitry Andric }; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric FunctionPass *createBasicAAWrapperPass(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric } // end namespace llvm 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric #endif // LLVM_ANALYSIS_BASICALIASANALYSIS_H 186