ModRef.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- ModRef.h - Memory effect modelling ---------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Definitions of ModRefInfo and MemoryEffects, which are used to
  15. // describe the memory effects of instructions.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_IR_MODREF_H
  19. #define LLVM_IR_MODREF_H
  20. #include "llvm/ADT/BitmaskEnum.h"
  21. #include "llvm/ADT/Sequence.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. namespace llvm {
  24. /// Flags indicating whether a memory access modifies or references memory.
  25. ///
  26. /// This is no access at all, a modification, a reference, or both
  27. /// a modification and a reference.
  28. enum class ModRefInfo : uint8_t {
  29. /// The access neither references nor modifies the value stored in memory.
  30. NoModRef = 0,
  31. /// The access may reference the value stored in memory.
  32. Ref = 1,
  33. /// The access may modify the value stored in memory.
  34. Mod = 2,
  35. /// The access may reference and may modify the value stored in memory.
  36. ModRef = Ref | Mod,
  37. LLVM_MARK_AS_BITMASK_ENUM(ModRef),
  38. };
  39. [[nodiscard]] inline bool isNoModRef(const ModRefInfo MRI) {
  40. return MRI == ModRefInfo::NoModRef;
  41. }
  42. [[nodiscard]] inline bool isModOrRefSet(const ModRefInfo MRI) {
  43. return MRI != ModRefInfo::NoModRef;
  44. }
  45. [[nodiscard]] inline bool isModAndRefSet(const ModRefInfo MRI) {
  46. return MRI == ModRefInfo::ModRef;
  47. }
  48. [[nodiscard]] inline bool isModSet(const ModRefInfo MRI) {
  49. return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod);
  50. }
  51. [[nodiscard]] inline bool isRefSet(const ModRefInfo MRI) {
  52. return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref);
  53. }
  54. /// Debug print ModRefInfo.
  55. raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
  56. /// Summary of how a function affects memory in the program.
  57. ///
  58. /// Loads from constant globals are not considered memory accesses for this
  59. /// interface. Also, functions may freely modify stack space local to their
  60. /// invocation without having to report it through these interfaces.
  61. class MemoryEffects {
  62. public:
  63. /// The locations at which a function might access memory.
  64. enum Location {
  65. /// Access to memory via argument pointers.
  66. ArgMem = 0,
  67. /// Memory that is inaccessible via LLVM IR.
  68. InaccessibleMem = 1,
  69. /// Any other memory.
  70. Other = 2,
  71. };
  72. private:
  73. uint32_t Data = 0;
  74. static constexpr uint32_t BitsPerLoc = 2;
  75. static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;
  76. static uint32_t getLocationPos(Location Loc) {
  77. return (uint32_t)Loc * BitsPerLoc;
  78. }
  79. MemoryEffects(uint32_t Data) : Data(Data) {}
  80. void setModRef(Location Loc, ModRefInfo MR) {
  81. Data &= ~(LocMask << getLocationPos(Loc));
  82. Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
  83. }
  84. friend raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
  85. public:
  86. /// Returns iterator over all supported location kinds.
  87. static auto locations() {
  88. return enum_seq_inclusive(Location::ArgMem, Location::Other,
  89. force_iteration_on_noniterable_enum);
  90. }
  91. /// Create MemoryEffects that can access only the given location with the
  92. /// given ModRefInfo.
  93. MemoryEffects(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
  94. /// Create MemoryEffects that can access any location with the given
  95. /// ModRefInfo.
  96. explicit MemoryEffects(ModRefInfo MR) {
  97. for (Location Loc : locations())
  98. setModRef(Loc, MR);
  99. }
  100. /// Create MemoryEffects that can read and write any memory.
  101. static MemoryEffects unknown() {
  102. return MemoryEffects(ModRefInfo::ModRef);
  103. }
  104. /// Create MemoryEffects that cannot read or write any memory.
  105. static MemoryEffects none() {
  106. return MemoryEffects(ModRefInfo::NoModRef);
  107. }
  108. /// Create MemoryEffects that can read any memory.
  109. static MemoryEffects readOnly() {
  110. return MemoryEffects(ModRefInfo::Ref);
  111. }
  112. /// Create MemoryEffects that can write any memory.
  113. static MemoryEffects writeOnly() {
  114. return MemoryEffects(ModRefInfo::Mod);
  115. }
  116. /// Create MemoryEffects that can only access argument memory.
  117. static MemoryEffects argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
  118. return MemoryEffects(ArgMem, MR);
  119. }
  120. /// Create MemoryEffects that can only access inaccessible memory.
  121. static MemoryEffects inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
  122. return MemoryEffects(InaccessibleMem, MR);
  123. }
  124. /// Create MemoryEffects that can only access inaccessible or argument memory.
  125. static MemoryEffects
  126. inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
  127. MemoryEffects FRMB = none();
  128. FRMB.setModRef(ArgMem, MR);
  129. FRMB.setModRef(InaccessibleMem, MR);
  130. return FRMB;
  131. }
  132. /// Create MemoryEffects from an encoded integer value (used by memory
  133. /// attribute).
  134. static MemoryEffects createFromIntValue(uint32_t Data) {
  135. return MemoryEffects(Data);
  136. }
  137. /// Convert MemoryEffects into an encoded integer value (used by memory
  138. /// attribute).
  139. uint32_t toIntValue() const {
  140. return Data;
  141. }
  142. /// Get ModRefInfo for the given Location.
  143. ModRefInfo getModRef(Location Loc) const {
  144. return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
  145. }
  146. /// Get new MemoryEffects with modified ModRefInfo for Loc.
  147. MemoryEffects getWithModRef(Location Loc, ModRefInfo MR) const {
  148. MemoryEffects ME = *this;
  149. ME.setModRef(Loc, MR);
  150. return ME;
  151. }
  152. /// Get new MemoryEffects with NoModRef on the given Loc.
  153. MemoryEffects getWithoutLoc(Location Loc) const {
  154. MemoryEffects ME = *this;
  155. ME.setModRef(Loc, ModRefInfo::NoModRef);
  156. return ME;
  157. }
  158. /// Get ModRefInfo for any location.
  159. ModRefInfo getModRef() const {
  160. ModRefInfo MR = ModRefInfo::NoModRef;
  161. for (Location Loc : locations())
  162. MR |= getModRef(Loc);
  163. return MR;
  164. }
  165. /// Whether this function accesses no memory.
  166. bool doesNotAccessMemory() const { return Data == 0; }
  167. /// Whether this function only (at most) reads memory.
  168. bool onlyReadsMemory() const { return !isModSet(getModRef()); }
  169. /// Whether this function only (at most) writes memory.
  170. bool onlyWritesMemory() const { return !isRefSet(getModRef()); }
  171. /// Whether this function only (at most) accesses argument memory.
  172. bool onlyAccessesArgPointees() const {
  173. return getWithoutLoc(ArgMem).doesNotAccessMemory();
  174. }
  175. /// Whether this function may access argument memory.
  176. bool doesAccessArgPointees() const {
  177. return isModOrRefSet(getModRef(ArgMem));
  178. }
  179. /// Whether this function only (at most) accesses inaccessible memory.
  180. bool onlyAccessesInaccessibleMem() const {
  181. return getWithoutLoc(InaccessibleMem).doesNotAccessMemory();
  182. }
  183. /// Whether this function only (at most) accesses argument and inaccessible
  184. /// memory.
  185. bool onlyAccessesInaccessibleOrArgMem() const {
  186. return isNoModRef(getModRef(Other));
  187. }
  188. /// Intersect with other MemoryEffects.
  189. MemoryEffects operator&(MemoryEffects Other) const {
  190. return MemoryEffects(Data & Other.Data);
  191. }
  192. /// Intersect (in-place) with other MemoryEffects.
  193. MemoryEffects &operator&=(MemoryEffects Other) {
  194. Data &= Other.Data;
  195. return *this;
  196. }
  197. /// Union with other MemoryEffects.
  198. MemoryEffects operator|(MemoryEffects Other) const {
  199. return MemoryEffects(Data | Other.Data);
  200. }
  201. /// Union (in-place) with other MemoryEffects.
  202. MemoryEffects &operator|=(MemoryEffects Other) {
  203. Data |= Other.Data;
  204. return *this;
  205. }
  206. /// Check whether this is the same as other MemoryEffects.
  207. bool operator==(MemoryEffects Other) const {
  208. return Data == Other.Data;
  209. }
  210. /// Check whether this is different from other MemoryEffects.
  211. bool operator!=(MemoryEffects Other) const {
  212. return !operator==(Other);
  213. }
  214. };
  215. /// Debug print MemoryEffects.
  216. raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
  217. // Legacy alias.
  218. using FunctionModRefBehavior = MemoryEffects;
  219. } // namespace llvm
  220. #endif
  221. #ifdef __GNUC__
  222. #pragma GCC diagnostic pop
  223. #endif