123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #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_IR_MODREF_H
- #define LLVM_IR_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);
- /// 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.
- class MemoryEffects {
- public:
- /// The locations at which a function might access memory.
- enum Location {
- /// Access to memory via argument pointers.
- ArgMem = 0,
- /// Memory that is inaccessible via LLVM IR.
- InaccessibleMem = 1,
- /// Any other memory.
- Other = 2,
- };
- 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;
- }
- MemoryEffects(uint32_t Data) : Data(Data) {}
- void setModRef(Location Loc, ModRefInfo MR) {
- Data &= ~(LocMask << getLocationPos(Loc));
- Data |= static_cast<uint32_t>(MR) << getLocationPos(Loc);
- }
- friend raw_ostream &operator<<(raw_ostream &OS, MemoryEffects RMRB);
- public:
- /// Returns iterator over all supported location kinds.
- static auto locations() {
- return enum_seq_inclusive(Location::ArgMem, Location::Other,
- force_iteration_on_noniterable_enum);
- }
- /// Create MemoryEffects that can access only the given location with the
- /// given ModRefInfo.
- MemoryEffects(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
- /// Create MemoryEffects that can access any location with the given
- /// ModRefInfo.
- explicit MemoryEffects(ModRefInfo MR) {
- for (Location Loc : locations())
- setModRef(Loc, MR);
- }
- /// Create MemoryEffects that can read and write any memory.
- static MemoryEffects unknown() {
- return MemoryEffects(ModRefInfo::ModRef);
- }
- /// Create MemoryEffects that cannot read or write any memory.
- static MemoryEffects none() {
- return MemoryEffects(ModRefInfo::NoModRef);
- }
- /// Create MemoryEffects that can read any memory.
- static MemoryEffects readOnly() {
- return MemoryEffects(ModRefInfo::Ref);
- }
- /// Create MemoryEffects that can write any memory.
- static MemoryEffects writeOnly() {
- return MemoryEffects(ModRefInfo::Mod);
- }
- /// Create MemoryEffects that can only access argument memory.
- static MemoryEffects argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- return MemoryEffects(ArgMem, MR);
- }
- /// Create MemoryEffects that can only access inaccessible memory.
- static MemoryEffects inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- return MemoryEffects(InaccessibleMem, MR);
- }
- /// Create MemoryEffects that can only access inaccessible or argument memory.
- static MemoryEffects
- inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- MemoryEffects FRMB = none();
- FRMB.setModRef(ArgMem, MR);
- FRMB.setModRef(InaccessibleMem, MR);
- return FRMB;
- }
- /// Create MemoryEffects from an encoded integer value (used by memory
- /// attribute).
- static MemoryEffects createFromIntValue(uint32_t Data) {
- return MemoryEffects(Data);
- }
- /// Convert MemoryEffects 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 MemoryEffects with modified ModRefInfo for Loc.
- MemoryEffects getWithModRef(Location Loc, ModRefInfo MR) const {
- MemoryEffects ME = *this;
- ME.setModRef(Loc, MR);
- return ME;
- }
- /// Get new MemoryEffects with NoModRef on the given Loc.
- MemoryEffects getWithoutLoc(Location Loc) const {
- MemoryEffects 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(ArgMem).doesNotAccessMemory();
- }
- /// Whether this function may access argument memory.
- bool doesAccessArgPointees() const {
- return isModOrRefSet(getModRef(ArgMem));
- }
- /// Whether this function only (at most) accesses inaccessible memory.
- bool onlyAccessesInaccessibleMem() const {
- return getWithoutLoc(InaccessibleMem).doesNotAccessMemory();
- }
- /// Whether this function only (at most) accesses argument and inaccessible
- /// memory.
- bool onlyAccessesInaccessibleOrArgMem() const {
- return isNoModRef(getModRef(Other));
- }
- /// Intersect with other MemoryEffects.
- MemoryEffects operator&(MemoryEffects Other) const {
- return MemoryEffects(Data & Other.Data);
- }
- /// Intersect (in-place) with other MemoryEffects.
- MemoryEffects &operator&=(MemoryEffects Other) {
- Data &= Other.Data;
- return *this;
- }
- /// Union with other MemoryEffects.
- MemoryEffects operator|(MemoryEffects Other) const {
- return MemoryEffects(Data | Other.Data);
- }
- /// Union (in-place) with other MemoryEffects.
- MemoryEffects &operator|=(MemoryEffects Other) {
- Data |= Other.Data;
- return *this;
- }
- /// Check whether this is the same as other MemoryEffects.
- bool operator==(MemoryEffects Other) const {
- return Data == Other.Data;
- }
- /// Check whether this is different from other MemoryEffects.
- bool operator!=(MemoryEffects Other) const {
- return !operator==(Other);
- }
- };
- /// 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
|