Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ enum Kind {
kw_readwrite,
kw_argmem,
kw_inaccessiblemem,
kw_aarch64_fpmr,
kw_aarch64_za,
kw_errnomem,

// Legacy attributes:
Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ def IntrArgMemOnly : IntrinsicProperty;
// accessible by the module being compiled. This is a weaker form of IntrNoMem.
def IntrInaccessibleMemOnly : IntrinsicProperty;



class IntrinsicMemoryLocation;
// This should be added in the Target, but once in IntrinsicsAArch64.td
// It complains error: "Variable not defined: 'AArch64_FPMR'"
def AArch64_FPMR : IntrinsicMemoryLocation;
def AArch64_ZA: IntrinsicMemoryLocation;
// IntrInaccessible{Read|Write}MemOnly needs to set Location
class IntrInaccessibleReadMemOnly<IntrinsicMemoryLocation idx> : IntrinsicProperty{IntrinsicMemoryLocation Loc=idx;}
class IntrInaccessibleWriteMemOnly<IntrinsicMemoryLocation idx> : IntrinsicProperty{IntrinsicMemoryLocation Loc=idx;}
class IntrInaccessibleReadWriteMem<IntrinsicMemoryLocation idx> : IntrinsicProperty{IntrinsicMemoryLocation Loc=idx;}

// IntrInaccessibleMemOrArgMemOnly -- This intrinsic only accesses memory that
// its pointer-typed arguments point to or memory that is not accessible
// by the module being compiled. This is a weaker form of IntrArgMemOnly.
Expand Down
52 changes: 51 additions & 1 deletion llvm/include/llvm/Support/ModRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ enum class ModRefInfo : uint8_t {
/// Debug print ModRefInfo.
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, ModRefInfo MR);

enum class InaccessibleTargetMemLocation {
AARCH64_FPMR = 3,
AARCH64_ZA = 4,
};
Comment on lines +59 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still somewhat think we shouldn't embed target-specific bits in IRMemLocation (or at least, I'm not sure having a enum class is a nice idea, doesn't look extendable to other architectures).

@nikic Would it make sense to extend MemoryEffectsBase with a optional storage to maintain target tags (e.g., a vector of std::pair<TargetMemID, ModRefInfo>)? The parser/reader could then leverage something similar to getOrInsertSyncScopeID from LLVMContext (i.e., getOrInsertTargetMemTag("aarch64.za") to have the TargetMemID, to work on unsigned rather than strings).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the discussion on #148650.


/// The locations at which a function might access memory.
enum class IRMemLocation {
/// Access to memory via argument pointers.
Expand All @@ -65,7 +70,7 @@ enum class IRMemLocation {
/// Errno memory.
ErrnoMem = 2,
/// Any other memory.
Other = 3,
Other = 5,

/// Helpers to iterate all locations in the MemoryEffectsBase class.
First = ArgMem,
Expand Down Expand Up @@ -152,6 +157,46 @@ template <typename LocationEnum> class MemoryEffectsBase {
return MemoryEffectsBase(Location::Other, MR);
}

/// Create MemoryEffectsBase that can only read inaccessible memory.
static MemoryEffectsBase
inaccessibleReadMemOnly(Location Loc = Location::InaccessibleMem) {
return MemoryEffectsBase(Loc, ModRefInfo::Ref);
}

/// Create MemoryEffectsBase that can only write inaccessible memory.
static MemoryEffectsBase
inaccessibleWriteMemOnly(Location Loc = Location::InaccessibleMem) {
return MemoryEffectsBase(Loc, ModRefInfo::Mod);
}

/// Create MemoryEffectsBase that can read write inaccessible memory.
static MemoryEffectsBase
inaccessibleReadWriteMem(Location Loc = Location::InaccessibleMem) {
return MemoryEffectsBase(Loc, ModRefInfo::ModRef);
}

/// Checks if only target-specific memory locations are set.
/// Ignores standard locations like ArgMem or InaccessibleMem.
/// Needed because `Data` may be non-zero by default unless explicitly
/// cleared.
bool onlyAccessTargetMemoryLocation() {
MemoryEffectsBase ME = *this;
for (unsigned I = static_cast<int>(LocationEnum::ErrnoMem);
I < static_cast<int>(LocationEnum::Last); I++)
ME = ME.getWithoutLoc(static_cast<IRMemLocation>(I));
return ME.doesNotAccessMemory();
}

/// Create MemoryEffectsBase that can only access Target Memory Locations
static MemoryEffectsBase
setTargetMemLocationModRef(ModRefInfo MR = ModRefInfo::NoModRef) {
MemoryEffectsBase FRMB = none();
for (unsigned I = static_cast<int>(LocationEnum::ErrnoMem);
I < static_cast<int>(LocationEnum::Last); I++)
FRMB.setModRef(static_cast<Location>(I), MR);
return FRMB;
}

/// Create MemoryEffectsBase that can only access inaccessible or argument
/// memory.
static MemoryEffectsBase
Expand All @@ -178,6 +223,11 @@ template <typename LocationEnum> class MemoryEffectsBase {
return MemoryEffectsBase(Data);
}

bool isTargetMemLoc(IRMemLocation Loc) {
return static_cast<unsigned>(Loc) >
static_cast<unsigned>(Location::ErrnoMem);
}

/// Convert MemoryEffectsBase into an encoded integer value (used by memory
/// attribute).
uint32_t toIntValue() const {
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/TableGen/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ModRef.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/TrailingObjects.h"
Expand Down Expand Up @@ -1961,6 +1962,8 @@ class Record {
/// value is not the right type.
int64_t getValueAsInt(StringRef FieldName) const;

llvm::IRMemLocation getLocationTypeAsInt(StringRef FieldName) const;

/// This method looks up the specified field and returns its value as an Dag,
/// throwing an exception if the field does not exist or if the value is not
/// the right type.
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,8 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(write);
KEYWORD(readwrite);
KEYWORD(argmem);
KEYWORD(aarch64_fpmr);
KEYWORD(aarch64_za);
KEYWORD(inaccessiblemem);
KEYWORD(errnomem);
KEYWORD(argmemonly);
Expand Down
32 changes: 19 additions & 13 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,25 @@ static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) {
}
}

static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
switch (Tok) {
case lltok::kw_argmem:
return IRMemLocation::ArgMem;
case lltok::kw_inaccessiblemem:
return IRMemLocation::InaccessibleMem;
case lltok::kw_errnomem:
return IRMemLocation::ErrnoMem;
case lltok::kw_aarch64_fpmr:
return static_cast<IRMemLocation>(
llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
case lltok::kw_aarch64_za:
return static_cast<IRMemLocation>(
llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
default:
return std::nullopt;
}
}

/// parseFnAttributeValuePairs
/// ::= <attr> | <attr> '=' <value>
bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
Expand Down Expand Up @@ -2510,19 +2529,6 @@ bool LLParser::parseAllocKind(AllocFnKind &Kind) {
return false;
}

static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
switch (Tok) {
case lltok::kw_argmem:
return IRMemLocation::ArgMem;
case lltok::kw_inaccessiblemem:
return IRMemLocation::InaccessibleMem;
case lltok::kw_errnomem:
return IRMemLocation::ErrnoMem;
default:
return std::nullopt;
}
}

static std::optional<ModRefInfo> keywordToModRef(lltok::Kind Tok) {
switch (Tok) {
case lltok::kw_none:
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
if (MR == OtherMR)
continue;

// Dont want to print Target Location if NoModRef
if (ME.isTargetMemLoc(Loc) && (MR == ModRefInfo::NoModRef))
continue;

if (!First)
OS << ", ";
First = false;
Expand All @@ -656,6 +660,15 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
break;
case IRMemLocation::Other:
llvm_unreachable("This is represented as the default access kind");
default: {
InaccessibleTargetMemLocation TargetLoc =
static_cast<InaccessibleTargetMemLocation>(Loc);
if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
OS << "aarch64_fpmr: ";
if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
OS << "aarch64_za: ";
break;
}
}
OS << getModRefStr(MR);
}
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Support/ModRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
case IRMemLocation::Other:
OS << "Other: ";
break;
default: {
InaccessibleTargetMemLocation TargetLoc =
static_cast<InaccessibleTargetMemLocation>(Loc);
if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_FPMR)
OS << "AARCH64_FPMR: ";
if (TargetLoc == InaccessibleTargetMemLocation::AARCH64_ZA)
OS << "AARCH64_ZA: ";
break;
}
}
OS << ME.getModRef(Loc);
});
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/TableGen/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3102,6 +3102,21 @@ Record::getValueAsListOfDefs(StringRef FieldName) const {
return Defs;
}

llvm::IRMemLocation Record::getLocationTypeAsInt(StringRef FieldName) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeating my earlier comment from the previous review:

Can you move the code you added in Record.cpp to CodeGenIntrinsic.cpp and make it a helper function in that file? Make getLocationTypeAsInt as static helper function iin that file.

const Record *LocRec = getValueAsDef(FieldName);
StringRef Name = LocRec->getName();
if (Name == "AArch64_FPMR")
return static_cast<IRMemLocation>(
llvm::InaccessibleTargetMemLocation::AARCH64_FPMR);
else if (Name == "AArch64_ZA")
return static_cast<IRMemLocation>(
llvm::InaccessibleTargetMemLocation::AARCH64_ZA);
else if (Name == "InaccessibleMem")
return llvm::IRMemLocation::InaccessibleMem;
else
PrintFatalError(getLoc(), "unknown IRMemLocation: " + Name);
}

int64_t Record::getValueAsInt(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (!R || !R->getValue())
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/FunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
ME |= MemoryEffects::argMemOnly(MR);
ME |= MemoryEffects(IRMemLocation::ErrnoMem, MR);
ME |= MemoryEffects(IRMemLocation::Other, MR);
// Should also set the other Target Memory Locations as MR.
// To compares with MemoryEffects::unknown() in addMemoryAttrs
ME |= MemoryEffects::setTargetMemLocationModRef(MR);
}

static void addArgLocs(MemoryEffects &ME, const CallBase *Call,
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/Assembler/memory-attribute.ll
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,28 @@ declare void @fn_argmem_read_inaccessiblemem_write()
; CHECK: @fn_argmem_read_inaccessiblemem_write_reordered()
declare void @fn_argmem_read_inaccessiblemem_write_reordered()
memory(inaccessiblemem: write, argmem: read)

; CHECK: Function Attrs: memory(aarch64_za: write)
; CHECK: @fn_inaccessiblemem_write_aarch64_za()
declare void @fn_inaccessiblemem_write_aarch64_za()
memory(aarch64_za: write)

; CHECK: Function Attrs: memory(aarch64_za: read)
; CHECK: @fn_inaccessiblemem_read_aarch64_za()
declare void @fn_inaccessiblemem_read_aarch64_za()
memory(aarch64_za: read)

; CHECK: Function Attrs: memory(aarch64_fpmr: write)
; CHECK: @fn_inaccessiblemem_write_aarch64_fpmr()
declare void @fn_inaccessiblemem_write_aarch64_fpmr()
memory(aarch64_fpmr: write)

; CHECK: Function Attrs: memory(aarch64_fpmr: read)
; CHECK: @fn_inaccessiblemem_read_aarch64_fpmr()
declare void @fn_inaccessiblemem_read_aarch64_fpmr()
memory(aarch64_fpmr: read)

; CHECK: Function Attrs: memory(aarch64_fpmr: read, aarch64_za: write)
; CHECK: @fn_inaccessiblemem_read_aarch64_fpmr_write_aarch64_za()
declare void @fn_inaccessiblemem_read_aarch64_fpmr_write_aarch64_za()
memory(aarch64_fpmr: read, aarch64_za: write)
1 change: 0 additions & 1 deletion llvm/test/Bitcode/attributes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ define void @dead_on_return(ptr dead_on_return %p) {
ret void
}

; CHECK: attributes #0 = { noreturn }
; CHECK: attributes #1 = { nounwind }
; CHECK: attributes #2 = { memory(none) }
; CHECK: attributes #3 = { memory(read) }
Expand Down
Loading