CFLSteensAliasAnalysis.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. //===- CFLSteensAliasAnalysis.cpp - Unification-based Alias Analysis ------===//
  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 a CFL-base, summary-based alias analysis algorithm. It
  10. // does not depend on types. The algorithm is a mixture of the one described in
  11. // "Demand-driven alias analysis for C" by Xin Zheng and Radu Rugina, and "Fast
  12. // algorithms for Dyck-CFL-reachability with applications to Alias Analysis" by
  13. // Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the papers, we build a
  14. // graph of the uses of a variable, where each node is a memory location, and
  15. // each edge is an action that happened on that memory location. The "actions"
  16. // can be one of Dereference, Reference, or Assign. The precision of this
  17. // analysis is roughly the same as that of an one level context-sensitive
  18. // Steensgaard's algorithm.
  19. //
  20. // Two variables are considered as aliasing iff you can reach one value's node
  21. // from the other value's node and the language formed by concatenating all of
  22. // the edge labels (actions) conforms to a context-free grammar.
  23. //
  24. // Because this algorithm requires a graph search on each query, we execute the
  25. // algorithm outlined in "Fast algorithms..." (mentioned above)
  26. // in order to transform the graph into sets of variables that may alias in
  27. // ~nlogn time (n = number of variables), which makes queries take constant
  28. // time.
  29. //===----------------------------------------------------------------------===//
  30. // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and
  31. // CFLSteensAA is interprocedural. This is *technically* A Bad Thing, because
  32. // FunctionPasses are only allowed to inspect the Function that they're being
  33. // run on. Realistically, this likely isn't a problem until we allow
  34. // FunctionPasses to run concurrently.
  35. #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
  36. #include "AliasAnalysisSummary.h"
  37. #include "CFLGraph.h"
  38. #include "StratifiedSets.h"
  39. #include "llvm/ADT/DenseMap.h"
  40. #include "llvm/ADT/Optional.h"
  41. #include "llvm/ADT/SmallVector.h"
  42. #include "llvm/Analysis/TargetLibraryInfo.h"
  43. #include "llvm/IR/Constants.h"
  44. #include "llvm/IR/Function.h"
  45. #include "llvm/IR/Type.h"
  46. #include "llvm/IR/Value.h"
  47. #include "llvm/InitializePasses.h"
  48. #include "llvm/Pass.h"
  49. #include "llvm/Support/Debug.h"
  50. #include "llvm/Support/raw_ostream.h"
  51. #include <algorithm>
  52. #include <cassert>
  53. #include <limits>
  54. #include <memory>
  55. #include <utility>
  56. using namespace llvm;
  57. using namespace llvm::cflaa;
  58. #define DEBUG_TYPE "cfl-steens-aa"
  59. CFLSteensAAResult::CFLSteensAAResult(
  60. std::function<const TargetLibraryInfo &(Function &F)> GetTLI)
  61. : GetTLI(std::move(GetTLI)) {}
  62. CFLSteensAAResult::CFLSteensAAResult(CFLSteensAAResult &&Arg)
  63. : AAResultBase(std::move(Arg)), GetTLI(std::move(Arg.GetTLI)) {}
  64. CFLSteensAAResult::~CFLSteensAAResult() = default;
  65. /// Information we have about a function and would like to keep around.
  66. class CFLSteensAAResult::FunctionInfo {
  67. StratifiedSets<InstantiatedValue> Sets;
  68. AliasSummary Summary;
  69. public:
  70. FunctionInfo(Function &Fn, const SmallVectorImpl<Value *> &RetVals,
  71. StratifiedSets<InstantiatedValue> S);
  72. const StratifiedSets<InstantiatedValue> &getStratifiedSets() const {
  73. return Sets;
  74. }
  75. const AliasSummary &getAliasSummary() const { return Summary; }
  76. };
  77. const StratifiedIndex StratifiedLink::SetSentinel =
  78. std::numeric_limits<StratifiedIndex>::max();
  79. //===----------------------------------------------------------------------===//
  80. // Function declarations that require types defined in the namespace above
  81. //===----------------------------------------------------------------------===//
  82. /// Determines whether it would be pointless to add the given Value to our sets.
  83. static bool canSkipAddingToSets(Value *Val) {
  84. // Constants can share instances, which may falsely unify multiple
  85. // sets, e.g. in
  86. // store i32* null, i32** %ptr1
  87. // store i32* null, i32** %ptr2
  88. // clearly ptr1 and ptr2 should not be unified into the same set, so
  89. // we should filter out the (potentially shared) instance to
  90. // i32* null.
  91. if (isa<Constant>(Val)) {
  92. // TODO: Because all of these things are constant, we can determine whether
  93. // the data is *actually* mutable at graph building time. This will probably
  94. // come for free/cheap with offset awareness.
  95. bool CanStoreMutableData = isa<GlobalValue>(Val) ||
  96. isa<ConstantExpr>(Val) ||
  97. isa<ConstantAggregate>(Val);
  98. return !CanStoreMutableData;
  99. }
  100. return false;
  101. }
  102. CFLSteensAAResult::FunctionInfo::FunctionInfo(
  103. Function &Fn, const SmallVectorImpl<Value *> &RetVals,
  104. StratifiedSets<InstantiatedValue> S)
  105. : Sets(std::move(S)) {
  106. // Historically, an arbitrary upper-bound of 50 args was selected. We may want
  107. // to remove this if it doesn't really matter in practice.
  108. if (Fn.arg_size() > MaxSupportedArgsInSummary)
  109. return;
  110. DenseMap<StratifiedIndex, InterfaceValue> InterfaceMap;
  111. // Our intention here is to record all InterfaceValues that share the same
  112. // StratifiedIndex in RetParamRelations. For each valid InterfaceValue, we
  113. // have its StratifiedIndex scanned here and check if the index is presented
  114. // in InterfaceMap: if it is not, we add the correspondence to the map;
  115. // otherwise, an aliasing relation is found and we add it to
  116. // RetParamRelations.
  117. auto AddToRetParamRelations = [&](unsigned InterfaceIndex,
  118. StratifiedIndex SetIndex) {
  119. unsigned Level = 0;
  120. while (true) {
  121. InterfaceValue CurrValue{InterfaceIndex, Level};
  122. auto Itr = InterfaceMap.find(SetIndex);
  123. if (Itr != InterfaceMap.end()) {
  124. if (CurrValue != Itr->second)
  125. Summary.RetParamRelations.push_back(
  126. ExternalRelation{CurrValue, Itr->second, UnknownOffset});
  127. break;
  128. }
  129. auto &Link = Sets.getLink(SetIndex);
  130. InterfaceMap.insert(std::make_pair(SetIndex, CurrValue));
  131. auto ExternalAttrs = getExternallyVisibleAttrs(Link.Attrs);
  132. if (ExternalAttrs.any())
  133. Summary.RetParamAttributes.push_back(
  134. ExternalAttribute{CurrValue, ExternalAttrs});
  135. if (!Link.hasBelow())
  136. break;
  137. ++Level;
  138. SetIndex = Link.Below;
  139. }
  140. };
  141. // Populate RetParamRelations for return values
  142. for (auto *RetVal : RetVals) {
  143. assert(RetVal != nullptr);
  144. assert(RetVal->getType()->isPointerTy());
  145. auto RetInfo = Sets.find(InstantiatedValue{RetVal, 0});
  146. if (RetInfo.hasValue())
  147. AddToRetParamRelations(0, RetInfo->Index);
  148. }
  149. // Populate RetParamRelations for parameters
  150. unsigned I = 0;
  151. for (auto &Param : Fn.args()) {
  152. if (Param.getType()->isPointerTy()) {
  153. auto ParamInfo = Sets.find(InstantiatedValue{&Param, 0});
  154. if (ParamInfo.hasValue())
  155. AddToRetParamRelations(I + 1, ParamInfo->Index);
  156. }
  157. ++I;
  158. }
  159. }
  160. // Builds the graph + StratifiedSets for a function.
  161. CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) {
  162. CFLGraphBuilder<CFLSteensAAResult> GraphBuilder(*this, GetTLI(*Fn), *Fn);
  163. StratifiedSetsBuilder<InstantiatedValue> SetBuilder;
  164. // Add all CFLGraph nodes and all Dereference edges to StratifiedSets
  165. auto &Graph = GraphBuilder.getCFLGraph();
  166. for (const auto &Mapping : Graph.value_mappings()) {
  167. auto Val = Mapping.first;
  168. if (canSkipAddingToSets(Val))
  169. continue;
  170. auto &ValueInfo = Mapping.second;
  171. assert(ValueInfo.getNumLevels() > 0);
  172. SetBuilder.add(InstantiatedValue{Val, 0});
  173. SetBuilder.noteAttributes(InstantiatedValue{Val, 0},
  174. ValueInfo.getNodeInfoAtLevel(0).Attr);
  175. for (unsigned I = 0, E = ValueInfo.getNumLevels() - 1; I < E; ++I) {
  176. SetBuilder.add(InstantiatedValue{Val, I + 1});
  177. SetBuilder.noteAttributes(InstantiatedValue{Val, I + 1},
  178. ValueInfo.getNodeInfoAtLevel(I + 1).Attr);
  179. SetBuilder.addBelow(InstantiatedValue{Val, I},
  180. InstantiatedValue{Val, I + 1});
  181. }
  182. }
  183. // Add all assign edges to StratifiedSets
  184. for (const auto &Mapping : Graph.value_mappings()) {
  185. auto Val = Mapping.first;
  186. if (canSkipAddingToSets(Val))
  187. continue;
  188. auto &ValueInfo = Mapping.second;
  189. for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) {
  190. auto Src = InstantiatedValue{Val, I};
  191. for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges)
  192. SetBuilder.addWith(Src, Edge.Other);
  193. }
  194. }
  195. return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
  196. }
  197. void CFLSteensAAResult::scan(Function *Fn) {
  198. auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>()));
  199. (void)InsertPair;
  200. assert(InsertPair.second &&
  201. "Trying to scan a function that has already been cached");
  202. // Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call
  203. // may get evaluated after operator[], potentially triggering a DenseMap
  204. // resize and invalidating the reference returned by operator[]
  205. auto FunInfo = buildSetsFrom(Fn);
  206. Cache[Fn] = std::move(FunInfo);
  207. Handles.emplace_front(Fn, this);
  208. }
  209. void CFLSteensAAResult::evict(Function *Fn) { Cache.erase(Fn); }
  210. /// Ensures that the given function is available in the cache, and returns the
  211. /// entry.
  212. const Optional<CFLSteensAAResult::FunctionInfo> &
  213. CFLSteensAAResult::ensureCached(Function *Fn) {
  214. auto Iter = Cache.find(Fn);
  215. if (Iter == Cache.end()) {
  216. scan(Fn);
  217. Iter = Cache.find(Fn);
  218. assert(Iter != Cache.end());
  219. assert(Iter->second.hasValue());
  220. }
  221. return Iter->second;
  222. }
  223. const AliasSummary *CFLSteensAAResult::getAliasSummary(Function &Fn) {
  224. auto &FunInfo = ensureCached(&Fn);
  225. if (FunInfo.hasValue())
  226. return &FunInfo->getAliasSummary();
  227. else
  228. return nullptr;
  229. }
  230. AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA,
  231. const MemoryLocation &LocB) {
  232. auto *ValA = const_cast<Value *>(LocA.Ptr);
  233. auto *ValB = const_cast<Value *>(LocB.Ptr);
  234. if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy())
  235. return AliasResult::NoAlias;
  236. Function *Fn = nullptr;
  237. Function *MaybeFnA = const_cast<Function *>(parentFunctionOfValue(ValA));
  238. Function *MaybeFnB = const_cast<Function *>(parentFunctionOfValue(ValB));
  239. if (!MaybeFnA && !MaybeFnB) {
  240. // The only times this is known to happen are when globals + InlineAsm are
  241. // involved
  242. LLVM_DEBUG(
  243. dbgs()
  244. << "CFLSteensAA: could not extract parent function information.\n");
  245. return AliasResult::MayAlias;
  246. }
  247. if (MaybeFnA) {
  248. Fn = MaybeFnA;
  249. assert((!MaybeFnB || MaybeFnB == MaybeFnA) &&
  250. "Interprocedural queries not supported");
  251. } else {
  252. Fn = MaybeFnB;
  253. }
  254. assert(Fn != nullptr);
  255. auto &MaybeInfo = ensureCached(Fn);
  256. assert(MaybeInfo.hasValue());
  257. auto &Sets = MaybeInfo->getStratifiedSets();
  258. auto MaybeA = Sets.find(InstantiatedValue{ValA, 0});
  259. if (!MaybeA.hasValue())
  260. return AliasResult::MayAlias;
  261. auto MaybeB = Sets.find(InstantiatedValue{ValB, 0});
  262. if (!MaybeB.hasValue())
  263. return AliasResult::MayAlias;
  264. auto SetA = *MaybeA;
  265. auto SetB = *MaybeB;
  266. auto AttrsA = Sets.getLink(SetA.Index).Attrs;
  267. auto AttrsB = Sets.getLink(SetB.Index).Attrs;
  268. // If both values are local (meaning the corresponding set has attribute
  269. // AttrNone or AttrEscaped), then we know that CFLSteensAA fully models them:
  270. // they may-alias each other if and only if they are in the same set.
  271. // If at least one value is non-local (meaning it either is global/argument or
  272. // it comes from unknown sources like integer cast), the situation becomes a
  273. // bit more interesting. We follow three general rules described below:
  274. // - Non-local values may alias each other
  275. // - AttrNone values do not alias any non-local values
  276. // - AttrEscaped do not alias globals/arguments, but they may alias
  277. // AttrUnknown values
  278. if (SetA.Index == SetB.Index)
  279. return AliasResult::MayAlias;
  280. if (AttrsA.none() || AttrsB.none())
  281. return AliasResult::NoAlias;
  282. if (hasUnknownOrCallerAttr(AttrsA) || hasUnknownOrCallerAttr(AttrsB))
  283. return AliasResult::MayAlias;
  284. if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB))
  285. return AliasResult::MayAlias;
  286. return AliasResult::NoAlias;
  287. }
  288. AnalysisKey CFLSteensAA::Key;
  289. CFLSteensAAResult CFLSteensAA::run(Function &F, FunctionAnalysisManager &AM) {
  290. auto GetTLI = [&AM](Function &F) -> const TargetLibraryInfo & {
  291. return AM.getResult<TargetLibraryAnalysis>(F);
  292. };
  293. return CFLSteensAAResult(GetTLI);
  294. }
  295. char CFLSteensAAWrapperPass::ID = 0;
  296. INITIALIZE_PASS(CFLSteensAAWrapperPass, "cfl-steens-aa",
  297. "Unification-Based CFL Alias Analysis", false, true)
  298. ImmutablePass *llvm::createCFLSteensAAWrapperPass() {
  299. return new CFLSteensAAWrapperPass();
  300. }
  301. CFLSteensAAWrapperPass::CFLSteensAAWrapperPass() : ImmutablePass(ID) {
  302. initializeCFLSteensAAWrapperPassPass(*PassRegistry::getPassRegistry());
  303. }
  304. void CFLSteensAAWrapperPass::initializePass() {
  305. auto GetTLI = [this](Function &F) -> const TargetLibraryInfo & {
  306. return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
  307. };
  308. Result.reset(new CFLSteensAAResult(GetTLI));
  309. }
  310. void CFLSteensAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
  311. AU.setPreservesAll();
  312. AU.addRequired<TargetLibraryInfoWrapperPass>();
  313. }