Skip to content

Commit

Permalink
[DataLayout] Refactor storage of non-integral address spaces
Browse files Browse the repository at this point in the history
Instead of storing this as a separate array of non-integral pointers,
add it to the PointerSpec class instead. This will allow for future
simplifications such as splitting the non-integral property into
multiple distinct ones: relocatable (i.e. non-stable representation) and
non-integral representation (i.e. pointers with metadata).

Reviewed By: arsenm

Pull Request: llvm#105734
  • Loading branch information
arichardson authored Oct 25, 2024
1 parent 9ea6fcd commit 305a1ce
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 20 deletions.
28 changes: 17 additions & 11 deletions llvm/include/llvm/IR/DataLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ class DataLayout {
Align ABIAlign;
Align PrefAlign;
uint32_t IndexBitWidth;

/// Pointers in this address space don't have a well-defined bitwise
/// representation (e.g. may be relocated by a copying garbage collector).
/// Additionally, they may also be non-integral (i.e. containing additional
/// metadata such as bounds information/permissions).
bool IsNonIntegral;
bool operator==(const PointerSpec &Other) const;
};

Expand Down Expand Up @@ -133,10 +137,6 @@ class DataLayout {
// The StructType -> StructLayout map.
mutable void *LayoutMap = nullptr;

/// Pointers in these address spaces are non-integral, and don't have a
/// well-defined bitwise representation.
SmallVector<unsigned, 8> NonIntegralAddressSpaces;

/// Sets or updates the specification for the given primitive type.
void setPrimitiveSpec(char Specifier, uint32_t BitWidth, Align ABIAlign,
Align PrefAlign);
Expand All @@ -147,7 +147,8 @@ class DataLayout {

/// Sets or updates the specification for pointer in the given address space.
void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
Align PrefAlign, uint32_t IndexBitWidth);
Align PrefAlign, uint32_t IndexBitWidth,
bool IsNonIntegral);

/// Internal helper to get alignment for integer of given bitwidth.
Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
Expand All @@ -165,7 +166,8 @@ class DataLayout {
Error parsePointerSpec(StringRef Spec);

/// Attempts to parse a single specification.
Error parseSpecification(StringRef Spec);
Error parseSpecification(StringRef Spec,
SmallVectorImpl<unsigned> &NonIntegralAddressSpaces);

/// Attempts to parse a data layout string.
Error parseLayoutString(StringRef LayoutString);
Expand Down Expand Up @@ -337,13 +339,17 @@ class DataLayout {

/// Return the address spaces containing non-integral pointers. Pointers in
/// this address space don't have a well-defined bitwise representation.
ArrayRef<unsigned> getNonIntegralAddressSpaces() const {
return NonIntegralAddressSpaces;
SmallVector<unsigned, 8> getNonIntegralAddressSpaces() const {
SmallVector<unsigned, 8> AddrSpaces;
for (const PointerSpec &PS : PointerSpecs) {
if (PS.IsNonIntegral)
AddrSpaces.push_back(PS.AddrSpace);
}
return AddrSpaces;
}

bool isNonIntegralAddressSpace(unsigned AddrSpace) const {
ArrayRef<unsigned> NonIntegralSpaces = getNonIntegralAddressSpaces();
return is_contained(NonIntegralSpaces, AddrSpace);
return getPointerSpec(AddrSpace).IsNonIntegral;
}

bool isNonIntegralPointerType(PointerType *PT) const {
Expand Down
32 changes: 23 additions & 9 deletions llvm/lib/IR/DataLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ bool DataLayout::PrimitiveSpec::operator==(const PrimitiveSpec &Other) const {
bool DataLayout::PointerSpec::operator==(const PointerSpec &Other) const {
return AddrSpace == Other.AddrSpace && BitWidth == Other.BitWidth &&
ABIAlign == Other.ABIAlign && PrefAlign == Other.PrefAlign &&
IndexBitWidth == Other.IndexBitWidth;
IndexBitWidth == Other.IndexBitWidth &&
IsNonIntegral == Other.IsNonIntegral;
}

namespace {
Expand Down Expand Up @@ -206,7 +207,8 @@ constexpr DataLayout::PrimitiveSpec DefaultVectorSpecs[] = {

// Default pointer type specifications.
constexpr DataLayout::PointerSpec DefaultPointerSpecs[] = {
{0, 64, Align::Constant<8>(), Align::Constant<8>(), 64} // p0:64:64:64:64
// p0:64:64:64:64
{0, 64, Align::Constant<8>(), Align::Constant<8>(), 64, false},
};

DataLayout::DataLayout()
Expand Down Expand Up @@ -239,13 +241,11 @@ DataLayout &DataLayout::operator=(const DataLayout &Other) {
PointerSpecs = Other.PointerSpecs;
StructABIAlignment = Other.StructABIAlignment;
StructPrefAlignment = Other.StructPrefAlignment;
NonIntegralAddressSpaces = Other.NonIntegralAddressSpaces;
return *this;
}

bool DataLayout::operator==(const DataLayout &Other) const {
// NOTE: StringRepresentation might differ, it is not canonicalized.
// FIXME: NonIntegralAddressSpaces isn't compared.
return BigEndian == Other.BigEndian &&
AllocaAddrSpace == Other.AllocaAddrSpace &&
ProgramAddrSpace == Other.ProgramAddrSpace &&
Expand Down Expand Up @@ -454,11 +454,13 @@ Error DataLayout::parsePointerSpec(StringRef Spec) {
return createStringError(
"index size cannot be larger than the pointer size");

setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth);
setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth,
false);
return Error::success();
}

Error DataLayout::parseSpecification(StringRef Spec) {
Error DataLayout::parseSpecification(
StringRef Spec, SmallVectorImpl<unsigned> &NonIntegralAddressSpaces) {
// The "ni" specifier is the only two-character specifier. Handle it first.
if (Spec.starts_with("ni")) {
// ni:<address space>[:<address space>]...
Expand Down Expand Up @@ -614,12 +616,23 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) {

// Split the data layout string into specifications separated by '-' and
// parse each specification individually, updating internal data structures.
SmallVector<unsigned, 8> NonIntegralAddressSpaces;
for (StringRef Spec : split(LayoutString, '-')) {
if (Spec.empty())
return createStringError("empty specification is not allowed");
if (Error Err = parseSpecification(Spec))
if (Error Err = parseSpecification(Spec, NonIntegralAddressSpaces))
return Err;
}
// Mark all address spaces that were qualified as non-integral now. This has
// to be done later since the non-integral property is not part of the data
// layout pointer specification.
for (unsigned AS : NonIntegralAddressSpaces) {
// If there is no special spec for a given AS, getPointerSpec(AS) returns
// the spec for AS0, and we then update that to mark it non-integral.
const PointerSpec &PS = getPointerSpec(AS);
setPointerSpec(AS, PS.BitWidth, PS.ABIAlign, PS.PrefAlign, PS.IndexBitWidth,
true);
}

return Error::success();
}
Expand Down Expand Up @@ -666,16 +679,17 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const {

void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
Align ABIAlign, Align PrefAlign,
uint32_t IndexBitWidth) {
uint32_t IndexBitWidth, bool IsNonIntegral) {
auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace());
if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) {
PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign,
IndexBitWidth});
IndexBitWidth, IsNonIntegral});
} else {
I->BitWidth = BitWidth;
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
I->IndexBitWidth = IndexBitWidth;
I->IsNonIntegral = IsNonIntegral;
}
}

Expand Down

0 comments on commit 305a1ce

Please sign in to comment.