[llvm] a90ac20 - [MemoryEffects][NFCI] Make the MemoryEffects class reusable
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 3 10:07:25 PDT 2023
Author: Johannes Doerfert
Date: 2023-07-03T10:07:03-07:00
New Revision: a90ac20c528f65ea50d14bc261bb65f7446b2231
URL: https://github.com/llvm/llvm-project/commit/a90ac20c528f65ea50d14bc261bb65f7446b2231
DIFF: https://github.com/llvm/llvm-project/commit/a90ac20c528f65ea50d14bc261bb65f7446b2231.diff
LOG: [MemoryEffects][NFCI] Make the MemoryEffects class reusable
In a follow up we will reuse the logic in MemoryEffectsBase to merge
AAMemoryLocation and AAMemoryBehavior without duplicating all the bit
fiddling code already available in MemoryEffectsBase.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D153305
Added:
Modified:
llvm/include/llvm/AsmParser/LLParser.h
llvm/include/llvm/IR/Attributes.h
llvm/include/llvm/Support/ModRef.h
llvm/lib/Analysis/AliasAnalysis.cpp
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/IR/Attributes.cpp
llvm/lib/Transforms/IPO/FunctionAttrs.cpp
llvm/lib/Transforms/IPO/SCCP.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 63cb61ae3a19df..eca908a24aac7b 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -20,6 +20,7 @@
#include "llvm/IR/FMF.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Support/ModRef.h"
#include <map>
#include <optional>
@@ -42,7 +43,6 @@ namespace llvm {
class Comdat;
class MDString;
class MDNode;
- class MemoryEffects;
struct SlotMapping;
/// ValID - Represents a reference of a definition of some sort with no type.
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 4982b11ece6fb4..db33b540047168 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -22,6 +22,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ModRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <cstdint>
@@ -39,7 +40,6 @@ class AttributeSetNode;
class FoldingSetNodeID;
class Function;
class LLVMContext;
-class MemoryEffects;
class Type;
class raw_ostream;
enum FPClassTest : unsigned;
diff --git a/llvm/include/llvm/Support/ModRef.h b/llvm/include/llvm/Support/ModRef.h
index d135625fc8a1ac..ac088620e2ba80 100644
--- a/llvm/include/llvm/Support/ModRef.h
+++ b/llvm/include/llvm/Support/ModRef.h
@@ -55,22 +55,23 @@ enum class ModRefInfo : uint8_t {
/// 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 {
+/// The locations at which a function might access memory.
+enum 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:
- /// 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,
- };
+ using Location = LocationEnum;
private:
uint32_t Data = 0;
@@ -82,79 +83,79 @@ class MemoryEffects {
return (uint32_t)Loc * BitsPerLoc;
}
- MemoryEffects(uint32_t Data) : Data(Data) {}
+ MemoryEffectsBase(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,
+ return enum_seq_inclusive(Location::First, Location::Last,
force_iteration_on_noniterable_enum);
}
- /// Create MemoryEffects that can access only the given location with the
+ /// Create MemoryEffectsBase that can access only the given location with the
/// given ModRefInfo.
- MemoryEffects(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
+ MemoryEffectsBase(Location Loc, ModRefInfo MR) { setModRef(Loc, MR); }
- /// Create MemoryEffects that can access any location with the given
+ /// Create MemoryEffectsBase that can access any location with the given
/// ModRefInfo.
- explicit MemoryEffects(ModRefInfo MR) {
+ explicit MemoryEffectsBase(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 MemoryEffectsBase that can read and write any memory.
+ static MemoryEffectsBase unknown() {
+ return MemoryEffectsBase(ModRefInfo::ModRef);
}
- /// Create MemoryEffects that cannot read or write any memory.
- static MemoryEffects none() {
- return MemoryEffects(ModRefInfo::NoModRef);
+ /// Create MemoryEffectsBase that cannot read or write any memory.
+ static MemoryEffectsBase none() {
+ return MemoryEffectsBase(ModRefInfo::NoModRef);
}
- /// Create MemoryEffects that can read any memory.
- static MemoryEffects readOnly() {
- return MemoryEffects(ModRefInfo::Ref);
+ /// Create MemoryEffectsBase that can read any memory.
+ static MemoryEffectsBase readOnly() {
+ return MemoryEffectsBase(ModRefInfo::Ref);
}
- /// Create MemoryEffects that can write any memory.
- static MemoryEffects writeOnly() {
- return MemoryEffects(ModRefInfo::Mod);
+ /// Create MemoryEffectsBase that can write any memory.
+ static MemoryEffectsBase writeOnly() {
+ return MemoryEffectsBase(ModRefInfo::Mod);
}
- /// Create MemoryEffects that can only access argument memory.
- static MemoryEffects argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- return MemoryEffects(ArgMem, MR);
+ /// Create MemoryEffectsBase that can only access argument memory.
+ static MemoryEffectsBase argMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
+ return MemoryEffectsBase(Location::ArgMem, MR);
}
- /// Create MemoryEffects that can only access inaccessible memory.
- static MemoryEffects inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- return MemoryEffects(InaccessibleMem, MR);
+ /// Create MemoryEffectsBase that can only access inaccessible memory.
+ static MemoryEffectsBase
+ inaccessibleMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
+ return MemoryEffectsBase(Location::InaccessibleMem, MR);
}
- /// Create MemoryEffects that can only access inaccessible or argument memory.
- static MemoryEffects
+ /// Create MemoryEffectsBase that can only access inaccessible or argument
+ /// memory.
+ static MemoryEffectsBase
inaccessibleOrArgMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
- MemoryEffects FRMB = none();
- FRMB.setModRef(ArgMem, MR);
- FRMB.setModRef(InaccessibleMem, MR);
+ MemoryEffectsBase FRMB = none();
+ FRMB.setModRef(Location::ArgMem, MR);
+ FRMB.setModRef(Location::InaccessibleMem, MR);
return FRMB;
}
- /// Create MemoryEffects from an encoded integer value (used by memory
+ /// Create MemoryEffectsBase from an encoded integer value (used by memory
/// attribute).
- static MemoryEffects createFromIntValue(uint32_t Data) {
- return MemoryEffects(Data);
+ static MemoryEffectsBase createFromIntValue(uint32_t Data) {
+ return MemoryEffectsBase(Data);
}
- /// Convert MemoryEffects into an encoded integer value (used by memory
+ /// Convert MemoryEffectsBase into an encoded integer value (used by memory
/// attribute).
uint32_t toIntValue() const {
return Data;
@@ -165,16 +166,16 @@ class MemoryEffects {
return ModRefInfo((Data >> getLocationPos(Loc)) & LocMask);
}
- /// Get new MemoryEffects with modified ModRefInfo for Loc.
- MemoryEffects getWithModRef(Location Loc, ModRefInfo MR) const {
- MemoryEffects ME = *this;
+ /// 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 MemoryEffects with NoModRef on the given Loc.
- MemoryEffects getWithoutLoc(Location Loc) const {
- MemoryEffects ME = *this;
+ /// Get new MemoryEffectsBase with NoModRef on the given Loc.
+ MemoryEffectsBase getWithoutLoc(Location Loc) const {
+ MemoryEffectsBase ME = *this;
ME.setModRef(Loc, ModRefInfo::NoModRef);
return ME;
}
@@ -198,58 +199,74 @@ class MemoryEffects {
/// Whether this function only (at most) accesses argument memory.
bool onlyAccessesArgPointees() const {
- return getWithoutLoc(ArgMem).doesNotAccessMemory();
+ return getWithoutLoc(Location::ArgMem).doesNotAccessMemory();
}
/// Whether this function may access argument memory.
bool doesAccessArgPointees() const {
- return isModOrRefSet(getModRef(ArgMem));
+ return isModOrRefSet(getModRef(Location::ArgMem));
}
/// Whether this function only (at most) accesses inaccessible memory.
bool onlyAccessesInaccessibleMem() const {
- return getWithoutLoc(InaccessibleMem).doesNotAccessMemory();
+ return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
}
/// Whether this function only (at most) accesses argument and inaccessible
/// memory.
bool onlyAccessesInaccessibleOrArgMem() const {
- return isNoModRef(getModRef(Other));
+ return getWithoutLoc(Location::InaccessibleMem)
+ .getWithoutLoc(Location::ArgMem)
+ .doesNotAccessMemory();
}
- /// Intersect with other MemoryEffects.
- MemoryEffects operator&(MemoryEffects Other) const {
- return MemoryEffects(Data & Other.Data);
+ /// Intersect with other MemoryEffectsBase.
+ MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
+ return MemoryEffectsBase(Data & Other.Data);
}
- /// Intersect (in-place) with other MemoryEffects.
- MemoryEffects &operator&=(MemoryEffects Other) {
+ /// Intersect (in-place) with other MemoryEffectsBase.
+ MemoryEffectsBase &operator&=(MemoryEffectsBase Other) {
Data &= Other.Data;
return *this;
}
- /// Union with other MemoryEffects.
- MemoryEffects operator|(MemoryEffects Other) const {
- return MemoryEffects(Data | Other.Data);
+ /// Union with other MemoryEffectsBase.
+ MemoryEffectsBase operator|(MemoryEffectsBase Other) const {
+ return MemoryEffectsBase(Data | Other.Data);
}
- /// Union (in-place) with other MemoryEffects.
- MemoryEffects &operator|=(MemoryEffects Other) {
+ /// Union (in-place) with other MemoryEffectsBase.
+ MemoryEffectsBase &operator|=(MemoryEffectsBase Other) {
Data |= Other.Data;
return *this;
}
- /// Check whether this is the same as other MemoryEffects.
- bool operator==(MemoryEffects Other) const {
- return Data == Other.Data;
+ /// Subtract other MemoryEffectsBase.
+ MemoryEffectsBase operator-(MemoryEffectsBase Other) const {
+ return MemoryEffectsBase(Data & ~Other.Data);
}
- /// Check whether this is
diff erent from other MemoryEffects.
- bool operator!=(MemoryEffects Other) const {
- return !operator==(Other);
+ /// 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
diff erent 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);
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
index a5338afee85b1e..7b2f91f5392a5b 100644
--- a/llvm/lib/Analysis/AliasAnalysis.cpp
+++ b/llvm/lib/Analysis/AliasAnalysis.cpp
@@ -227,12 +227,12 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
// We can completely ignore inaccessible memory here, because MemoryLocations
// can only reference accessible memory.
auto ME = getMemoryEffects(Call, AAQI)
- .getWithoutLoc(MemoryEffects::InaccessibleMem);
+ .getWithoutLoc(IRMemLocation::InaccessibleMem);
if (ME.doesNotAccessMemory())
return ModRefInfo::NoModRef;
- ModRefInfo ArgMR = ME.getModRef(MemoryEffects::ArgMem);
- ModRefInfo OtherMR = ME.getWithoutLoc(MemoryEffects::ArgMem).getModRef();
+ ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
+ ModRefInfo OtherMR = ME.getWithoutLoc(IRMemLocation::ArgMem).getModRef();
if ((ArgMR | OtherMR) != OtherMR) {
// Refine the modref info for argument memory. We only bother to do this
// if ArgMR is not a subset of OtherMR, otherwise this won't have an impact
@@ -442,15 +442,15 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, ModRefInfo MR) {
}
raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
- for (MemoryEffects::Location Loc : MemoryEffects::locations()) {
+ for (IRMemLocation Loc : MemoryEffects::locations()) {
switch (Loc) {
- case MemoryEffects::ArgMem:
+ case IRMemLocation::ArgMem:
OS << "ArgMem: ";
break;
- case MemoryEffects::InaccessibleMem:
+ case IRMemLocation::InaccessibleMem:
OS << "InaccessibleMem: ";
break;
- case MemoryEffects::Other:
+ case IRMemLocation::Other:
OS << "Other: ";
break;
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 1638791e3f5eb2..dcb3476a2d840a 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -2279,9 +2279,9 @@ bool LLParser::parseAllocKind(AllocFnKind &Kind) {
static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
switch (Tok) {
case lltok::kw_argmem:
- return MemoryEffects::ArgMem;
+ return IRMemLocation::ArgMem;
case lltok::kw_inaccessiblemem:
- return MemoryEffects::InaccessibleMem;
+ return IRMemLocation::InaccessibleMem;
default:
return std::nullopt;
}
@@ -2318,7 +2318,7 @@ std::optional<MemoryEffects> LLParser::parseMemoryAttr() {
bool SeenLoc = false;
do {
- std::optional<MemoryEffects::Location> Loc = keywordToLoc(Lex.getKind());
+ std::optional<IRMemLocation> Loc = keywordToLoc(Lex.getKind());
if (Loc) {
Lex.Lex();
if (!EatIfPresent(lltok::colon)) {
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 710e29e348a865..3d89d18e5822be 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -523,7 +523,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
// Print access kind for "other" as the default access kind. This way it
// will apply to any new location kinds that get split out of "other".
- ModRefInfo OtherMR = ME.getModRef(MemoryEffects::Other);
+ ModRefInfo OtherMR = ME.getModRef(IRMemLocation::Other);
if (OtherMR != ModRefInfo::NoModRef || ME.getModRef() == OtherMR) {
First = false;
OS << getModRefStr(OtherMR);
@@ -539,13 +539,13 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
First = false;
switch (Loc) {
- case MemoryEffects::ArgMem:
+ case IRMemLocation::ArgMem:
OS << "argmem: ";
break;
- case MemoryEffects::InaccessibleMem:
+ case IRMemLocation::InaccessibleMem:
OS << "inaccessiblemem: ";
break;
- case MemoryEffects::Other:
+ case IRMemLocation::Other:
llvm_unreachable("This is represented as the default access kind");
}
OS << getModRefStr(MR);
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index e7a0c93f2afdac..34299f9dbb2325 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -152,7 +152,7 @@ static MemoryEffects checkFunctionMemoryAccess(Function &F, bool ThisBody,
// If it's not an identified object, it might be an argument.
if (!isIdentifiedObject(UO))
ME |= MemoryEffects::argMemOnly(MR);
- ME |= MemoryEffects(MemoryEffects::Other, MR);
+ ME |= MemoryEffects(IRMemLocation::Other, MR);
};
// Scan the function body for instructions that may read or write memory.
for (Instruction &I : instructions(F)) {
@@ -179,17 +179,17 @@ static MemoryEffects checkFunctionMemoryAccess(Function &F, bool ThisBody,
if (isa<PseudoProbeInst>(I))
continue;
- ME |= CallME.getWithoutLoc(MemoryEffects::ArgMem);
+ ME |= CallME.getWithoutLoc(IRMemLocation::ArgMem);
// If the call accesses captured memory (currently part of "other") and
// an argument is captured (currently not tracked), then it may also
// access argument memory.
- ModRefInfo OtherMR = CallME.getModRef(MemoryEffects::Other);
+ ModRefInfo OtherMR = CallME.getModRef(IRMemLocation::Other);
ME |= MemoryEffects::argMemOnly(OtherMR);
// Check whether all pointer arguments point to local memory, and
// ignore calls that only access local memory.
- ModRefInfo ArgMR = CallME.getModRef(MemoryEffects::ArgMem);
+ ModRefInfo ArgMR = CallME.getModRef(IRMemLocation::ArgMem);
if (ArgMR != ModRefInfo::NoModRef) {
for (const Use &U : Call->args()) {
const Value *Arg = U;
diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index 985ae0062b0ec4..e2e6364df9065a 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -191,8 +191,8 @@ static bool runIPSCCP(
if (ME == MemoryEffects::unknown())
return AL;
- ME |= MemoryEffects(MemoryEffects::Other,
- ME.getModRef(MemoryEffects::ArgMem));
+ ME |= MemoryEffects(IRMemLocation::Other,
+ ME.getModRef(IRMemLocation::ArgMem));
return AL.addFnAttribute(
F.getContext(),
Attribute::getWithMemoryEffects(F.getContext(), ME));
More information about the llvm-commits
mailing list