diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2011-10-14 23:23:15 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2011-10-14 23:23:15 +0000 |
commit | f0c267e6e05c2583c23fad3aa1c9ddad5e9d4998 (patch) | |
tree | b1c9c50501a95458c2582cbb0593561537f6335f /clang/lib/CodeGen | |
parent | 1f64b5987263ac40f0f1b104972afde03f5087a5 (diff) | |
download | bcm5719-llvm-f0c267e6e05c2583c23fad3aa1c9ddad5e9d4998.tar.gz bcm5719-llvm-f0c267e6e05c2583c23fad3aa1c9ddad5e9d4998.zip |
Provide half floating point support as a storage only type.
Lack of half FP was a regression compared to llvm-gcc.
llvm-svn: 142016
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 79 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGRTTI.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 10 |
5 files changed, 76 insertions, 24 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 39a9ef788f9..c7a9b407d26 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -391,6 +391,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { case BuiltinType::WChar_S: case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break; case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break; + case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::LongDouble: case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 8711c1fdd5b..3997866ea68 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1026,8 +1026,13 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, NULL); return llvm::ConstantStruct::get(STy, Complex); } - case APValue::Float: - return llvm::ConstantFP::get(VMContext, Result.Val.getFloat()); + case APValue::Float: { + const llvm::APFloat &Init = Result.Val.getFloat(); + if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf) + return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt()); + else + return llvm::ConstantFP::get(VMContext, Init); + } case APValue::ComplexFloat: { llvm::Constant *Complex[2]; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 26a3e948efe..3a9fbeed9d6 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -552,6 +552,16 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, if (DstType->isVoidType()) return 0; + llvm::Type *SrcTy = Src->getType(); + + // Floating casts might be a bit special: if we're doing casts to / from half + // FP, we should go via special intrinsics. + if (SrcType->isHalfType()) { + Src = Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16), Src); + SrcType = CGF.getContext().FloatTy; + SrcTy = llvm::Type::getFloatTy(VMContext); + } + // Handle conversions to bool first, they are special: comparisons against 0. if (DstType->isBooleanType()) return EmitConversionToBool(Src, SrcType); @@ -559,7 +569,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, llvm::Type *DstTy = ConvertType(DstType); // Ignore conversions like int -> uint. - if (Src->getType() == DstTy) + if (SrcTy == DstTy) return Src; // Handle pointer conversions next: pointers can only be converted to/from @@ -567,7 +577,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, // some native types (like Obj-C id) may map to a pointer type. if (isa<llvm::PointerType>(DstTy)) { // The source value may be an integer, or a pointer. - if (isa<llvm::PointerType>(Src->getType())) + if (isa<llvm::PointerType>(SrcTy)) return Builder.CreateBitCast(Src, DstTy, "conv"); assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); @@ -581,7 +591,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, return Builder.CreateIntToPtr(IntResult, DstTy, "conv"); } - if (isa<llvm::PointerType>(Src->getType())) { + if (isa<llvm::PointerType>(SrcTy)) { // Must be an ptr to int cast. assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?"); return Builder.CreatePtrToInt(Src, DstTy, "conv"); @@ -610,34 +620,47 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, } // Allow bitcast from vector to integer/fp of the same size. - if (isa<llvm::VectorType>(Src->getType()) || + if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) return Builder.CreateBitCast(Src, DstTy, "conv"); // Finally, we have the arithmetic types: real int/float. - if (isa<llvm::IntegerType>(Src->getType())) { + Value *Res = NULL; + llvm::Type *ResTy = DstTy; + + // Cast to half via float + if (DstType->isHalfType()) + DstTy = llvm::Type::getFloatTy(VMContext); + + if (isa<llvm::IntegerType>(SrcTy)) { bool InputSigned = SrcType->isSignedIntegerOrEnumerationType(); if (isa<llvm::IntegerType>(DstTy)) - return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); + Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); else if (InputSigned) - return Builder.CreateSIToFP(Src, DstTy, "conv"); + Res = Builder.CreateSIToFP(Src, DstTy, "conv"); else - return Builder.CreateUIToFP(Src, DstTy, "conv"); - } - - assert(Src->getType()->isFloatingPointTy() && "Unknown real conversion"); - if (isa<llvm::IntegerType>(DstTy)) { + Res = Builder.CreateUIToFP(Src, DstTy, "conv"); + } else if (isa<llvm::IntegerType>(DstTy)) { + assert(SrcTy->isFloatingPointTy() && "Unknown real conversion"); if (DstType->isSignedIntegerOrEnumerationType()) - return Builder.CreateFPToSI(Src, DstTy, "conv"); + Res = Builder.CreateFPToSI(Src, DstTy, "conv"); else - return Builder.CreateFPToUI(Src, DstTy, "conv"); + Res = Builder.CreateFPToUI(Src, DstTy, "conv"); + } else { + assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() && + "Unknown real conversion"); + if (DstTy->getTypeID() < SrcTy->getTypeID()) + Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); + else + Res = Builder.CreateFPExt(Src, DstTy, "conv"); } - assert(DstTy->isFloatingPointTy() && "Unknown real conversion"); - if (DstTy->getTypeID() < Src->getType()->getTypeID()) - return Builder.CreateFPTrunc(Src, DstTy, "conv"); - else - return Builder.CreateFPExt(Src, DstTy, "conv"); + if (DstTy != ResTy) { + assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion"); + Res = Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16), Res); + } + + return Res; } /// EmitComplexToScalarConversion - Emit a conversion from the specified complex @@ -1202,7 +1225,6 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_FloatingToIntegral: case CK_FloatingCast: return EmitScalarConversion(Visit(E), E->getType(), DestTy); - case CK_IntegralToBoolean: return EmitIntToBoolConversion(Visit(E)); case CK_PointerToBoolean: @@ -1356,6 +1378,14 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } else if (type->isRealFloatingType()) { // Add the inc/dec to the real part. llvm::Value *amt; + + if (type->isHalfType()) { + // Another special case: half FP increment should be done via float + value = + Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_from_fp16), + input); + } + if (value->getType()->isFloatTy()) amt = llvm::ConstantFP::get(VMContext, llvm::APFloat(static_cast<float>(amount))); @@ -1371,6 +1401,11 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec"); + if (type->isHalfType()) + value = + Builder.CreateCall(CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16), + value); + // Objective-C pointer types. } else { const ObjCObjectPointerType *OPT = type->castAs<ObjCObjectPointerType>(); @@ -1387,13 +1422,13 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); value = Builder.CreateBitCast(value, input->getType()); } - + // Store the updated result through the lvalue. if (LV.isBitField()) CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value); else CGF.EmitStoreThroughLValue(RValue::get(value), LV); - + // If this is a postinc, return the value read from memory, otherwise use the // updated value. return isPre ? value : input; diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp index dbf99fa5d76..fbdb2984830 100644 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ b/clang/lib/CodeGen/CGRTTI.cpp @@ -185,6 +185,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::ULong: case BuiltinType::LongLong: case BuiltinType::ULongLong: + case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 03a15ae67ea..e0d92189658 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -263,6 +263,8 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext, const llvm::fltSemantics &format) { + if (&format == &llvm::APFloat::IEEEhalf) + return llvm::Type::getInt16Ty(VMContext); if (&format == &llvm::APFloat::IEEEsingle) return llvm::Type::getFloatTy(VMContext); if (&format == &llvm::APFloat::IEEEdouble) @@ -341,6 +343,14 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { static_cast<unsigned>(Context.getTypeSize(T))); break; + case BuiltinType::Half: + // Half is special: it might be lowered to i16 (and will be storage-only + // type),. or can be represented as a set of native operations. + + // FIXME: Ask target which kind of half FP it prefers (storage only vs + // native). + ResultType = llvm::Type::getInt16Ty(getLLVMContext()); + break; case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: |