diff options
author | Nate Begeman <natebegeman@mac.com> | 2010-09-20 22:41:17 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2010-09-20 22:41:17 +0000 |
commit | abb5a7370d021c33c9f4e4640acfe9289b21c93c (patch) | |
tree | 6bc5b099d3cdcd029f2293f5f10276715bb3e69e | |
parent | 50832e02156c689e12a0e75ae6c62db3091d6bbf (diff) | |
download | bcm5719-llvm-abb5a7370d021c33c9f4e4640acfe9289b21c93c.tar.gz bcm5719-llvm-abb5a7370d021c33c9f4e4640acfe9289b21c93c.zip |
Check in support for OpenCL conditional operator on vector types.
llvm-svn: 114371
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 45 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 38 | ||||
-rw-r--r-- | clang/test/Sema/opencl-cond.c | 5 |
4 files changed, 87 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9508c913ec3..5cb242f9ca5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2740,6 +2740,8 @@ def err_typecheck_cond_expect_scalar : Error< "used type %0 where arithmetic or pointer type is required">; def ext_typecheck_cond_one_void : Extension< "C99 forbids conditional expressions with only one void side">; +def err_typecheck_cond_expect_scalar_or_vector : Error< + "used type %0 where arithmetic, pointer, or vector type is required">; def err_typecheck_cast_to_incomplete : Error< "cast to incomplete type %0">; def ext_typecheck_cast_nonscalar : Extension< diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index bacb5641a76..73e94d1ece1 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2169,7 +2169,52 @@ VisitConditionalOperator(const ConditionalOperator *E) { return Visit(Live); } + // OpenCL: If the condition is a vector, we can treat this condition like + // the select function. + if (CGF.getContext().getLangOptions().OpenCL + && E->getCond()->getType()->isVectorType()) { + llvm::Value *CondV = CGF.EmitScalarExpr(E->getCond()); + llvm::Value *LHS = Visit(E->getLHS()); + llvm::Value *RHS = Visit(E->getRHS()); + + const llvm::Type *condType = ConvertType(E->getCond()->getType()); + const llvm::VectorType *vecTy = cast<llvm::VectorType>(condType); + + unsigned numElem = vecTy->getNumElements(); + const llvm::Type *elemType = vecTy->getElementType(); + + std::vector<llvm::Constant*> Zvals; + for (unsigned i = 0; i < numElem; ++i) + Zvals.push_back(llvm::ConstantInt::get(elemType,0)); + + llvm::Value *zeroVec = llvm::ConstantVector::get(Zvals); + llvm::Value *TestMSB = Builder.CreateICmpSLT(CondV, zeroVec); + llvm::Value *tmp = Builder.CreateSExt(TestMSB, + llvm::VectorType::get(elemType, + numElem), + "sext"); + llvm::Value *tmp2 = Builder.CreateNot(tmp); + + // Cast float to int to perform ANDs if necessary. + llvm::Value *RHSTmp = RHS; + llvm::Value *LHSTmp = LHS; + bool wasCast = false; + const llvm::VectorType *rhsVTy = cast<llvm::VectorType>(RHS->getType()); + if (rhsVTy->getElementType()->isFloatTy()) { + RHSTmp = Builder.CreateBitCast(RHS, tmp2->getType()); + LHSTmp = Builder.CreateBitCast(LHS, tmp->getType()); + wasCast = true; + } + + llvm::Value *tmp3 = Builder.CreateAnd(RHSTmp, tmp2); + llvm::Value *tmp4 = Builder.CreateAnd(LHSTmp, tmp); + llvm::Value *tmp5 = Builder.CreateOr(tmp3, tmp4, "cond"); + if (wasCast) + tmp5 = Builder.CreateBitCast(tmp5, RHS->getType()); + return tmp5; + } + // If this is a really simple expression (like x ? 4 : 5), emit this as a // select instead of as control flow. We can only do this if it is cheap and // safe to evaluate the LHS and RHS unconditionally. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2db253a8933..79b27273b5d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4222,15 +4222,47 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // first, check the condition. if (!CondTy->isScalarType()) { // C99 6.5.15p2 - Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) - << CondTy; - return QualType(); + // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar. + // Throw an error if its not either. + if (getLangOptions().OpenCL) { + if (!CondTy->isVectorType()) { + Diag(Cond->getLocStart(), + diag::err_typecheck_cond_expect_scalar_or_vector) + << CondTy; + return QualType(); + } + } + else { + Diag(Cond->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } } // Now check the two expressions. if (LHSTy->isVectorType() || RHSTy->isVectorType()) return CheckVectorOperands(QuestionLoc, LHS, RHS); + // OpenCL: If the condition is a vector, and both operands are scalar, + // attempt to implicity convert them to the vector type to act like the + // built in select. + if (getLangOptions().OpenCL && CondTy->isVectorType()) { + // Both operands should be of scalar type. + if (!LHSTy->isScalarType()) { + Diag(LHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } + if (!RHSTy->isScalarType()) { + Diag(RHS->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } + // Implicity convert these scalars to the type of the condition. + ImpCastExprToType(LHS, CondTy, CK_IntegralCast); + ImpCastExprToType(RHS, CondTy, CK_IntegralCast); + } + // If both operands have arithmetic type, do the usual arithmetic conversions // to find a common type: C99 6.5.15p3,5. if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { diff --git a/clang/test/Sema/opencl-cond.c b/clang/test/Sema/opencl-cond.c new file mode 100644 index 00000000000..d654a152c81 --- /dev/null +++ b/clang/test/Sema/opencl-cond.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 %s -x cl -verify -pedantic -fsyntax-only + +typedef __attribute__((ext_vector_type(4))) float float4; + +float4 foo(float4 a, float4 b, float4 c, float4 d) { return a < b ? c : d; } |