xref: /openbsd/gnu/llvm/llvm/include/llvm/Support/ModRef.h (revision d415bd75)
1 //===--- ModRef.h - Memory effect modelling ---------------------*- 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_IR_MODREF_H
15 #define LLVM_IR_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 
isNoModRef(const ModRefInfo MRI)39 [[nodiscard]] inline bool isNoModRef(const ModRefInfo MRI) {
40   return MRI == ModRefInfo::NoModRef;
41 }
isModOrRefSet(const ModRefInfo MRI)42 [[nodiscard]] inline bool isModOrRefSet(const ModRefInfo MRI) {
43   return MRI != ModRefInfo::NoModRef;
44 }
isModAndRefSet(const ModRefInfo MRI)45 [[nodiscard]] inline bool isModAndRefSet(const ModRefInfo MRI) {
46   return MRI == ModRefInfo::ModRef;
47 }
isModSet(const ModRefInfo MRI)48 [[nodiscard]] inline bool isModSet(const ModRefInfo MRI) {
49   return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod);
50 }
isRefSet(const ModRefInfo MRI)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 /// Summary of how a function affects memory in the program.
59 ///
60 /// Loads from constant globals are not considered memory accesses for this
61 /// interface. Also, functions may freely modify stack space local to their
62 /// invocation without having to report it through these interfaces.
63 class MemoryEffects {
64 public:
65   /// The locations at which a function might access memory.
66   enum Location {
67     /// Access to memory via argument pointers.
68     ArgMem = 0,
69     /// Memory that is inaccessible via LLVM IR.
70     InaccessibleMem = 1,
71     /// Any other memory.
72     Other = 2,
73   };
74 
75 private:
76   uint32_t Data = 0;
77 
78   static constexpr uint32_t BitsPerLoc = 2;
79   static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;
80 
getLocationPos(Location Loc)81   static uint32_t getLocationPos(Location Loc) {
82     return (uint32_t)Loc * BitsPerLoc;
83   }
84 
MemoryEffects(uint32_t Data)85   MemoryEffects(uint32_t Data) : Data(Data) {}
86 
setModRef(Location Loc,ModRefInfo MR)87   void setModRef(Location Loc, ModRefInfo MR) {
88     Data &= ~(LocMask << getLocationPos(Loc));
89     Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
90   }
91 
92   friend raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
93 
94 public:
95   /// Returns iterator over all supported location kinds.
locations()96   static auto locations() {
97     return enum_seq_inclusive(Location::ArgMem, Location::Other,
98                               force_iteration_on_noniterable_enum);
99   }
100 
101   /// Create MemoryEffects that can access only the given location with the
102   /// given ModRefInfo.
MemoryEffects(Location Loc,ModRefInfo MR)103   MemoryEffects(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
104 
105   /// Create MemoryEffects that can access any location with the given
106   /// ModRefInfo.
MemoryEffects(ModRefInfo MR)107   explicit MemoryEffects(ModRefInfo MR) {
108     for (Location Loc : locations())
109       setModRef(Loc, MR);
110   }
111 
112   /// Create MemoryEffects that can read and write any memory.
unknown()113   static MemoryEffects unknown() {
114     return MemoryEffects(ModRefInfo::ModRef);
115   }
116 
117   /// Create MemoryEffects that cannot read or write any memory.
none()118   static MemoryEffects none() {
119     return MemoryEffects(ModRefInfo::NoModRef);
120   }
121 
122   /// Create MemoryEffects that can read any memory.
readOnly()123   static MemoryEffects readOnly() {
124     return MemoryEffects(ModRefInfo::Ref);
125   }
126 
127   /// Create MemoryEffects that can write any memory.
writeOnly()128   static MemoryEffects writeOnly() {
129     return MemoryEffects(ModRefInfo::Mod);
130   }
131 
132   /// Create MemoryEffects that can only access argument memory.
133   static MemoryEffects argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
134     return MemoryEffects(ArgMem, MR);
135   }
136 
137   /// Create MemoryEffects that can only access inaccessible memory.
138   static MemoryEffects inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
139     return MemoryEffects(InaccessibleMem, MR);
140   }
141 
142   /// Create MemoryEffects that can only access inaccessible or argument memory.
143   static MemoryEffects
144   inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
145     MemoryEffects FRMB = none();
146     FRMB.setModRef(ArgMem, MR);
147     FRMB.setModRef(InaccessibleMem, MR);
148     return FRMB;
149   }
150 
151   /// Create MemoryEffects from an encoded integer value (used by memory
152   /// attribute).
createFromIntValue(uint32_t Data)153   static MemoryEffects createFromIntValue(uint32_t Data) {
154     return MemoryEffects(Data);
155   }
156 
157   /// Convert MemoryEffects into an encoded integer value (used by memory
158   /// attribute).
toIntValue()159   uint32_t toIntValue() const {
160     return Data;
161   }
162 
163   /// Get ModRefInfo for the given Location.
getModRef(Location Loc)164   ModRefInfo getModRef(Location Loc) const {
165     return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
166   }
167 
168   /// Get new MemoryEffects with modified ModRefInfo for Loc.
getWithModRef(Location Loc,ModRefInfo MR)169   MemoryEffects getWithModRef(Location Loc, ModRefInfo MR) const {
170     MemoryEffects ME = *this;
171     ME.setModRef(Loc, MR);
172     return ME;
173   }
174 
175   /// Get new MemoryEffects with NoModRef on the given Loc.
getWithoutLoc(Location Loc)176   MemoryEffects getWithoutLoc(Location Loc) const {
177     MemoryEffects ME = *this;
178     ME.setModRef(Loc, ModRefInfo::NoModRef);
179     return ME;
180   }
181 
182   /// Get ModRefInfo for any location.
getModRef()183   ModRefInfo getModRef() const {
184     ModRefInfo MR = ModRefInfo::NoModRef;
185     for (Location Loc : locations())
186       MR |= getModRef(Loc);
187     return MR;
188   }
189 
190   /// Whether this function accesses no memory.
doesNotAccessMemory()191   bool doesNotAccessMemory() const { return Data == 0; }
192 
193   /// Whether this function only (at most) reads memory.
onlyReadsMemory()194   bool onlyReadsMemory() const { return !isModSet(getModRef()); }
195 
196   /// Whether this function only (at most) writes memory.
onlyWritesMemory()197   bool onlyWritesMemory() const { return !isRefSet(getModRef()); }
198 
199   /// Whether this function only (at most) accesses argument memory.
onlyAccessesArgPointees()200   bool onlyAccessesArgPointees() const {
201     return getWithoutLoc(ArgMem).doesNotAccessMemory();
202   }
203 
204   /// Whether this function may access argument memory.
doesAccessArgPointees()205   bool doesAccessArgPointees() const {
206     return isModOrRefSet(getModRef(ArgMem));
207   }
208 
209   /// Whether this function only (at most) accesses inaccessible memory.
onlyAccessesInaccessibleMem()210   bool onlyAccessesInaccessibleMem() const {
211     return getWithoutLoc(InaccessibleMem).doesNotAccessMemory();
212   }
213 
214   /// Whether this function only (at most) accesses argument and inaccessible
215   /// memory.
onlyAccessesInaccessibleOrArgMem()216   bool onlyAccessesInaccessibleOrArgMem() const {
217     return isNoModRef(getModRef(Other));
218   }
219 
220   /// Intersect with other MemoryEffects.
221   MemoryEffects operator&(MemoryEffects Other) const {
222     return MemoryEffects(Data & Other.Data);
223   }
224 
225   /// Intersect (in-place) with other MemoryEffects.
226   MemoryEffects &operator&=(MemoryEffects Other) {
227     Data &= Other.Data;
228     return *this;
229   }
230 
231   /// Union with other MemoryEffects.
232   MemoryEffects operator|(MemoryEffects Other) const {
233     return MemoryEffects(Data | Other.Data);
234   }
235 
236   /// Union (in-place) with other MemoryEffects.
237   MemoryEffects &operator|=(MemoryEffects Other) {
238     Data |= Other.Data;
239     return *this;
240   }
241 
242   /// Check whether this is the same as other MemoryEffects.
243   bool operator==(MemoryEffects Other) const {
244     return Data == Other.Data;
245   }
246 
247   /// Check whether this is different from other MemoryEffects.
248   bool operator!=(MemoryEffects Other) const {
249     return !operator==(Other);
250   }
251 };
252 
253 /// Debug print MemoryEffects.
254 raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
255 
256 // Legacy alias.
257 using FunctionModRefBehavior = MemoryEffects;
258 
259 } // namespace llvm
260 
261 #endif
262