summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2013-09-18 03:29:45 +0000
committerHal Finkel <hfinkel@anl.gov>2013-09-18 03:29:45 +0000
commitc4d7c82c7f7356ac9aca70d67593479897ad7f2b (patch)
tree6805191117ef09e757b99f96db3d0764c7f296fb /clang/lib/CodeGen
parent4c2316be490f798ed44e439d91a6604f57d3b9db (diff)
downloadbcm5719-llvm-c4d7c82c7f7356ac9aca70d67593479897ad7f2b.tar.gz
bcm5719-llvm-c4d7c82c7f7356ac9aca70d67593479897ad7f2b.zip
Add the intrinsic __builtin_convertvector
LLVM supports applying conversion instructions to vectors of the same number of elements (fptrunc, fptosi, etc.) but there had been no way for a Clang user to cause such instructions to be generated when using builtin vector types. C-style casting on vectors is already defined in terms of bitcasts, and so cannot be used for these conversions as well (without leading to a very confusing set of semantics). As a result, this adds a __builtin_convertvector intrinsic (patterned after the OpenCL __builtin_astype intrinsic). This is intended to aid the creation of vector intrinsic headers that create generic IR instead of target-dependent intrinsics (in other words, this is a generic _mm_cvtepi32_ps). As noted in the documentation, the action of __builtin_convertvector is defined in terms of the action of a C-style cast on each vector element. llvm-svn: 190915
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 287dc6c0231..57f102f2932 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -257,6 +257,7 @@ public:
Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E);
+ Value *VisitConvertVectorExpr(ConvertVectorExpr *E);
Value *VisitMemberExpr(MemberExpr *E);
Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
@@ -966,6 +967,81 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
Value *SV = llvm::ConstantVector::get(indices);
return Builder.CreateShuffleVector(V1, V2, SV, "shuffle");
}
+
+Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
+ QualType SrcType = E->getSrcExpr()->getType(),
+ DstType = E->getType();
+
+ Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
+
+ SrcType = CGF.getContext().getCanonicalType(SrcType);
+ DstType = CGF.getContext().getCanonicalType(DstType);
+ if (SrcType == DstType) return Src;
+
+ assert(SrcType->isVectorType() &&
+ "ConvertVector source type must be a vector");
+ assert(DstType->isVectorType() &&
+ "ConvertVector destination type must be a vector");
+
+ llvm::Type *SrcTy = Src->getType();
+ llvm::Type *DstTy = ConvertType(DstType);
+
+ // Ignore conversions like int -> uint.
+ if (SrcTy == DstTy)
+ return Src;
+
+ QualType SrcEltType = SrcType->getAs<VectorType>()->getElementType(),
+ DstEltType = DstType->getAs<VectorType>()->getElementType();
+
+ assert(SrcTy->isVectorTy() &&
+ "ConvertVector source IR type must be a vector");
+ assert(DstTy->isVectorTy() &&
+ "ConvertVector destination IR type must be a vector");
+
+ llvm::Type *SrcEltTy = SrcTy->getVectorElementType(),
+ *DstEltTy = DstTy->getVectorElementType();
+
+ if (DstEltType->isBooleanType()) {
+ assert((SrcEltTy->isFloatingPointTy() ||
+ isa<llvm::IntegerType>(SrcEltTy)) && "Unknown boolean conversion");
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(SrcTy);
+ if (SrcEltTy->isFloatingPointTy()) {
+ return Builder.CreateFCmpUNE(Src, Zero, "tobool");
+ } else {
+ return Builder.CreateICmpNE(Src, Zero, "tobool");
+ }
+ }
+
+ // We have the arithmetic types: real int/float.
+ Value *Res = NULL;
+
+ if (isa<llvm::IntegerType>(SrcEltTy)) {
+ bool InputSigned = SrcEltType->isSignedIntegerOrEnumerationType();
+ if (isa<llvm::IntegerType>(DstEltTy))
+ Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
+ else if (InputSigned)
+ Res = Builder.CreateSIToFP(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateUIToFP(Src, DstTy, "conv");
+ } else if (isa<llvm::IntegerType>(DstEltTy)) {
+ assert(SrcEltTy->isFloatingPointTy() && "Unknown real conversion");
+ if (DstEltType->isSignedIntegerOrEnumerationType())
+ Res = Builder.CreateFPToSI(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateFPToUI(Src, DstTy, "conv");
+ } else {
+ assert(SrcEltTy->isFloatingPointTy() && DstEltTy->isFloatingPointTy() &&
+ "Unknown real conversion");
+ if (DstEltTy->getTypeID() < SrcEltTy->getTypeID())
+ Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
+ else
+ Res = Builder.CreateFPExt(Src, DstTy, "conv");
+ }
+
+ return Res;
+}
+
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
llvm::APSInt Value;
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
OpenPOWER on IntegriCloud