diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11557,9 +11557,10 @@ QualType CXXCheckConditionalOperands( // C++ 5.16 ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); - QualType CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, - ExprResult &RHS, - SourceLocation QuestionLoc); + template + QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool ConvertArgs = true); QualType FindCompositePointerType(SourceLocation Loc, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5945,28 +5945,31 @@ // extension. static bool isValidVectorForConditionalCondition(ASTContext &Ctx, QualType CondTy) { - if (!CondTy->isVectorType() || CondTy->isExtVectorType()) + if (!CondTy->isVectorType() && !CondTy->isExtVectorType()) return false; const QualType EltTy = - cast(CondTy.getCanonicalType())->getElementType(); + CondTy->isVectorType() + ? cast(CondTy.getCanonicalType())->getElementType() + : cast(CondTy.getCanonicalType())->getElementType(); assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() && "Vectors cant be boolean or enum types"); return EltTy->isIntegralType(Ctx); } -QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, - ExprResult &RHS, - SourceLocation QuestionLoc) { +template +QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc) { LHS = DefaultFunctionArrayLvalueConversion(LHS.get()); RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); QualType CondType = Cond.get()->getType(); - const auto *CondVT = CondType->castAs(); + const auto *CondVT = CondType->castAs(); QualType CondElementTy = CondVT->getElementType(); unsigned CondElementCount = CondVT->getNumElements(); QualType LHSType = LHS.get()->getType(); - const auto *LHSVT = LHSType->getAs(); + const auto *LHSVT = LHSType->getAs(); QualType RHSType = RHS.get()->getType(); const auto *RHSVT = RHSType->getAs(); @@ -5974,17 +5977,6 @@ // FIXME: In the future we should define what the Extvector conditional // operator looks like. - if (LHSVT && isa(LHSVT)) { - Diag(QuestionLoc, diag::err_conditional_vector_operand_type) - << /*isExtVector*/ true << LHSType; - return {}; - } - - if (RHSVT && isa(RHSVT)) { - Diag(QuestionLoc, diag::err_conditional_vector_operand_type) - << /*isExtVector*/ true << RHSType; - return {}; - } if (LHSVT && RHSVT) { // If both are vector types, they must be the same type. @@ -6017,17 +6009,21 @@ << /*isExtVector*/ false << ResultElementTy; return {}; } - ResultType = Context.getVectorType( - ResultElementTy, CondType->castAs()->getNumElements(), - VectorType::GenericVector); + if (std::is_same::value) + ResultType = Context.getExtVectorType( + ResultElementTy, CondType->castAs()->getNumElements()); + else + ResultType = Context.getVectorType( + ResultElementTy, CondType->castAs()->getNumElements(), + VectorType::GenericVector); LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat); RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat); } - assert(!ResultType.isNull() && ResultType->isVectorType() && + assert(!ResultType.isNull() && ResultType->getAs() && "Result should have been a vector type"); - auto *ResultVectorTy = ResultType->castAs(); + auto *ResultVectorTy = ResultType->castAs(); QualType ResultElementTy = ResultVectorTy->getElementType(); unsigned ResultElementCount = ResultVectorTy->getNumElements(); @@ -6143,8 +6139,14 @@ } // Neither is void. - if (IsVectorConditional) - return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc); + if (IsVectorConditional) { + auto CondTy = Cond.get()->getType(); + if (CondTy->isExtVectorType()) + return CheckVectorConditionalTypes(Cond, LHS, RHS, + QuestionLoc); + assert(CondTy->isVectorType()); + return CheckVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc); + } // C++11 [expr.cond]p3 // Otherwise, if the second and third operand have different types, and diff --git a/clang/test/CodeGenCXX/ext-vector-type-conditional.cpp b/clang/test/CodeGenCXX/ext-vector-type-conditional.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/ext-vector-type-conditional.cpp @@ -0,0 +1,267 @@ +// RUN: %clang_cc1 %s -triple x86_64-linux-gnu -Wno-unused -std=c++11 -emit-llvm -o - | FileCheck %s + +using FourShorts = short __attribute__((ext_vector_type(4))); +using TwoInts = int __attribute__((ext_vector_type(2))); +using TwoUInts = unsigned __attribute__((ext_vector_type(2))); +using FourInts = int __attribute__((ext_vector_type(4))); +using FourUInts = unsigned __attribute__((ext_vector_type(4))); +using TwoLongLong = long long __attribute__((ext_vector_type(2))); +using FourLongLong = long long __attribute__((ext_vector_type(4))); +using TwoFloats = float __attribute__((ext_vector_type(2))); +using FourFloats = float __attribute__((ext_vector_type(4))); +using TwoDoubles = double __attribute__((ext_vector_type(2))); +using FourDoubles = double __attribute__((ext_vector_type(4))); + +FourShorts four_shorts; +TwoInts two_ints; +TwoUInts two_uints; +FourInts four_ints; +FourUInts four_uints; +TwoLongLong two_ll; +FourLongLong four_ll; +TwoFloats two_floats; +FourFloats four_floats; +TwoDoubles two_doubles; +FourDoubles four_doubles; + +short some_short; +unsigned short some_ushort; +int some_int; +float some_float; +unsigned int some_uint; +long long some_ll; +unsigned long long some_ull; +double some_double; + +// CHECK: TwoVectorOps +void TwoVectorOps() { + two_ints ? two_ints : two_ints; + // CHECK: [[COND:%.+]] = load <2 x i32> + // CHECK: [[LHS:%.+]] = load <2 x i32> + // CHECK: [[RHS:%.+]] = load <2 x i32> + // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32> + // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS]], [[SEXT]] + // CHECK: = or <2 x i32> [[RHS_AND]], [[LHS_AND]] + + two_ints ? two_floats : two_floats; + // CHECK: [[COND:%.+]] = load <2 x i32> + // CHECK: [[LHS:%.+]] = load <2 x float> + // CHECK: [[RHS:%.+]] = load <2 x float> + // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32> + // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], + // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x float> [[RHS]] to <2 x i32> + // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x float> [[LHS]] to <2 x i32> + // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS_EXT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS_EXT]], [[SEXT]] + // CHECK: [[OR:%.+]] = or <2 x i32> [[RHS_AND]], [[LHS_AND]] + // CHECK: = bitcast <2 x i32> [[OR]] to <2 x float> + + two_ll ? two_doubles : two_doubles; + // CHECK: [[COND:%.+]] = load <2 x i64> + // CHECK: [[LHS:%.+]] = load <2 x double> + // CHECK: [[RHS:%.+]] = load <2 x double> + // CHECK: [[NEG:%.+]] = icmp slt <2 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i64> + // CHECK: [[XOR:%.+]] = xor <2 x i64> [[SEXT]], + // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x double> [[RHS]] to <2 x i64> + // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x double> [[LHS]] to <2 x i64> + // CHECK: [[RHS_AND:%.+]] = and <2 x i64> [[RHS_EXT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <2 x i64> [[LHS_EXT]], [[SEXT]] + // CHECK: [[OR:%.+]] = or <2 x i64> [[RHS_AND]], [[LHS_AND]] + // CHECK: = bitcast <2 x i64> [[OR]] to <2 x double> +} + +// CHECK: TwoScalarOps +void TwoScalarOps() { + four_shorts ? some_short : some_short; + // CHECK: [[COND:%.+]] = load <4 x i16> + // CHECK: [[LHS:%.+]] = load i16 + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load i16 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16> + // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]] + // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]] + + four_shorts ? some_ushort : some_ushort; + // CHECK: [[COND:%.+]] = load <4 x i16> + // CHECK: [[LHS:%.+]] = load i16 + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load i16 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16> + // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]] + // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]] + + four_ints ? some_ushort : some_short; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load i16 + // CHECK: [[LHS_ZEXT:%.+]] = zext i16 [[LHS]] to i32 + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS_ZEXT]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load i16 + // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] + + four_ints ? some_int : some_float; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load i32 + // CHECK: [[LHS_CONV:%.+]] = sitofp i32 [[LHS]] to float + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[LHS_CONV]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x float> [[LHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load float + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32> + // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS_SPLAT]] to <4 x i32> + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] + + four_ll ? some_double : some_ll; + // CHECK: [[COND:%.+]] = load <4 x i64> + // CHECK: [[LHS:%.+]] = load double + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[LHS]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x double> [[LHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load i64 + // CHECK: [[RHS_CONV:%.+]] = sitofp i64 [[RHS]] to double + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[RHS_CONV]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x double> [[RHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64> + // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], + // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x double> [[RHS_SPLAT]] to <4 x i64> + // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS_SPLAT]] to <4 x i64> + // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_CAST]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]] + // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]] + + four_ints ? some_int : some_short; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load i32 + // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS]], i32 0 + // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer + // CHECK: [[RHS:%.+]] = load i16 + // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] +} + +// CHECK: OneScalarOp +void OneScalarOp() { + four_ints ? four_ints : some_int; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load <4 x i32> + // CHECK: [[RHS:%.+]] = load i32 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] + + four_ints ? four_ints : 5; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load <4 x i32> + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> , [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] + + four_ints ? four_floats : some_float; + // CHECK: [[COND:%.+]] = load <4 x i32> + // CHECK: [[LHS:%.+]] = load <4 x float> + // CHECK: [[RHS:%.+]] = load float + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32> + // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], + // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32> + // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS]] to <4 x i32> + // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]] + // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]] + + four_ll ? four_doubles : 6.0; + // CHECK: [[COND:%.+]] = load <4 x i64> + // CHECK: [[LHS:%.+]] = load <4 x double> + // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64> + // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], + // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS]] to <4 x i64> + // CHECK: [[RHS_AND:%.+]] = and <4 x i64> , [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]] + // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]] + + four_ll ? four_ll : 6; + // CHECK: [[COND:%.+]] = load <4 x i64> + // CHECK: [[LHS:%.+]] = load <4 x i64> + // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64> + // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i64> , [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]] + // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]] + + four_ll ? four_ll : some_int; + // CHECK: [[COND:%.+]] = load <4 x i64> + // CHECK: [[LHS:%.+]] = load <4 x i64> + // CHECK: [[RHS:%.+]] = load i32 + // CHECK: [[RHS_CONV:%.+]] = sext i32 [[RHS]] to i64 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS_CONV]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64> + // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]] + // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]] + + four_ll ? four_ll : some_ll; + // CHECK: [[COND:%.+]] = load <4 x i64> + // CHECK: [[LHS:%.+]] = load <4 x i64> + // CHECK: [[RHS:%.+]] = load i64 + // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS]], i32 0 + // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer + // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer + // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64> + // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], + // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]] + // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]] + // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]] +} diff --git a/clang/test/CodeGenCXX/vector-conditional.cpp b/clang/test/CodeGenCXX/vector-size-conditional.cpp rename from clang/test/CodeGenCXX/vector-conditional.cpp rename to clang/test/CodeGenCXX/vector-size-conditional.cpp diff --git a/clang/test/SemaCXX/vector-conditional.cpp b/clang/test/SemaCXX/ext-vector-type-conditional.cpp rename from clang/test/SemaCXX/vector-conditional.cpp rename to clang/test/SemaCXX/ext-vector-type-conditional.cpp --- a/clang/test/SemaCXX/vector-conditional.cpp +++ b/clang/test/SemaCXX/ext-vector-type-conditional.cpp @@ -2,17 +2,17 @@ // Note that this test depends on the size of long-long to be different from // int, so it specifies a triple. -using FourShorts = short __attribute__((__vector_size__(8))); -using TwoInts = int __attribute__((__vector_size__(8))); -using TwoUInts = unsigned __attribute__((__vector_size__(8))); -using FourInts = int __attribute__((__vector_size__(16))); -using FourUInts = unsigned __attribute__((__vector_size__(16))); -using TwoLongLong = long long __attribute__((__vector_size__(16))); -using FourLongLong = long long __attribute__((__vector_size__(32))); -using TwoFloats = float __attribute__((__vector_size__(8))); -using FourFloats = float __attribute__((__vector_size__(16))); -using TwoDoubles = double __attribute__((__vector_size__(16))); -using FourDoubles = double __attribute__((__vector_size__(32))); +using FourShorts = short __attribute__((ext_vector_type(4))); +using TwoInts = int __attribute__((ext_vector_type(2))); +using TwoUInts = unsigned __attribute__((ext_vector_type(2))); +using FourInts = int __attribute__((ext_vector_type(4))); +using FourUInts = unsigned __attribute__((ext_vector_type(4))); +using TwoLongLong = long long __attribute__((ext_vector_type(2))); +using FourLongLong = long long __attribute__((ext_vector_type(4))); +using TwoFloats = float __attribute__((ext_vector_type(2))); +using FourFloats = float __attribute__((ext_vector_type(4))); +using TwoDoubles = double __attribute__((ext_vector_type(2))); +using FourDoubles = double __attribute__((ext_vector_type(4))); FourShorts four_shorts; TwoInts two_ints; @@ -55,9 +55,9 @@ (void)(four_ints ?: four_doubles); // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourDoubles' (vector of 4 'double' values)}} // Scalars are promoted, but must be the same element size. - (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) do not have elements of the same size}} - (void)(four_ints ? 5ll : 5); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(long long)))) long long' (vector of 4 'long long' values) do not have elements of the same size}} - (void)(four_ints ?: 3.0); // expected-error {{cannot convert between scalar type 'double' and vector type 'FourInts' (vector of 4 'int' values) as implicit conversion would cause truncation}} + (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values) do not have elements of the same size}} + (void)(four_ints ? 5ll : 5); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'long long __attribute__((ext_vector_type(4)))' (vector of 4 'long long' values) do not have elements of the same size}} + (void)(four_ints ?: 3.0); // expected-error {{annot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'double')}} (void)(four_ints ?: 5ll); // We allow this despite GCc not allowing this since we support integral->vector-integral conversions despite integer rank. // This one would be allowed in GCC, but we don't allow vectors of enum. Also, @@ -66,7 +66,7 @@ // the other side causes. (void)(four_ints ? e : e); // expected-error {{enumeration type 'E' is not allowed in a vector conditional}} (void)(four_ints ? se : se); // expected-error {{enumeration type 'SE' is not allowed in a vector conditional}} - (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}} + (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}} // They must also be convertible. (void)(four_ints ? 3.0f : 5u); @@ -81,29 +81,28 @@ (void)(four_ints ? 3.0f : sint); // Test promotion: - (void)(four_shorts ? uss : shrt); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}} + (void)(four_shorts ? uss : shrt); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}} (void)(four_shorts ? shrt : shrt); // should be fine. (void)(four_ints ? uss : shrt); // should be fine, since they get promoted to int. - (void)(four_ints ? shrt : shrt); //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(short)))) short' (vector of 4 'short' values) do not have elements of the same size}} + (void)(four_ints ? shrt : shrt); //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'short __attribute__((ext_vector_type(4)))' (vector of 4 'short' values) do not have elements of the same size}} // Vectors must be the same type as eachother. (void)(four_ints ? four_uints : four_floats); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourFloats' (vector of 4 'float' values))}} (void)(four_ints ? four_uints : four_ints); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourInts' (vector of 4 'int' values))}} (void)(four_ints ? four_ints : four_uints); // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourUInts' (vector of 4 'unsigned int' values))}} - // GCC rejects these, but our lax vector conversions don't seem to have a problem with them. Allow conversion of the float to an int as an extension. - (void)(four_ints ? four_uints : 3.0f); - (void)(four_ints ? four_ints : 3.0f); + (void)(four_ints ? four_uints : 3.0f); // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'float')}} + (void)(four_ints ? four_ints : 3.0f); // expected-error {{cannot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'float')}} // When there is a vector and a scalar, conversions must be legal. (void)(four_ints ? four_floats : 3); // should work, ints can convert to floats. - (void)(four_ints ? four_uints : e); // expected-error {{cannot convert between scalar type 'E' and vector type 'FourUInts'}} + (void)(four_ints ? four_uints : e); // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'E')}} (void)(four_ints ? four_uints : se); // expected-error {{cannot convert between vector and non-scalar values ('FourUInts' (vector of 4 'unsigned int' values) and 'SE'}} - // GCC permits this, but our conversion rules reject this for truncation. - (void)(two_ints ? two_ints : us); // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'TwoInts'}} - (void)(four_shorts ? four_shorts : uss); // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'FourShorts'}} - (void)(four_ints ? four_floats : us); // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'FourFloats'}} - (void)(four_ints ? four_floats : sint); // expected-error {{cannot convert between scalar type 'int' and vector type 'FourFloats'}} + + (void)(two_ints ? two_ints : us); + (void)(four_shorts ? four_shorts : uss); + (void)(four_ints ? four_floats : us); + (void)(four_ints ? four_floats : sint); } template @@ -163,10 +162,10 @@ void Templates() { dependent_cond(two_ints); dependent_operand(two_floats); - // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values))}}} + // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values))}}} all_dependent(four_ints, four_uints, four_doubles); // expected-note {{in instantiation of}} - // expected-error@159 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values))}}} + // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'unsigned int __attribute__((ext_vector_type(2)))' (vector of 2 'unsigned int' values))}}} all_dependent(four_ints, four_uints, two_uints); // expected-note {{in instantiation of}} all_dependent(four_ints, four_uints, four_uints); } diff --git a/clang/test/SemaCXX/vector-conditional.cpp b/clang/test/SemaCXX/vector-size-conditional.cpp rename from clang/test/SemaCXX/vector-conditional.cpp rename to clang/test/SemaCXX/vector-size-conditional.cpp