forked from OSchip/llvm-project
IR: Allow vectors of halfs to be ConstantDataVectors
Currently, vectors of halfs end up as ConstantVectors, but there isn't a good reason they can't be ConstantDataVectors. This should save some memory. llvm-svn: 254991
This commit is contained in:
parent
b13edeb9b5
commit
0ebc8605ad
|
@ -899,7 +899,9 @@ static Constant *getSequenceIfElementsMatch(Constant *C,
|
|||
else if (CI->getType()->isIntegerTy(64))
|
||||
return getIntSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
|
||||
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
if (CFP->getType()->isFloatTy())
|
||||
if (CFP->getType()->isHalfTy())
|
||||
return getFPSequenceIfElementsMatch<SequenceTy, uint16_t>(V);
|
||||
else if (CFP->getType()->isFloatTy())
|
||||
return getFPSequenceIfElementsMatch<SequenceTy, uint32_t>(V);
|
||||
else if (CFP->getType()->isDoubleTy())
|
||||
return getFPSequenceIfElementsMatch<SequenceTy, uint64_t>(V);
|
||||
|
@ -2365,7 +2367,7 @@ StringRef ConstantDataSequential::getRawDataValues() const {
|
|||
/// ConstantDataArray only works with normal float and int types that are
|
||||
/// stored densely in memory, not with things like i42 or x86_f80.
|
||||
bool ConstantDataSequential::isElementTypeCompatible(Type *Ty) {
|
||||
if (Ty->isFloatTy() || Ty->isDoubleTy()) return true;
|
||||
if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) return true;
|
||||
if (auto *IT = dyn_cast<IntegerType>(Ty)) {
|
||||
switch (IT->getBitWidth()) {
|
||||
case 8:
|
||||
|
@ -2637,6 +2639,11 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) {
|
|||
}
|
||||
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
|
||||
if (CFP->getType()->isHalfTy()) {
|
||||
SmallVector<uint16_t, 16> Elts(
|
||||
NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
|
||||
return getFP(V->getContext(), Elts);
|
||||
}
|
||||
if (CFP->getType()->isFloatTy()) {
|
||||
SmallVector<uint32_t, 16> Elts(
|
||||
NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue());
|
||||
|
@ -2682,6 +2689,10 @@ APFloat ConstantDataSequential::getElementAsAPFloat(unsigned Elt) const {
|
|||
switch (getElementType()->getTypeID()) {
|
||||
default:
|
||||
llvm_unreachable("Accessor can only be used when element is float/double!");
|
||||
case Type::HalfTyID: {
|
||||
auto EltVal = *reinterpret_cast<const uint16_t *>(EltPtr);
|
||||
return APFloat(APFloat::IEEEhalf, APInt(16, EltVal));
|
||||
}
|
||||
case Type::FloatTyID: {
|
||||
auto EltVal = *reinterpret_cast<const uint32_t *>(EltPtr);
|
||||
return APFloat(APFloat::IEEEsingle, APInt(32, EltVal));
|
||||
|
@ -2716,7 +2727,8 @@ double ConstantDataSequential::getElementAsDouble(unsigned Elt) const {
|
|||
/// Note that this has to compute a new constant to return, so it isn't as
|
||||
/// efficient as getElementAsInteger/Float/Double.
|
||||
Constant *ConstantDataSequential::getElementAsConstant(unsigned Elt) const {
|
||||
if (getElementType()->isFloatTy() || getElementType()->isDoubleTy())
|
||||
if (getElementType()->isHalfTy() || getElementType()->isFloatTy() ||
|
||||
getElementType()->isDoubleTy())
|
||||
return ConstantFP::get(getContext(), getElementAsAPFloat(Elt));
|
||||
|
||||
return ConstantInt::get(getElementType(), getElementAsInteger(Elt));
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
@var64 = global double -0.0, align 8
|
||||
@var32 = global float -0.0, align 4
|
||||
@var16 = global half -0.0, align 2
|
||||
@var4f32 = global <4 x float> <float -0.0, float 0.0, float 1.0, float 2.0>
|
||||
@var4f16 = global <4 x half> <half -0.0, half 0.0, half 1.0, half 2.0>
|
||||
|
||||
; CHECK: var128:
|
||||
; CHECK-NEXT: .quad 0 # fp128 -0
|
||||
|
@ -39,3 +41,16 @@
|
|||
; CHECK-NEXT: .short 32768 # half -0
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var4f32:
|
||||
; CHECK-NEXT: .long 2147483648 # float -0
|
||||
; CHECK-NEXT: .long 0 # float 0
|
||||
; CHECK-NEXT: .long 1065353216 # float 1
|
||||
; CHECK-NEXT: .long 1073741824 # float 2
|
||||
; CHECK-NEXT: .size
|
||||
|
||||
; CHECK: var4f16:
|
||||
; CHECK-NEXT: .short 32768 # half -0
|
||||
; CHECK-NEXT: .short 0 # half 0
|
||||
; CHECK-NEXT: .short 15360 # half 1
|
||||
; CHECK-NEXT: .short 16384 # half 2
|
||||
; CHECK-NEXT: .size
|
||||
|
|
|
@ -382,5 +382,33 @@ TEST(ConstantsTest, AliasCAPI) {
|
|||
ASSERT_EQ(unwrap<GlobalAlias>(AliasRef)->getAliasee(), Aliasee);
|
||||
}
|
||||
|
||||
static std::string getNameOfType(Type *T) {
|
||||
std::string S;
|
||||
raw_string_ostream RSOS(S);
|
||||
T->print(RSOS);
|
||||
return S;
|
||||
}
|
||||
|
||||
TEST(ConstantsTest, BuildConstantDataVectors) {
|
||||
LLVMContext Context;
|
||||
std::unique_ptr<Module> M(new Module("MyModule", Context));
|
||||
|
||||
for (Type *T : {Type::getInt8Ty(Context), Type::getInt16Ty(Context),
|
||||
Type::getInt32Ty(Context), Type::getInt64Ty(Context)}) {
|
||||
Constant *Vals[] = {ConstantInt::get(T, 0), ConstantInt::get(T, 1)};
|
||||
Constant *CDV = ConstantVector::get(Vals);
|
||||
ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
|
||||
<< " T = " << getNameOfType(T);
|
||||
}
|
||||
|
||||
for (Type *T : {Type::getHalfTy(Context), Type::getFloatTy(Context),
|
||||
Type::getDoubleTy(Context)}) {
|
||||
Constant *Vals[] = {ConstantFP::get(T, 0), ConstantFP::get(T, 1)};
|
||||
Constant *CDV = ConstantVector::get(Vals);
|
||||
ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
|
||||
<< " T = " << getNameOfType(T);
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
} // end namespace llvm
|
||||
|
|
Loading…
Reference in New Issue