xref: /llvm-project/llvm/include/llvm/Support/ModRef.h (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1 //===--- ModRef.h - Memory effect modeling ----------------------*- C++ -*-===//
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 // Definitions of ModRefInfo and MemoryEffects, which are used to
10 // describe the memory effects of instructions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_SUPPORT_MODREF_H
15 #define LLVM_SUPPORT_MODREF_H
16 
17 #include "llvm/ADT/BitmaskEnum.h"
18 #include "llvm/ADT/Sequence.h"
19 #include "llvm/Support/raw_ostream.h"
20 
21 namespace llvm {
22 
23 /// Flags indicating whether a memory access modifies or references memory.
24 ///
25 /// This is no access at all, a modification, a reference, or both
26 /// a modification and a reference.
27 enum class ModRefInfo : uint8_t {
28   /// The access neither references nor modifies the value stored in memory.
29   NoModRef = 0,
30   /// The access may reference the value stored in memory.
31   Ref = 1,
32   /// The access may modify the value stored in memory.
33   Mod = 2,
34   /// The access may reference and may modify the value stored in memory.
35   ModRef = Ref | Mod,
36   LLVM_MARK_AS_BITMASK_ENUM(ModRef),
37 };
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 
55 /// Debug print ModRefInfo.
56 raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);
57 
58 /// The locations at which a function might access memory.
59 enum class IRMemLocation {
60   /// Access to memory via argument pointers.
61   ArgMem = 0,
62   /// Memory that is inaccessible via LLVM IR.
63   InaccessibleMem = 1,
64   /// Any other memory.
65   Other = 2,
66 
67   /// Helpers to iterate all locations in the MemoryEffectsBase class.
68   First = ArgMem,
69   Last = Other,
70 };
71 
72 template <typename LocationEnum> class MemoryEffectsBase {
73 public:
74   using Location = LocationEnum;
75 
76 private:
77   uint32_t Data = 0;
78 
79   static constexpr uint32_t BitsPerLoc = 2;
80   static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;
81 
82   static uint32_t getLocationPos(Location Loc) {
83     return (uint32_t)Loc * BitsPerLoc;
84   }
85 
86   MemoryEffectsBase(uint32_t Data) : Data(Data) {}
87 
88   void setModRef(Location Loc, ModRefInfo MR) {
89     Data &= ~(LocMask << getLocationPos(Loc));
90     Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
91   }
92 
93 public:
94   /// Returns iterator over all supported location kinds.
95   static auto locations() {
96     return enum_seq_inclusive(Location::First, Location::Last,
97                               force_iteration_on_noniterable_enum);
98   }
99 
100   /// Create MemoryEffectsBase that can access only the given location with the
101   /// given ModRefInfo.
102   MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
103 
104   /// Create MemoryEffectsBase that can access any location with the given
105   /// ModRefInfo.
106   explicit MemoryEffectsBase(ModRefInfo MR) {
107     for (Location Loc : locations())
108       setModRef(Loc, MR);
109   }
110 
111   /// Create MemoryEffectsBase that can read and write any memory.
112   static MemoryEffectsBase unknown() {
113     return MemoryEffectsBase(ModRefInfo::ModRef);
114   }
115 
116   /// Create MemoryEffectsBase that cannot read or write any memory.
117   static MemoryEffectsBase none() {
118     return MemoryEffectsBase(ModRefInfo::NoModRef);
119   }
120 
121   /// Create MemoryEffectsBase that can read any memory.
122   static MemoryEffectsBase readOnly() {
123     return MemoryEffectsBase(ModRefInfo::Ref);
124   }
125 
126   /// Create MemoryEffectsBase that can write any memory.
127   static MemoryEffectsBase writeOnly() {
128     return MemoryEffectsBase(ModRefInfo::Mod);
129   }
130 
131   /// Create MemoryEffectsBase that can only access argument memory.
132   static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
133     return MemoryEffectsBase(Location::ArgMem, MR);
134   }
135 
136   /// Create MemoryEffectsBase that can only access inaccessible memory.
137   static MemoryEffectsBase
138   inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
139     return MemoryEffectsBase(Location::InaccessibleMem, MR);
140   }
141 
142   /// Create MemoryEffectsBase that can only access inaccessible or argument
143   /// memory.
144   static MemoryEffectsBase
145   inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
146     MemoryEffectsBase FRMB = none();
147     FRMB.setModRef(Location::ArgMem, MR);
148     FRMB.setModRef(Location::InaccessibleMem, MR);
149     return FRMB;
150   }
151 
152   /// Create MemoryEffectsBase from an encoded integer value (used by memory
153   /// attribute).
154   static MemoryEffectsBase createFromIntValue(uint32_t Data) {
155     return MemoryEffectsBase(Data);
156   }
157 
158   /// Convert MemoryEffectsBase into an encoded integer value (used by memory
159   /// attribute).
160   uint32_t toIntValue() const {
161     return Data;
162   }
163 
164   /// Get ModRefInfo for the given Location.
165   ModRefInfo getModRef(Location Loc) const {
166     return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
167   }
168 
169   /// Get new MemoryEffectsBase with modified ModRefInfo for Loc.
170   MemoryEffectsBase getWithModRef(Location Loc, ModRefInfo MR) const {
171     MemoryEffectsBase ME = *this;
172     ME.setModRef(Loc, MR);
173     return ME;
174   }
175 
176   /// Get new MemoryEffectsBase with NoModRef on the given Loc.
177   MemoryEffectsBase getWithoutLoc(Location Loc) const {
178     MemoryEffectsBase ME = *this;
179     ME.setModRef(Loc, ModRefInfo::NoModRef);
180     return ME;
181   }
182 
183   /// Get ModRefInfo for any location.
184   ModRefInfo getModRef() const {
185     ModRefInfo MR = ModRefInfo::NoModRef;
186     for (Location Loc : locations())
187       MR |= getModRef(Loc);
188     return MR;
189   }
190 
191   /// Whether this function accesses no memory.
192   bool doesNotAccessMemory() const { return Data == 0; }
193 
194   /// Whether this function only (at most) reads memory.
195   bool onlyReadsMemory() const { return !isModSet(getModRef()); }
196 
197   /// Whether this function only (at most) writes memory.
198   bool onlyWritesMemory() const { return !isRefSet(getModRef()); }
199 
200   /// Whether this function only (at most) accesses argument memory.
201   bool onlyAccessesArgPointees() const {
202     return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
203   }
204 
205   /// Whether this function may access argument memory.
206   bool doesAccessArgPointees() const {
207     return isModOrRefSet(getModRef(Location::ArgMem));
208   }
209 
210   /// Whether this function only (at most) accesses inaccessible memory.
211   bool onlyAccessesInaccessibleMem() const {
212     return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
213   }
214 
215   /// Whether this function only (at most) accesses argument and inaccessible
216   /// memory.
217   bool onlyAccessesInaccessibleOrArgMem() const {
218     return getWithoutLoc(Location::InaccessibleMem)
219         .getWithoutLoc(Location::ArgMem)
220         .doesNotAccessMemory();
221   }
222 
223   /// Intersect with other MemoryEffectsBase.
224   MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
225     return MemoryEffectsBase(Data & Other.Data);
226   }
227 
228   /// Intersect (in-place) with other MemoryEffectsBase.
229   MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
230     Data &= Other.Data;
231     return *this;
232   }
233 
234   /// Union with other MemoryEffectsBase.
235   MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
236     return MemoryEffectsBase(Data | Other.Data);
237   }
238 
239   /// Union (in-place) with other MemoryEffectsBase.
240   MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
241     Data |= Other.Data;
242     return *this;
243   }
244 
245   /// Subtract other MemoryEffectsBase.
246   MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
247     return MemoryEffectsBase(Data & ~Other.Data);
248   }
249 
250   /// Subtract (in-place) with other MemoryEffectsBase.
251   MemoryEffectsBase &operator-=(MemoryEffectsBase Other) {
252     Data &= ~Other.Data;
253     return *this;
254   }
255 
256   /// Check whether this is the same as other MemoryEffectsBase.
257   bool operator==(MemoryEffectsBase Other) const { return Data == Other.Data; }
258 
259   /// Check whether this is different from other MemoryEffectsBase.
260   bool operator!=(MemoryEffectsBase Other) const { return !operator==(Other); }
261 };
262 
263 /// Summary of how a function affects memory in the program.
264 ///
265 /// Loads from constant globals are not considered memory accesses for this
266 /// interface. Also, functions may freely modify stack space local to their
267 /// invocation without having to report it through these interfaces.
268 using MemoryEffects = MemoryEffectsBase<IRMemLocation>;
269 
270 /// Debug print MemoryEffects.
271 raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
272 
273 // Legacy alias.
274 using FunctionModRefBehavior = MemoryEffects;
275 
276 /// Components of the pointer that may be captured.
277 enum class CaptureComponents : uint8_t {
278   None = 0,
279   AddressIsNull = (1 << 0),
280   Address = (1 << 1) | AddressIsNull,
281   ReadProvenance = (1 << 2),
282   Provenance = (1 << 3) | ReadProvenance,
283   All = Address | Provenance,
284   LLVM_MARK_AS_BITMASK_ENUM(Provenance),
285 };
286 
287 inline bool capturesNothing(CaptureComponents CC) {
288   return CC == CaptureComponents::None;
289 }
290 
291 inline bool capturesAnything(CaptureComponents CC) {
292   return CC != CaptureComponents::None;
293 }
294 
295 inline bool capturesAddressIsNullOnly(CaptureComponents CC) {
296   return (CC & CaptureComponents::Address) == CaptureComponents::AddressIsNull;
297 }
298 
299 inline bool capturesAddress(CaptureComponents CC) {
300   return (CC & CaptureComponents::Address) != CaptureComponents::None;
301 }
302 
303 inline bool capturesReadProvenanceOnly(CaptureComponents CC) {
304   return (CC & CaptureComponents::Provenance) ==
305          CaptureComponents::ReadProvenance;
306 }
307 
308 inline bool capturesFullProvenance(CaptureComponents CC) {
309   return (CC & CaptureComponents::Provenance) == CaptureComponents::Provenance;
310 }
311 
312 raw_ostream &operator<<(raw_ostream &OS, CaptureComponents CC);
313 
314 /// Represents which components of the pointer may be captured in which
315 /// location. This represents the captures(...) attribute in IR.
316 ///
317 /// For more information on the precise semantics see LangRef.
318 class CaptureInfo {
319   CaptureComponents OtherComponents;
320   CaptureComponents RetComponents;
321 
322 public:
323   CaptureInfo(CaptureComponents OtherComponents,
324               CaptureComponents RetComponents)
325       : OtherComponents(OtherComponents), RetComponents(RetComponents) {}
326 
327   CaptureInfo(CaptureComponents Components)
328       : OtherComponents(Components), RetComponents(Components) {}
329 
330   /// Create CaptureInfo that does not capture any components of the pointer
331   static CaptureInfo none() { return CaptureInfo(CaptureComponents::None); }
332 
333   /// Create CaptureInfo that may capture all components of the pointer.
334   static CaptureInfo all() { return CaptureInfo(CaptureComponents::All); }
335 
336   /// Get components potentially captured by the return value.
337   CaptureComponents getRetComponents() const { return RetComponents; }
338 
339   /// Get components potentially captured through locations other than the
340   /// return value.
341   CaptureComponents getOtherComponents() const { return OtherComponents; }
342 
343   /// Get the potentially captured components of the pointer (regardless of
344   /// location).
345   operator CaptureComponents() const { return OtherComponents | RetComponents; }
346 
347   bool operator==(CaptureInfo Other) const {
348     return OtherComponents == Other.OtherComponents &&
349            RetComponents == Other.RetComponents;
350   }
351 
352   bool operator!=(CaptureInfo Other) const { return !(*this == Other); }
353 
354   /// Compute union of CaptureInfos.
355   CaptureInfo operator|(CaptureInfo Other) const {
356     return CaptureInfo(OtherComponents | Other.OtherComponents,
357                        RetComponents | Other.RetComponents);
358   }
359 
360   /// Compute intersection of CaptureInfos.
361   CaptureInfo operator&(CaptureInfo Other) const {
362     return CaptureInfo(OtherComponents & Other.OtherComponents,
363                        RetComponents & Other.RetComponents);
364   }
365 
366   /// Compute union of CaptureInfos in-place.
367   CaptureInfo &operator|=(CaptureInfo Other) {
368     OtherComponents |= Other.OtherComponents;
369     RetComponents |= Other.RetComponents;
370     return *this;
371   }
372 
373   /// Compute intersection of CaptureInfos in-place.
374   CaptureInfo &operator&=(CaptureInfo Other) {
375     OtherComponents &= Other.OtherComponents;
376     RetComponents &= Other.RetComponents;
377     return *this;
378   }
379 
380   static CaptureInfo createFromIntValue(uint32_t Data) {
381     return CaptureInfo(CaptureComponents(Data >> 4),
382                        CaptureComponents(Data & 0xf));
383   }
384 
385   /// Convert CaptureInfo into an encoded integer value (used by captures
386   /// attribute).
387   uint32_t toIntValue() const {
388     return (uint32_t(OtherComponents) << 4) | uint32_t(RetComponents);
389   }
390 };
391 
392 raw_ostream &operator<<(raw_ostream &OS, CaptureInfo Info);
393 
394 } // namespace llvm
395 
396 #endif
397