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 | 6155d73ad1668be5335b1a060f6c49c03d4dca05 (patch) | |
tree | 06c3cc14f70cac261dce9f550e0ced6b2a29dab7 /lib/CodeGen/CGExprScalar.cpp | |
parent | cee9ff16688bc6dd6571162c1860f4eae05d98f7 (diff) |
Check in support for OpenCL conditional operator on vector types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114371 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprScalar.cpp')
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index bacb5641a7..73e94d1ece 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/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. |