summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm18/include/llvm/Support/ModRef.h
blob: 94d39ef689cab8fd0c8b3a33bf8300886b0d5c53 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===--- ModRef.h - Memory effect modelling ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Definitions of ModRefInfo and MemoryEffects, which are used to
// describe the memory effects of instructions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_MODREF_H
#define LLVM_SUPPORT_MODREF_H

#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {

/// Flags indicating whether a memory access modifies or references memory.
///
/// This is no access at all, a modification, a reference, or both
/// a modification and a reference.
enum class ModRefInfo : uint8_t {
  /// The access neither references nor modifies the value stored in memory.
  NoModRef = 0,
  /// The access may reference the value stored in memory.
  Ref = 1,
  /// The access may modify the value stored in memory.
  Mod = 2,
  /// The access may reference and may modify the value stored in memory.
  ModRef = Ref | Mod,
  LLVM_MARK_AS_BITMASK_ENUM(ModRef),
};

[[nodiscard]] inline bool isNoModRef(const ModRefInfo MRI) {
  return MRI == ModRefInfo::NoModRef;
}
[[nodiscard]] inline bool isModOrRefSet(const ModRefInfo MRI) {
  return MRI != ModRefInfo::NoModRef;
}
[[nodiscard]] inline bool isModAndRefSet(const ModRefInfo MRI) {
  return MRI == ModRefInfo::ModRef;
}
[[nodiscard]] inline bool isModSet(const ModRefInfo MRI) {
  return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Mod);
}
[[nodiscard]] inline bool isRefSet(const ModRefInfo MRI) {
  return static_cast<int>(MRI) & static_cast<int>(ModRefInfo::Ref);
}

/// Debug print ModRefInfo.
raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);

/// The locations at which a function might access memory.
enum class IRMemLocation {
  /// Access to memory via argument pointers.
  ArgMem = 0,
  /// Memory that is inaccessible via LLVM IR.
  InaccessibleMem = 1,
  /// Any other memory.
  Other = 2,

  /// Helpers to iterate all locations in the MemoryEffectsBase class.
  First = ArgMem,
  Last = Other,
};

template <typename LocationEnum> class MemoryEffectsBase {
public:
  using Location = LocationEnum;

private:
  uint32_t Data = 0;

  static constexpr uint32_t BitsPerLoc = 2;
  static constexpr uint32_t LocMask = (1 << BitsPerLoc) - 1;

  static uint32_t getLocationPos(Location Loc) {
    return (uint32_t)Loc * BitsPerLoc;
  }

  MemoryEffectsBase(uint32_t Data) : Data(Data) {}

  void setModRef(Location Loc, ModRefInfo MR) {
    Data &= ~(LocMask << getLocationPos(Loc));
    Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
  }

public:
  /// Returns iterator over all supported location kinds.
  static auto locations() {
    return enum_seq_inclusive(Location::First, Location::Last,
                              force_iteration_on_noniterable_enum);
  }

  /// Create MemoryEffectsBase that can access only the given location with the
  /// given ModRefInfo.
  MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }

  /// Create MemoryEffectsBase that can access any location with the given
  /// ModRefInfo.
  explicit MemoryEffectsBase(ModRefInfo MR) {
    for (Location Loc : locations())
      setModRef(Loc, MR);
  }

  /// Create MemoryEffectsBase that can read and write any memory.
  static MemoryEffectsBase unknown() {
    return MemoryEffectsBase(ModRefInfo::ModRef);
  }

  /// Create MemoryEffectsBase that cannot read or write any memory.
  static MemoryEffectsBase none() {
    return MemoryEffectsBase(ModRefInfo::NoModRef);
  }

  /// Create MemoryEffectsBase that can read any memory.
  static MemoryEffectsBase readOnly() {
    return MemoryEffectsBase(ModRefInfo::Ref);
  }

  /// Create MemoryEffectsBase that can write any memory.
  static MemoryEffectsBase writeOnly() {
    return MemoryEffectsBase(ModRefInfo::Mod);
  }

  /// Create MemoryEffectsBase that can only access argument memory.
  static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
    return MemoryEffectsBase(Location::ArgMem, MR);
  }

  /// Create MemoryEffectsBase that can only access inaccessible memory.
  static MemoryEffectsBase
  inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
    return MemoryEffectsBase(Location::InaccessibleMem, MR);
  }

  /// Create MemoryEffectsBase that can only access inaccessible or argument
  /// memory.
  static MemoryEffectsBase
  inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
    MemoryEffectsBase FRMB = none();
    FRMB.setModRef(Location::ArgMem, MR);
    FRMB.setModRef(Location::InaccessibleMem, MR);
    return FRMB;
  }

  /// Create MemoryEffectsBase from an encoded integer value (used by memory
  /// attribute).
  static MemoryEffectsBase createFromIntValue(uint32_t Data) {
    return MemoryEffectsBase(Data);
  }

  /// Convert MemoryEffectsBase into an encoded integer value (used by memory
  /// attribute).
  uint32_t toIntValue() const {
    return Data;
  }

  /// Get ModRefInfo for the given Location.
  ModRefInfo getModRef(Location Loc) const {
    return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
  }

  /// Get new MemoryEffectsBase with modified ModRefInfo for Loc.
  MemoryEffectsBase getWithModRef(Location Loc, ModRefInfo MR) const {
    MemoryEffectsBase ME = *this;
    ME.setModRef(Loc, MR);
    return ME;
  }

  /// Get new MemoryEffectsBase with NoModRef on the given Loc.
  MemoryEffectsBase getWithoutLoc(Location Loc) const {
    MemoryEffectsBase ME = *this;
    ME.setModRef(Loc, ModRefInfo::NoModRef);
    return ME;
  }

  /// Get ModRefInfo for any location.
  ModRefInfo getModRef() const {
    ModRefInfo MR = ModRefInfo::NoModRef;
    for (Location Loc : locations())
      MR |= getModRef(Loc);
    return MR;
  }

  /// Whether this function accesses no memory.
  bool doesNotAccessMemory() const { return Data == 0; }

  /// Whether this function only (at most) reads memory.
  bool onlyReadsMemory() const { return !isModSet(getModRef()); }

  /// Whether this function only (at most) writes memory.
  bool onlyWritesMemory() const { return !isRefSet(getModRef()); }

  /// Whether this function only (at most) accesses argument memory.
  bool onlyAccessesArgPointees() const {
    return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
  }

  /// Whether this function may access argument memory.
  bool doesAccessArgPointees() const {
    return isModOrRefSet(getModRef(Location::ArgMem));
  }

  /// Whether this function only (at most) accesses inaccessible memory.
  bool onlyAccessesInaccessibleMem() const {
    return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
  }

  /// Whether this function only (at most) accesses argument and inaccessible
  /// memory.
  bool onlyAccessesInaccessibleOrArgMem() const {
    return getWithoutLoc(Location::InaccessibleMem)
        .getWithoutLoc(Location::ArgMem)
        .doesNotAccessMemory();
  }

  /// Intersect with other MemoryEffectsBase.
  MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
    return MemoryEffectsBase(Data & Other.Data);
  }

  /// Intersect (in-place) with other MemoryEffectsBase.
  MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
    Data &= Other.Data;
    return *this;
  }

  /// Union with other MemoryEffectsBase.
  MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
    return MemoryEffectsBase(Data | Other.Data);
  }

  /// Union (in-place) with other MemoryEffectsBase.
  MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
    Data |= Other.Data;
    return *this;
  }

  /// Subtract other MemoryEffectsBase.
  MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
    return MemoryEffectsBase(Data & ~Other.Data);
  }

  /// Subtract (in-place) with other MemoryEffectsBase.
  MemoryEffectsBase &operator-=(MemoryEffectsBase Other) {
    Data &= ~Other.Data;
    return *this;
  }

  /// Check whether this is the same as other MemoryEffectsBase.
  bool operator==(MemoryEffectsBase Other) const { return Data == Other.Data; }

  /// Check whether this is different from other MemoryEffectsBase.
  bool operator!=(MemoryEffectsBase Other) const { return !operator==(Other); }
};

/// Summary of how a function affects memory in the program.
///
/// Loads from constant globals are not considered memory accesses for this
/// interface. Also, functions may freely modify stack space local to their
/// invocation without having to report it through these interfaces.
using MemoryEffects = MemoryEffectsBase<IRMemLocation>;

/// Debug print MemoryEffects.
raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);

// Legacy alias.
using FunctionModRefBehavior = MemoryEffects;

} // namespace llvm

#endif

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif