From 4431d64c10cb681986e752420f1136f259daa5a7 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu Date: Tue, 26 May 2020 06:27:34 +0000 Subject: [PATCH] Support ExtVectorType conditional operator Extension vectors now can be used in element-wise conditional selector. For example: ``` R[i] = C[i]? A[i] : B[i] ``` This feature was previously only enabled in OpenCL C. Now it's also available in C. Not that it has different behaviors than GNU vectors (i.e. __vector_size__). Extension vectors selects on signdness of the vector. GNU vectors on the other hand do normal bool conversions. Also, this feature is not available in C++. Differential Revision: https://reviews.llvm.org/D80574 --- clang/docs/LanguageExtensions.rst | 10 ++++++---- clang/lib/CodeGen/CGExprScalar.cpp | 4 ++-- clang/lib/Sema/SemaExpr.cpp | 3 ++- clang/test/Sema/ext_vector_comparisons.c | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 2fbf5ea..d3d73bf 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -478,7 +478,7 @@ bitwise operators &,|,^,~ yes yes yes -- !, &&, || yes -- yes [#]_ -- ==, !=, >, <, >=, <= yes yes yes -- = yes yes yes yes -:? [#]_ yes -- yes -- +?: [#]_ yes -- yes -- sizeof yes yes yes yes C-style cast yes yes yes no reinterpret_cast yes no yes no @@ -489,9 +489,11 @@ const_cast no no no no See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. .. [#] unary operator ! is not implemented, however && and || are. -.. [#] While OpenCL and GCC vectors both implement the comparison operator(?:) as a - 'select', they operate somewhat differently. OpenCL selects based on signedness of - the condition operands, but GCC vectors use normal bool conversions (that is, != 0). +.. [#] ternary operator(?:) has different behaviors depending on condition + operand's vector type. If the condition is a GNU vector (i.e. __vector_size__), + it's only available in C++ and uses normal bool conversions (that is, != 0). + If it's an extension (OpenCL) vector, it's only available in C and OpenCL C. + And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9). Matrix Types ============ diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 028a2cf..b169462 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4432,8 +4432,8 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { // OpenCL: If the condition is a vector, we can treat this condition like // the select function. - if (CGF.getLangOpts().OpenCL - && condExpr->getType()->isVectorType()) { + if ((CGF.getLangOpts().OpenCL && condExpr->getType()->isVectorType()) || + condExpr->getType()->isExtVectorType()) { CGF.incrementProfileCounter(E); llvm::Value *CondV = CGF.EmitScalarExpr(condExpr); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2221f98..5e8b1d8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8078,7 +8078,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // The OpenCL operator with a vector condition is sufficiently // different to merit its own checker. - if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) + if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) || + Cond.get()->getType()->isExtVectorType()) return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc); // First, check the condition. diff --git a/clang/test/Sema/ext_vector_comparisons.c b/clang/test/Sema/ext_vector_comparisons.c index 4c632a4..f1c292f 100644 --- a/clang/test/Sema/ext_vector_comparisons.c +++ b/clang/test/Sema/ext_vector_comparisons.c @@ -28,3 +28,19 @@ static int4 test2() { return vec > vec; // no-warning return vec >= vec; // no-warning } + +static int4 test3() { + int4 i0, i1; + + return i0 > i1 ? i0 : i1; // no-error + return i0 ? i0 : i1; // no-error +} + +static float4 test4() { + float4 f0, f1; + + // This would actually generate implicit casting warning + // under Weverything flag but we don't really care here + return f0 > f1 ? f0 : f1; // no-error + return f0 ? f0 : f1; // expected-error {{used type 'float4' (vector of 4 'float' values) where floating point type is not allowed}} +} -- 2.7.4