mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Add support for zero-sized Scalars as a LowLevelType
Opaque values (of zero size) can be stored in memory with the implemention of reference types in the WebAssembly backend. Since MachineMemOperand uses LLTs we need to be able to support zero-sized scalars types in LLTs. Differential Revision: https://reviews.llvm.org/D105423
This commit is contained in:
parent
152a339cb1
commit
ceddd7eb41
@ -41,8 +41,7 @@ class LLT {
|
|||||||
public:
|
public:
|
||||||
/// Get a low-level scalar or aggregate "bag of bits".
|
/// Get a low-level scalar or aggregate "bag of bits".
|
||||||
static LLT scalar(unsigned SizeInBits) {
|
static LLT scalar(unsigned SizeInBits) {
|
||||||
assert(SizeInBits > 0 && "invalid scalar size");
|
return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
|
||||||
return LLT{/*isPointer=*/false, /*isVector=*/false,
|
|
||||||
ElementCount::getFixed(0), SizeInBits,
|
ElementCount::getFixed(0), SizeInBits,
|
||||||
/*AddressSpace=*/0};
|
/*AddressSpace=*/0};
|
||||||
}
|
}
|
||||||
@ -50,23 +49,23 @@ public:
|
|||||||
/// Get a low-level pointer in the given address space.
|
/// Get a low-level pointer in the given address space.
|
||||||
static LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
|
static LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
|
||||||
assert(SizeInBits > 0 && "invalid pointer size");
|
assert(SizeInBits > 0 && "invalid pointer size");
|
||||||
return LLT{/*isPointer=*/true, /*isVector=*/false,
|
return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
|
||||||
ElementCount::getFixed(0), SizeInBits, AddressSpace};
|
ElementCount::getFixed(0), SizeInBits, AddressSpace};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a low-level vector of some number of elements and element width.
|
/// Get a low-level vector of some number of elements and element width.
|
||||||
static LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
|
static LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
|
||||||
assert(!EC.isScalar() && "invalid number of vector elements");
|
assert(!EC.isScalar() && "invalid number of vector elements");
|
||||||
assert(ScalarSizeInBits > 0 && "invalid vector element size");
|
return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
|
||||||
return LLT{/*isPointer=*/false, /*isVector=*/true, EC, ScalarSizeInBits,
|
EC, ScalarSizeInBits, /*AddressSpace=*/0};
|
||||||
/*AddressSpace=*/0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a low-level vector of some number of elements and element type.
|
/// Get a low-level vector of some number of elements and element type.
|
||||||
static LLT vector(ElementCount EC, LLT ScalarTy) {
|
static LLT vector(ElementCount EC, LLT ScalarTy) {
|
||||||
assert(!EC.isScalar() && "invalid number of vector elements");
|
assert(!EC.isScalar() && "invalid number of vector elements");
|
||||||
assert(!ScalarTy.isVector() && "invalid vector element type");
|
assert(!ScalarTy.isVector() && "invalid vector element type");
|
||||||
return LLT{ScalarTy.isPointer(), /*isVector=*/true, EC,
|
return LLT{ScalarTy.isPointer(), /*isVector=*/true, /*isScalar=*/false,
|
||||||
|
EC,
|
||||||
ScalarTy.getSizeInBits().getFixedSize(),
|
ScalarTy.getSizeInBits().getFixedSize(),
|
||||||
ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
|
ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
|
||||||
}
|
}
|
||||||
@ -106,17 +105,18 @@ public:
|
|||||||
return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
|
return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit LLT(bool isPointer, bool isVector, ElementCount EC,
|
explicit LLT(bool isPointer, bool isVector, bool isScalar, ElementCount EC,
|
||||||
uint64_t SizeInBits, unsigned AddressSpace) {
|
uint64_t SizeInBits, unsigned AddressSpace) {
|
||||||
init(isPointer, isVector, EC, SizeInBits, AddressSpace);
|
init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
|
||||||
}
|
}
|
||||||
explicit LLT() : IsPointer(false), IsVector(false), RawData(0) {}
|
explicit LLT()
|
||||||
|
: IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
|
||||||
|
|
||||||
explicit LLT(MVT VT);
|
explicit LLT(MVT VT);
|
||||||
|
|
||||||
bool isValid() const { return RawData != 0; }
|
bool isValid() const { return IsScalar || RawData != 0; }
|
||||||
|
|
||||||
bool isScalar() const { return isValid() && !IsPointer && !IsVector; }
|
bool isScalar() const { return IsScalar; }
|
||||||
|
|
||||||
bool isPointer() const { return isValid() && IsPointer && !IsVector; }
|
bool isPointer() const { return isValid() && IsPointer && !IsVector; }
|
||||||
|
|
||||||
@ -196,6 +196,8 @@ public:
|
|||||||
/// not attempt to handle cases that aren't evenly divisible.
|
/// not attempt to handle cases that aren't evenly divisible.
|
||||||
LLT divide(int Factor) const {
|
LLT divide(int Factor) const {
|
||||||
assert(Factor != 1);
|
assert(Factor != 1);
|
||||||
|
assert((!isScalar() || getScalarSizeInBits() != 0) &&
|
||||||
|
"cannot divide scalar of size zero");
|
||||||
if (isVector()) {
|
if (isVector()) {
|
||||||
assert(getElementCount().isKnownMultipleOf(Factor));
|
assert(getElementCount().isKnownMultipleOf(Factor));
|
||||||
return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
|
return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
|
||||||
@ -209,18 +211,17 @@ public:
|
|||||||
bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); }
|
bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); }
|
||||||
|
|
||||||
unsigned getScalarSizeInBits() const {
|
unsigned getScalarSizeInBits() const {
|
||||||
assert(RawData != 0 && "Invalid Type");
|
if (IsScalar)
|
||||||
if (!IsVector) {
|
|
||||||
if (!IsPointer)
|
|
||||||
return getFieldValue(ScalarSizeFieldInfo);
|
return getFieldValue(ScalarSizeFieldInfo);
|
||||||
else
|
if (IsVector) {
|
||||||
return getFieldValue(PointerSizeFieldInfo);
|
|
||||||
} else {
|
|
||||||
if (!IsPointer)
|
if (!IsPointer)
|
||||||
return getFieldValue(VectorSizeFieldInfo);
|
return getFieldValue(VectorSizeFieldInfo);
|
||||||
else
|
else
|
||||||
return getFieldValue(PointerVectorSizeFieldInfo);
|
return getFieldValue(PointerVectorSizeFieldInfo);
|
||||||
}
|
} else if (IsPointer)
|
||||||
|
return getFieldValue(PointerSizeFieldInfo);
|
||||||
|
else
|
||||||
|
llvm_unreachable("unexpected LLT");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getAddressSpace() const {
|
unsigned getAddressSpace() const {
|
||||||
@ -252,7 +253,7 @@ public:
|
|||||||
|
|
||||||
bool operator==(const LLT &RHS) const {
|
bool operator==(const LLT &RHS) const {
|
||||||
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
|
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
|
||||||
RHS.RawData == RawData;
|
IsScalar == RHS.IsScalar && RHS.RawData == RawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
|
bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
|
||||||
@ -262,9 +263,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/// LLT is packed into 64 bits as follows:
|
/// LLT is packed into 64 bits as follows:
|
||||||
|
/// isScalar : 1
|
||||||
/// isPointer : 1
|
/// isPointer : 1
|
||||||
/// isVector : 1
|
/// isVector : 1
|
||||||
/// with 62 bits remaining for Kind-specific data, packed in bitfields
|
/// with 61 bits remaining for Kind-specific data, packed in bitfields
|
||||||
/// as described below. As there isn't a simple portable way to pack bits
|
/// as described below. As there isn't a simple portable way to pack bits
|
||||||
/// into bitfields, here the different fields in the packed structure is
|
/// into bitfields, here the different fields in the packed structure is
|
||||||
/// described in static const *Field variables. Each of these variables
|
/// described in static const *Field variables. Each of these variables
|
||||||
@ -286,7 +288,7 @@ private:
|
|||||||
static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
|
static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
|
||||||
24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
|
24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
|
||||||
static_assert((PointerAddressSpaceFieldInfo[0] +
|
static_assert((PointerAddressSpaceFieldInfo[0] +
|
||||||
PointerAddressSpaceFieldInfo[1]) <= 62,
|
PointerAddressSpaceFieldInfo[1]) <= 61,
|
||||||
"Insufficient bits to encode all data");
|
"Insufficient bits to encode all data");
|
||||||
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
|
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
|
||||||
/// NumElements: 16;
|
/// NumElements: 16;
|
||||||
@ -297,7 +299,7 @@ private:
|
|||||||
32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
|
32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
|
||||||
static const constexpr BitFieldInfo VectorScalableFieldInfo{
|
static const constexpr BitFieldInfo VectorScalableFieldInfo{
|
||||||
1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]};
|
1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]};
|
||||||
static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 62,
|
static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 61,
|
||||||
"Insufficient bits to encode all data");
|
"Insufficient bits to encode all data");
|
||||||
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
|
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
|
||||||
/// NumElements: 16;
|
/// NumElements: 16;
|
||||||
@ -314,12 +316,13 @@ private:
|
|||||||
1, PointerVectorAddressSpaceFieldInfo[0] +
|
1, PointerVectorAddressSpaceFieldInfo[0] +
|
||||||
PointerVectorAddressSpaceFieldInfo[1]};
|
PointerVectorAddressSpaceFieldInfo[1]};
|
||||||
static_assert((PointerVectorAddressSpaceFieldInfo[0] +
|
static_assert((PointerVectorAddressSpaceFieldInfo[0] +
|
||||||
PointerVectorAddressSpaceFieldInfo[1]) <= 62,
|
PointerVectorAddressSpaceFieldInfo[1]) <= 61,
|
||||||
"Insufficient bits to encode all data");
|
"Insufficient bits to encode all data");
|
||||||
|
|
||||||
|
uint64_t IsScalar : 1;
|
||||||
uint64_t IsPointer : 1;
|
uint64_t IsPointer : 1;
|
||||||
uint64_t IsVector : 1;
|
uint64_t IsVector : 1;
|
||||||
uint64_t RawData : 62;
|
uint64_t RawData : 61;
|
||||||
|
|
||||||
static uint64_t getMask(const BitFieldInfo FieldInfo) {
|
static uint64_t getMask(const BitFieldInfo FieldInfo) {
|
||||||
const int FieldSizeInBits = FieldInfo[0];
|
const int FieldSizeInBits = FieldInfo[0];
|
||||||
@ -336,19 +339,16 @@ private:
|
|||||||
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
|
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(bool IsPointer, bool IsVector, ElementCount EC, uint64_t SizeInBits,
|
void init(bool IsPointer, bool IsVector, bool IsScalar, ElementCount EC,
|
||||||
unsigned AddressSpace) {
|
uint64_t SizeInBits, unsigned AddressSpace) {
|
||||||
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
|
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
|
||||||
"Not enough bits in LLT to represent size");
|
"Not enough bits in LLT to represent size");
|
||||||
this->IsPointer = IsPointer;
|
this->IsPointer = IsPointer;
|
||||||
this->IsVector = IsVector;
|
this->IsVector = IsVector;
|
||||||
if (!IsVector) {
|
this->IsScalar = IsScalar;
|
||||||
if (!IsPointer)
|
if (IsScalar)
|
||||||
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
|
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
|
||||||
else
|
else if (IsVector) {
|
||||||
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
|
|
||||||
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
|
|
||||||
} else {
|
|
||||||
assert(EC.isVector() && "invalid number of vector elements");
|
assert(EC.isVector() && "invalid number of vector elements");
|
||||||
if (!IsPointer)
|
if (!IsPointer)
|
||||||
RawData =
|
RawData =
|
||||||
@ -363,13 +363,17 @@ private:
|
|||||||
maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) |
|
maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) |
|
||||||
maskAndShift(EC.isScalable() ? 1 : 0,
|
maskAndShift(EC.isScalable() ? 1 : 0,
|
||||||
PointerVectorScalableFieldInfo);
|
PointerVectorScalableFieldInfo);
|
||||||
}
|
} else if (IsPointer)
|
||||||
|
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
|
||||||
|
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
|
||||||
|
else
|
||||||
|
llvm_unreachable("unexpected LLT configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t getUniqueRAWLLTData() const {
|
uint64_t getUniqueRAWLLTData() const {
|
||||||
return ((uint64_t)RawData) << 2 | ((uint64_t)IsPointer) << 1 |
|
return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
|
||||||
((uint64_t)IsVector);
|
((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,16 +17,17 @@ using namespace llvm;
|
|||||||
|
|
||||||
LLT::LLT(MVT VT) {
|
LLT::LLT(MVT VT) {
|
||||||
if (VT.isVector()) {
|
if (VT.isVector()) {
|
||||||
init(/*IsPointer=*/false, VT.getVectorNumElements() > 1,
|
bool asVector = VT.getVectorNumElements() > 1;
|
||||||
|
init(/*IsPointer=*/false, asVector, /*IsScalar=*/!asVector,
|
||||||
VT.getVectorElementCount(), VT.getVectorElementType().getSizeInBits(),
|
VT.getVectorElementCount(), VT.getVectorElementType().getSizeInBits(),
|
||||||
/*AddressSpace=*/0);
|
/*AddressSpace=*/0);
|
||||||
} else if (VT.isValid()) {
|
} else if (VT.isValid()) {
|
||||||
// Aggregates are no different from real scalars as far as GlobalISel is
|
// Aggregates are no different from real scalars as far as GlobalISel is
|
||||||
// concerned.
|
// concerned.
|
||||||
assert(VT.getSizeInBits().isNonZero() && "invalid zero-sized type");
|
init(/*IsPointer=*/false, /*IsVector=*/false, /*IsScalar=*/true,
|
||||||
init(/*IsPointer=*/false, /*IsVector=*/false, ElementCount::getFixed(0),
|
ElementCount::getFixed(0), VT.getSizeInBits(), /*AddressSpace=*/0);
|
||||||
VT.getSizeInBits(), /*AddressSpace=*/0);
|
|
||||||
} else {
|
} else {
|
||||||
|
IsScalar = false;
|
||||||
IsPointer = false;
|
IsPointer = false;
|
||||||
IsVector = false;
|
IsVector = false;
|
||||||
RawData = 0;
|
RawData = 0;
|
||||||
|
@ -22,7 +22,7 @@ TEST(LowLevelTypeTest, Scalar) {
|
|||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
DataLayout DL("");
|
DataLayout DL("");
|
||||||
|
|
||||||
for (unsigned S : {1U, 17U, 32U, 64U, 0xfffffU}) {
|
for (unsigned S : {0U, 1U, 17U, 32U, 64U, 0xfffffU}) {
|
||||||
const LLT Ty = LLT::scalar(S);
|
const LLT Ty = LLT::scalar(S);
|
||||||
|
|
||||||
// Test kind.
|
// Test kind.
|
||||||
@ -41,16 +41,18 @@ TEST(LowLevelTypeTest, Scalar) {
|
|||||||
EXPECT_FALSE(Ty != Ty);
|
EXPECT_FALSE(Ty != Ty);
|
||||||
|
|
||||||
// Test Type->LLT conversion.
|
// Test Type->LLT conversion.
|
||||||
|
if (S != 0) {
|
||||||
Type *IRTy = IntegerType::get(C, S);
|
Type *IRTy = IntegerType::get(C, S);
|
||||||
EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));
|
EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LowLevelTypeTest, Vector) {
|
TEST(LowLevelTypeTest, Vector) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
DataLayout DL("");
|
DataLayout DL("");
|
||||||
|
|
||||||
for (unsigned S : {1U, 17U, 32U, 64U, 0xfffU}) {
|
for (unsigned S : {0U, 1U, 17U, 32U, 64U, 0xfffU}) {
|
||||||
for (auto EC :
|
for (auto EC :
|
||||||
{ElementCount::getFixed(2), ElementCount::getFixed(3),
|
{ElementCount::getFixed(2), ElementCount::getFixed(3),
|
||||||
ElementCount::getFixed(4), ElementCount::getFixed(32),
|
ElementCount::getFixed(4), ElementCount::getFixed(32),
|
||||||
@ -94,11 +96,13 @@ TEST(LowLevelTypeTest, Vector) {
|
|||||||
EXPECT_NE(VTy, STy);
|
EXPECT_NE(VTy, STy);
|
||||||
|
|
||||||
// Test Type->LLT conversion.
|
// Test Type->LLT conversion.
|
||||||
|
if (S != 0) {
|
||||||
Type *IRSTy = IntegerType::get(C, S);
|
Type *IRSTy = IntegerType::get(C, S);
|
||||||
Type *IRTy = VectorType::get(IRSTy, EC);
|
Type *IRTy = VectorType::get(IRSTy, EC);
|
||||||
EXPECT_EQ(VTy, getLLTForType(*IRTy, DL));
|
EXPECT_EQ(VTy, getLLTForType(*IRTy, DL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LowLevelTypeTest, ScalarOrVector) {
|
TEST(LowLevelTypeTest, ScalarOrVector) {
|
||||||
|
Loading…
Reference in New Issue
Block a user