Reland D80979 [clang] Implement VectorType logic not operator

With a fix to use -triple %itanium_abi_triple

Differential Revision: https://reviews.llvm.org/D80979
This commit is contained in:
Fangrui Song 2020-06-08 09:32:30 -07:00
parent 9982d48a92
commit fc935fc35b
5 changed files with 35 additions and 6 deletions

View File

@ -475,7 +475,7 @@ unary operators +, -- yes yes yes --
+,--,*,/,% yes yes yes --
bitwise operators &,|,^,~ yes yes yes --
>>,<< yes yes yes --
!, &&, || yes -- yes [#]_ --
!, &&, || yes -- yes --
==, !=, >, <, >=, <= yes yes yes --
= yes yes yes yes
?: [#]_ yes -- yes --
@ -488,7 +488,6 @@ const_cast no no no no
See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`.
.. [#] unary operator ! is not implemented, however && and || are.
.. [#] 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).

View File

@ -2762,7 +2762,9 @@ 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()) {
if (E->getType()->isVectorType() &&
E->getType()->castAs<VectorType>()->getVectorKind() ==
VectorType::GenericVector) {
Value *Oper = Visit(E->getSubExpr());
Value *Zero = llvm::Constant::getNullValue(Oper->getType());
Value *Result;

View File

@ -14481,12 +14481,19 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
// Vector logical not returns the signed variant of the operand type.
resultType = GetSignedVectorType(resultType);
break;
} else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) {
const VectorType *VTy = resultType->castAs<VectorType>();
if (VTy->getVectorKind() != VectorType::GenericVector)
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
// Vector logical not returns the signed variant of the operand type.
resultType = GetSignedVectorType(resultType);
break;
} else {
// FIXME: GCC's vector extension permits the usage of '!' with a vector
// type in C++. We should allow that here too.
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}

View File

@ -0,0 +1,21 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
typedef __attribute__((__vector_size__(16))) float float4;
typedef __attribute__((__vector_size__(16))) int int4;
typedef __attribute__((__vector_size__(16))) unsigned int uint4;
// CHECK: @_Z5test1Dv4_j
int4 test1(uint4 V0) {
// CHECK: [[CMP0:%.*]] = icmp eq <4 x i32> [[V0:%.*]], zeroinitializer
// CHECK-NEXT: [[V1:%.*]] = sext <4 x i1> [[CMP0]] to <4 x i32>
int4 V = !V0;
return V;
}
// CHECK: @_Z5test2Dv4_fS_
int4 test2(float4 V0, float4 V1) {
// CHECK: [[CMP0:%.*]] = fcmp oeq <4 x float> [[V0:%.*]], zeroinitializer
// CHECK-NEXT: [[V1:%.*]] = sext <4 x i1> [[CMP0]] to <4 x i32>
int4 V = !V0;
return V;
}

View File

@ -83,7 +83,7 @@ void logicTest(void) {
v2i64 v2i64_c = (v2i64){3, 1}; // expected-warning {{compound literals are a C99-specific feature}}
v2i64 v2i64_r;
v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}}
v2i64_r = !v2i64_a;
v2i64_r = ~v2i64_a;
v2i64_r = v2i64_a ? v2i64_b : v2i64_c;