From: Tanya Lattner Date: Mon, 16 Jan 2012 21:02:28 +0000 (+0000) Subject: Add support for OpenCL 1.1 logical operations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f692c27d74e249d6ef8d24792c35f3e5c620e2a;p=clang Add support for OpenCL 1.1 logical operations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148254 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 61d3022d52..c4af62530a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5925,8 +5925,11 @@ public: /// type checking for vector binary operators. QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign); + QualType GetSignedVectorType(QualType V); QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool isRelational); + QualType CheckVectorLogicalOperands(ExprResult LHS, ExprResult RHS, + SourceLocation Loc); /// type checking declaration initializers (C99 6.7.8) bool CheckForConstantInitializer(Expr *e, QualType t); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 8087c3b802..faa90872e7 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1478,6 +1478,15 @@ Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) { } Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { + + // Perform vector logical not on comparison with zero vector. + if (E->getType()->isExtVectorType()) { + Value *Oper = Visit(E->getSubExpr()); + Value *Zero = llvm::Constant::getNullValue(Oper->getType()); + Value *Result = Builder.CreateICmp(llvm::CmpInst::ICMP_EQ, Oper, Zero, "cmp"); + return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext"); + } + // Compare operand to zero. Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr()); @@ -2386,6 +2395,18 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { } Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { + + // Perform vector logical and on comparisons with zero vectors. + if (E->getType()->isVectorType()) { + Value *LHS = Visit(E->getLHS()); + Value *RHS = Visit(E->getRHS()); + Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType()); + LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp"); + RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp"); + Value *And = Builder.CreateAnd(LHS, RHS); + return Builder.CreateSExt(And, Zero->getType(), "sext"); + } + llvm::Type *ResTy = ConvertType(E->getType()); // If we have 0 && RHS, see if we can elide RHS, if so, just return 0. @@ -2441,6 +2462,18 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { } Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { + + // Perform vector logical or on comparisons with zero vectors. + if (E->getType()->isVectorType()) { + Value *LHS = Visit(E->getLHS()); + Value *RHS = Visit(E->getRHS()); + Value *Zero = llvm::ConstantAggregateZero::get(LHS->getType()); + LHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, LHS, Zero, "cmp"); + RHS = Builder.CreateICmp(llvm::CmpInst::ICMP_NE, RHS, Zero, "cmp"); + Value *Or = Builder.CreateOr(LHS, RHS); + return Builder.CreateSExt(Or, Zero->getType(), "sext"); + } + llvm::Type *ResTy = ConvertType(E->getType()); // If we have 1 || RHS, see if we can elide RHS, if so, just return 1. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5baf14342f..1655c9105f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -6882,6 +6882,26 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } + +// Return a signed type that is of identical size and number of elements. +// For floating point vectors, return an integer type of identical size +// and number of elements. +QualType Sema::GetSignedVectorType(QualType V) { + const VectorType *VTy = V->getAs(); + unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); + if (TypeSize == Context.getTypeSize(Context.CharTy)) + return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + else if (TypeSize == Context.getTypeSize(Context.LongTy)) + return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); + assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + "Unhandled vector element size in vector compare"); + return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +} + /// CheckVectorCompareOperands - vector comparisons are a clang extension that /// operates on extended vector types. Instead of producing an IntTy result, /// like a scalar comparison, a vector comparison produces a vector of integer @@ -6923,23 +6943,21 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, assert (RHS.get()->getType()->hasFloatingRepresentation()); CheckFloatComparison(Loc, LHS.get(), RHS.get()); } + + // Return a signed type for the vector. + return GetSignedVectorType(LHSType); +} - // Return a signed type that is of identical size and number of elements. - // For floating point vectors, return an integer type of identical size - // and number of elements. - const VectorType *VTy = LHSType->getAs(); - unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); - if (TypeSize == Context.getTypeSize(Context.CharTy)) - return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.ShortTy)) - return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.IntTy)) - return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.LongTy)) - return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); - assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && - "Unhandled vector element size in vector compare"); - return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +QualType Sema::CheckVectorLogicalOperands(ExprResult LHS, ExprResult RHS, + SourceLocation Loc) +{ + // Ensure that either both operands are of the same vector type, or + // one operand is of a vector type and the other is of its element type. + QualType vType = CheckVectorOperands(LHS, RHS, Loc, false); + if (vType.isNull() || vType->isFloatingType()) + return InvalidOperands(Loc, LHS, RHS); + + return GetSignedVectorType(LHS.get()->getType()); } inline QualType Sema::CheckBitwiseOperands( @@ -6972,6 +6990,10 @@ inline QualType Sema::CheckBitwiseOperands( inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc) { + // Check vector operands differently. + if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) + return CheckVectorLogicalOperands(LHS, RHS, Loc); + // Diagnose cases where the user write a logical and/or but probably meant a // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. @@ -8261,6 +8283,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, Input = ImpCastExprToType(Input.take(), Context.BoolTy, ScalarTypeToBooleanCastKind(resultType)); } + } + else if (resultType->isExtVectorType()) { + // Handle vector types. + // Vector logical not returns the signed variant of the operand type. + resultType = GetSignedVectorType(resultType); + break; } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); diff --git a/test/CodeGen/ext-vector.c b/test/CodeGen/ext-vector.c index 896814bc24..1387b139ca 100644 --- a/test/CodeGen/ext-vector.c +++ b/test/CodeGen/ext-vector.c @@ -277,3 +277,12 @@ void test14(uint4 *ap, uint4 *bp, unsigned c) { d = a == b; d = a != b; } + +// CHECK: @test15 +int4 test15(uint4 V0) { + // CHECK: icmp eq <4 x i32> + int4 V = !V0; + V = V && V; + V = V || V; + return V; +} \ No newline at end of file