AliasAnalysisSummary.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. //=====- CFLSummary.h - Abstract stratified sets implementation. --------=====//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. /// This file defines various utility types and functions useful to
  10. /// summary-based alias analysis.
  11. ///
  12. /// Summary-based analysis, also known as bottom-up analysis, is a style of
  13. /// interprocedrual static analysis that tries to analyze the callees before the
  14. /// callers get analyzed. The key idea of summary-based analysis is to first
  15. /// process each function independently, outline its behavior in a condensed
  16. /// summary, and then instantiate the summary at the callsite when the said
  17. /// function is called elsewhere. This is often in contrast to another style
  18. /// called top-down analysis, in which callers are always analyzed first before
  19. /// the callees.
  20. ///
  21. /// In a summary-based analysis, functions must be examined independently and
  22. /// out-of-context. We have no information on the state of the memory, the
  23. /// arguments, the global values, and anything else external to the function. To
  24. /// carry out the analysis conservative assumptions have to be made about those
  25. /// external states. In exchange for the potential loss of precision, the
  26. /// summary we obtain this way is highly reusable, which makes the analysis
  27. /// easier to scale to large programs even if carried out context-sensitively.
  28. ///
  29. /// Currently, all CFL-based alias analyses adopt the summary-based approach
  30. /// and therefore heavily rely on this header.
  31. ///
  32. //===----------------------------------------------------------------------===//
  33. #ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
  34. #define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
  35. #include "llvm/ADT/DenseMapInfo.h"
  36. #include "llvm/ADT/Optional.h"
  37. #include "llvm/ADT/SmallVector.h"
  38. #include <bitset>
  39. namespace llvm {
  40. class CallBase;
  41. class Value;
  42. namespace cflaa {
  43. //===----------------------------------------------------------------------===//
  44. // AliasAttr related stuffs
  45. //===----------------------------------------------------------------------===//
  46. /// The number of attributes that AliasAttr should contain. Attributes are
  47. /// described below, and 32 was an arbitrary choice because it fits nicely in 32
  48. /// bits (because we use a bitset for AliasAttr).
  49. static const unsigned NumAliasAttrs = 32;
  50. /// These are attributes that an alias analysis can use to mark certain special
  51. /// properties of a given pointer. Refer to the related functions below to see
  52. /// what kinds of attributes are currently defined.
  53. typedef std::bitset<NumAliasAttrs> AliasAttrs;
  54. /// Attr represent whether the said pointer comes from an unknown source
  55. /// (such as opaque memory or an integer cast).
  56. AliasAttrs getAttrNone();
  57. /// AttrUnknown represent whether the said pointer comes from a source not known
  58. /// to alias analyses (such as opaque memory or an integer cast).
  59. AliasAttrs getAttrUnknown();
  60. bool hasUnknownAttr(AliasAttrs);
  61. /// AttrCaller represent whether the said pointer comes from a source not known
  62. /// to the current function but known to the caller. Values pointed to by the
  63. /// arguments of the current function have this attribute set
  64. AliasAttrs getAttrCaller();
  65. bool hasCallerAttr(AliasAttrs);
  66. bool hasUnknownOrCallerAttr(AliasAttrs);
  67. /// AttrEscaped represent whether the said pointer comes from a known source but
  68. /// escapes to the unknown world (e.g. casted to an integer, or passed as an
  69. /// argument to opaque function). Unlike non-escaped pointers, escaped ones may
  70. /// alias pointers coming from unknown sources.
  71. AliasAttrs getAttrEscaped();
  72. bool hasEscapedAttr(AliasAttrs);
  73. /// AttrGlobal represent whether the said pointer is a global value.
  74. /// AttrArg represent whether the said pointer is an argument, and if so, what
  75. /// index the argument has.
  76. AliasAttrs getGlobalOrArgAttrFromValue(const Value &);
  77. bool isGlobalOrArgAttr(AliasAttrs);
  78. /// Given an AliasAttrs, return a new AliasAttrs that only contains attributes
  79. /// meaningful to the caller. This function is primarily used for
  80. /// interprocedural analysis
  81. /// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal,
  82. /// and AttrEscaped
  83. AliasAttrs getExternallyVisibleAttrs(AliasAttrs);
  84. //===----------------------------------------------------------------------===//
  85. // Function summary related stuffs
  86. //===----------------------------------------------------------------------===//
  87. /// The maximum number of arguments we can put into a summary.
  88. static const unsigned MaxSupportedArgsInSummary = 50;
  89. /// We use InterfaceValue to describe parameters/return value, as well as
  90. /// potential memory locations that are pointed to by parameters/return value,
  91. /// of a function.
  92. /// Index is an integer which represents a single parameter or a return value.
  93. /// When the index is 0, it refers to the return value. Non-zero index i refers
  94. /// to the i-th parameter.
  95. /// DerefLevel indicates the number of dereferences one must perform on the
  96. /// parameter/return value to get this InterfaceValue.
  97. struct InterfaceValue {
  98. unsigned Index;
  99. unsigned DerefLevel;
  100. };
  101. inline bool operator==(InterfaceValue LHS, InterfaceValue RHS) {
  102. return LHS.Index == RHS.Index && LHS.DerefLevel == RHS.DerefLevel;
  103. }
  104. inline bool operator!=(InterfaceValue LHS, InterfaceValue RHS) {
  105. return !(LHS == RHS);
  106. }
  107. inline bool operator<(InterfaceValue LHS, InterfaceValue RHS) {
  108. return LHS.Index < RHS.Index ||
  109. (LHS.Index == RHS.Index && LHS.DerefLevel < RHS.DerefLevel);
  110. }
  111. inline bool operator>(InterfaceValue LHS, InterfaceValue RHS) {
  112. return RHS < LHS;
  113. }
  114. inline bool operator<=(InterfaceValue LHS, InterfaceValue RHS) {
  115. return !(RHS < LHS);
  116. }
  117. inline bool operator>=(InterfaceValue LHS, InterfaceValue RHS) {
  118. return !(LHS < RHS);
  119. }
  120. // We use UnknownOffset to represent pointer offsets that cannot be determined
  121. // at compile time. Note that MemoryLocation::UnknownSize cannot be used here
  122. // because we require a signed value.
  123. static const int64_t UnknownOffset = INT64_MAX;
  124. inline int64_t addOffset(int64_t LHS, int64_t RHS) {
  125. if (LHS == UnknownOffset || RHS == UnknownOffset)
  126. return UnknownOffset;
  127. // FIXME: Do we need to guard against integer overflow here?
  128. return LHS + RHS;
  129. }
  130. /// We use ExternalRelation to describe an externally visible aliasing relations
  131. /// between parameters/return value of a function.
  132. struct ExternalRelation {
  133. InterfaceValue From, To;
  134. int64_t Offset;
  135. };
  136. inline bool operator==(ExternalRelation LHS, ExternalRelation RHS) {
  137. return LHS.From == RHS.From && LHS.To == RHS.To && LHS.Offset == RHS.Offset;
  138. }
  139. inline bool operator!=(ExternalRelation LHS, ExternalRelation RHS) {
  140. return !(LHS == RHS);
  141. }
  142. inline bool operator<(ExternalRelation LHS, ExternalRelation RHS) {
  143. if (LHS.From < RHS.From)
  144. return true;
  145. if (LHS.From > RHS.From)
  146. return false;
  147. if (LHS.To < RHS.To)
  148. return true;
  149. if (LHS.To > RHS.To)
  150. return false;
  151. return LHS.Offset < RHS.Offset;
  152. }
  153. inline bool operator>(ExternalRelation LHS, ExternalRelation RHS) {
  154. return RHS < LHS;
  155. }
  156. inline bool operator<=(ExternalRelation LHS, ExternalRelation RHS) {
  157. return !(RHS < LHS);
  158. }
  159. inline bool operator>=(ExternalRelation LHS, ExternalRelation RHS) {
  160. return !(LHS < RHS);
  161. }
  162. /// We use ExternalAttribute to describe an externally visible AliasAttrs
  163. /// for parameters/return value.
  164. struct ExternalAttribute {
  165. InterfaceValue IValue;
  166. AliasAttrs Attr;
  167. };
  168. /// AliasSummary is just a collection of ExternalRelation and ExternalAttribute
  169. struct AliasSummary {
  170. // RetParamRelations is a collection of ExternalRelations.
  171. SmallVector<ExternalRelation, 8> RetParamRelations;
  172. // RetParamAttributes is a collection of ExternalAttributes.
  173. SmallVector<ExternalAttribute, 8> RetParamAttributes;
  174. };
  175. /// This is the result of instantiating InterfaceValue at a particular call
  176. struct InstantiatedValue {
  177. Value *Val;
  178. unsigned DerefLevel;
  179. };
  180. Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue,
  181. CallBase &Call);
  182. inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) {
  183. return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
  184. }
  185. inline bool operator!=(InstantiatedValue LHS, InstantiatedValue RHS) {
  186. return !(LHS == RHS);
  187. }
  188. inline bool operator<(InstantiatedValue LHS, InstantiatedValue RHS) {
  189. return std::less<Value *>()(LHS.Val, RHS.Val) ||
  190. (LHS.Val == RHS.Val && LHS.DerefLevel < RHS.DerefLevel);
  191. }
  192. inline bool operator>(InstantiatedValue LHS, InstantiatedValue RHS) {
  193. return RHS < LHS;
  194. }
  195. inline bool operator<=(InstantiatedValue LHS, InstantiatedValue RHS) {
  196. return !(RHS < LHS);
  197. }
  198. inline bool operator>=(InstantiatedValue LHS, InstantiatedValue RHS) {
  199. return !(LHS < RHS);
  200. }
  201. /// This is the result of instantiating ExternalRelation at a particular
  202. /// callsite
  203. struct InstantiatedRelation {
  204. InstantiatedValue From, To;
  205. int64_t Offset;
  206. };
  207. Optional<InstantiatedRelation>
  208. instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call);
  209. /// This is the result of instantiating ExternalAttribute at a particular
  210. /// callsite
  211. struct InstantiatedAttr {
  212. InstantiatedValue IValue;
  213. AliasAttrs Attr;
  214. };
  215. Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr,
  216. CallBase &Call);
  217. }
  218. template <> struct DenseMapInfo<cflaa::InstantiatedValue> {
  219. static inline cflaa::InstantiatedValue getEmptyKey() {
  220. return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getEmptyKey(),
  221. DenseMapInfo<unsigned>::getEmptyKey()};
  222. }
  223. static inline cflaa::InstantiatedValue getTombstoneKey() {
  224. return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getTombstoneKey(),
  225. DenseMapInfo<unsigned>::getTombstoneKey()};
  226. }
  227. static unsigned getHashValue(const cflaa::InstantiatedValue &IV) {
  228. return DenseMapInfo<std::pair<Value *, unsigned>>::getHashValue(
  229. std::make_pair(IV.Val, IV.DerefLevel));
  230. }
  231. static bool isEqual(const cflaa::InstantiatedValue &LHS,
  232. const cflaa::InstantiatedValue &RHS) {
  233. return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
  234. }
  235. };
  236. }
  237. #endif