summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorYaxun Liu <Yaxun.Liu@amd.com>2016-06-08 15:11:21 +0000
committerYaxun Liu <Yaxun.Liu@amd.com>2016-06-08 15:11:21 +0000
commitc564701fbd62bbd47b001564ace2649c19ae92ce (patch)
tree0f7f7cee8d011c821496fab2c5b7b9afa8ce0ff1 /clang/lib/CodeGen/CGExprScalar.cpp
parent13d3048cedad51123d42fea730d30bcfaa7967fb (diff)
[OpenCL] Fix __builtin_astype for vec3 types.
__builtin_astype does not generate correct LLVM IR for vec3 types. This patch inserts bitcasts to/from vec4 when necessary in addition to generating vector shuffle. Sema and codegen tests are added. Differential Revision: http://reviews.llvm.org/D20133 llvm-svn: 272153
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp74
1 files changed, 36 insertions, 38 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 0e49ce6aaf35..67ee517d6acb 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -3382,50 +3382,48 @@ Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) {
return CGF.EmitBlockLiteral(block);
}
+// Convert a vec3 to vec4, or vice versa.
+static Value *ConvertVec3AndVec4(CGBuilderTy &Builder, CodeGenFunction &CGF,
+ Value *Src, unsigned NumElementsDst) {
+ llvm::Value *UnV = llvm::UndefValue::get(Src->getType());
+ SmallVector<llvm::Constant*, 4> Args;
+ Args.push_back(Builder.getInt32(0));
+ Args.push_back(Builder.getInt32(1));
+ Args.push_back(Builder.getInt32(2));
+ if (NumElementsDst == 4)
+ Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
+ llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ return Builder.CreateShuffleVector(Src, UnV, Mask);
+}
+
Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
llvm::Type *DstTy = ConvertType(E->getType());
- // Going from vec4->vec3 or vec3->vec4 is a special case and requires
- // a shuffle vector instead of a bitcast.
llvm::Type *SrcTy = Src->getType();
- if (isa<llvm::VectorType>(DstTy) && isa<llvm::VectorType>(SrcTy)) {
- unsigned numElementsDst = cast<llvm::VectorType>(DstTy)->getNumElements();
- unsigned numElementsSrc = cast<llvm::VectorType>(SrcTy)->getNumElements();
- if ((numElementsDst == 3 && numElementsSrc == 4)
- || (numElementsDst == 4 && numElementsSrc == 3)) {
-
-
- // In the case of going from int4->float3, a bitcast is needed before
- // doing a shuffle.
- llvm::Type *srcElemTy =
- cast<llvm::VectorType>(SrcTy)->getElementType();
- llvm::Type *dstElemTy =
- cast<llvm::VectorType>(DstTy)->getElementType();
-
- if ((srcElemTy->isIntegerTy() && dstElemTy->isFloatTy())
- || (srcElemTy->isFloatTy() && dstElemTy->isIntegerTy())) {
- // Create a float type of the same size as the source or destination.
- llvm::VectorType *newSrcTy = llvm::VectorType::get(dstElemTy,
- numElementsSrc);
-
- Src = Builder.CreateBitCast(Src, newSrcTy, "astypeCast");
- }
-
- llvm::Value *UnV = llvm::UndefValue::get(Src->getType());
-
- SmallVector<llvm::Constant*, 3> Args;
- Args.push_back(Builder.getInt32(0));
- Args.push_back(Builder.getInt32(1));
- Args.push_back(Builder.getInt32(2));
-
- if (numElementsDst == 4)
- Args.push_back(llvm::UndefValue::get(CGF.Int32Ty));
-
- llvm::Constant *Mask = llvm::ConstantVector::get(Args);
+ unsigned NumElementsSrc = isa<llvm::VectorType>(SrcTy) ?
+ cast<llvm::VectorType>(SrcTy)->getNumElements() : 0;
+ unsigned NumElementsDst = isa<llvm::VectorType>(DstTy) ?
+ cast<llvm::VectorType>(DstTy)->getNumElements() : 0;
+
+ // Going from vec3 to non-vec3 is a special case and requires a shuffle
+ // vector to get a vec4, then a bitcast if the target type is different.
+ if (NumElementsSrc == 3 && NumElementsDst != 3) {
+ Src = ConvertVec3AndVec4(Builder, CGF, Src, 4);
+ Src = Builder.CreateBitCast(Src, DstTy);
+ Src->setName("astype");
+ return Src;
+ }
- return Builder.CreateShuffleVector(Src, UnV, Mask, "astype");
- }
+ // Going from non-vec3 to vec3 is a special case and requires a bitcast
+ // to vec4 if the original type is not vec4, then a shuffle vector to
+ // get a vec3.
+ if (NumElementsSrc != 3 && NumElementsDst == 3) {
+ auto Vec4Ty = llvm::VectorType::get(DstTy->getVectorElementType(), 4);
+ Src = Builder.CreateBitCast(Src, Vec4Ty);
+ Src = ConvertVec3AndVec4(Builder, CGF, Src, 3);
+ Src->setName("astype");
+ return Src;
}
return Builder.CreateBitCast(Src, DstTy, "astype");