From e32f0e20e5af6fe16869bde63c121b5571133550 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 8 Dec 2015 03:01:16 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254991 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Constants.cpp | 18 +++++++++++++++--- test/CodeGen/X86/float-asmprint.ll | 15 +++++++++++++++ unittests/IR/ConstantsTest.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index b4a07a1b6b4..509783fff8b 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -899,7 +899,9 @@ static Constant *getSequenceIfElementsMatch(Constant *C, else if (CI->getType()->isIntegerTy(64)) return getIntSequenceIfElementsMatch(V); } else if (ConstantFP *CFP = dyn_cast(C)) { - if (CFP->getType()->isFloatTy()) + if (CFP->getType()->isHalfTy()) + return getFPSequenceIfElementsMatch(V); + else if (CFP->getType()->isFloatTy()) return getFPSequenceIfElementsMatch(V); else if (CFP->getType()->isDoubleTy()) return getFPSequenceIfElementsMatch(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(Ty)) { switch (IT->getBitWidth()) { case 8: @@ -2637,6 +2639,11 @@ Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { } if (ConstantFP *CFP = dyn_cast(V)) { + if (CFP->getType()->isHalfTy()) { + SmallVector Elts( + NumElts, CFP->getValueAPF().bitcastToAPInt().getLimitedValue()); + return getFP(V->getContext(), Elts); + } if (CFP->getType()->isFloatTy()) { SmallVector 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(EltPtr); + return APFloat(APFloat::IEEEhalf, APInt(16, EltVal)); + } case Type::FloatTyID: { auto EltVal = *reinterpret_cast(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)); diff --git a/test/CodeGen/X86/float-asmprint.ll b/test/CodeGen/X86/float-asmprint.ll index 5de9700fc06..0108430ee93 100644 --- a/test/CodeGen/X86/float-asmprint.ll +++ b/test/CodeGen/X86/float-asmprint.ll @@ -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> +@var4f16 = global <4 x half> ; 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 diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 7741b448fa8..8c33453d293 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -382,5 +382,33 @@ TEST(ConstantsTest, AliasCAPI) { ASSERT_EQ(unwrap(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 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(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(CDV) != nullptr) + << " T = " << getNameOfType(T); + } +} + } // end anonymous namespace } // end namespace llvm -- 2.34.1