[clang] a94f68a - Implement some constexpr vector unary operators, fix boolean-ops

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 17 06:08:41 PST 2021


Author: Erich Keane
Date: 2021-12-17T06:08:36-08:00
New Revision: a94f68a2bd31db9712582b973e78746cee9a4e50

URL: https://github.com/llvm/llvm-project/commit/a94f68a2bd31db9712582b973e78746cee9a4e50
DIFF: https://github.com/llvm/llvm-project/commit/a94f68a2bd31db9712582b973e78746cee9a4e50.diff

LOG: Implement some constexpr vector unary operators, fix boolean-ops

As requested in the review, this implements unary +,-,~, and ! for
vector types.

All of our boolean operations on vector types should be using something
like vcmpeqd, which results in a mask of '-1' for the 'truth' type. We are
currently instead using '1', which results in some incorrect
calculations when used later (note that it does NOT result in a boolean
vector, as that is not really a thing).

This patch corrects that 1 to be a -1, and updates the affected tests.

Differential Revision: https://reviews.llvm.org/D115670

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/constexpr-vectors.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index bb59e72ed51b6..9fcba4e25cef6 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2931,6 +2931,11 @@ handleCompareOpForVectorHelper(const APTy &LHSValue, BinaryOperatorKind Opcode,
     break;
   }
 
+  // The boolean operations on these vector types use an instruction that
+  // results in a mask of '-1' for the 'truth' value.  Ensure that we negate 1
+  // to -1 to make sure that we produce the correct value.
+  Result.negate();
+
   return true;
 }
 
@@ -10179,7 +10184,8 @@ namespace {
     bool VisitInitListExpr(const InitListExpr *E);
     bool VisitUnaryImag(const UnaryOperator *E);
     bool VisitBinaryOperator(const BinaryOperator *E);
-    // FIXME: Missing: unary -, unary ~, conditional operator (for GNU
+    bool VisitUnaryOperator(const UnaryOperator *E);
+    // FIXME: Missing: conditional operator (for GNU
     //                 conditional select), shufflevector, ExtVectorElementExpr
   };
 } // end anonymous namespace
@@ -10364,6 +10370,83 @@ bool VectorExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
   return Success(LHSValue, E);
 }
 
+static llvm::Optional<APValue> handleVectorUnaryOperator(ASTContext &Ctx,
+                                                         QualType ResultTy,
+                                                         UnaryOperatorKind Op,
+                                                         APValue Elt) {
+  switch (Op) {
+  case UO_Plus:
+    // Nothing to do here.
+    return Elt;
+  case UO_Minus:
+    if (Elt.getKind() == APValue::Int) {
+      Elt.getInt().negate();
+    } else {
+      assert(Elt.getKind() == APValue::Float &&
+             "Vector can only be int or float type");
+      Elt.getFloat().changeSign();
+    }
+    return Elt;
+  case UO_Not:
+    // This is only valid for integral types anyway, so we don't have to handle
+    // float here.
+    assert(Elt.getKind() == APValue::Int &&
+           "Vector operator ~ can only be int");
+    Elt.getInt().flipAllBits();
+    return Elt;
+  case UO_LNot: {
+    if (Elt.getKind() == APValue::Int) {
+      Elt.getInt() = !Elt.getInt();
+      // operator ! on vectors returns -1 for 'truth', so negate it.
+      Elt.getInt().negate();
+      return Elt;
+    }
+    assert(Elt.getKind() == APValue::Float &&
+           "Vector can only be int or float type");
+    // Float types result in an int of the same size, but -1 for true, or 0 for
+    // false.
+    APSInt EltResult{Ctx.getIntWidth(ResultTy),
+                     ResultTy->isUnsignedIntegerType()};
+    if (Elt.getFloat().isZero())
+      EltResult.setAllBits();
+    else
+      EltResult.clearAllBits();
+
+    return APValue{EltResult};
+  }
+  default:
+    // FIXME: Implement the rest of the unary operators.
+    return llvm::None;
+  }
+}
+
+bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+  Expr *SubExpr = E->getSubExpr();
+  const auto *VD = SubExpr->getType()->castAs<VectorType>();
+  // This result element type 
diff ers in the case of negating a floating point
+  // vector, since the result type is the a vector of the equivilant sized
+  // integer.
+  const QualType ResultEltTy = VD->getElementType();
+  UnaryOperatorKind Op = E->getOpcode();
+
+  APValue SubExprValue;
+  if (!Evaluate(SubExprValue, Info, SubExpr))
+    return false;
+
+  assert(SubExprValue.getVectorLength() == VD->getNumElements() &&
+         "Vector length doesn't match type?");
+
+  SmallVector<APValue, 4> ResultElements;
+  for (unsigned EltNum = 0; EltNum < VD->getNumElements(); ++EltNum) {
+    llvm::Optional<APValue> Elt = handleVectorUnaryOperator(
+        Info.Ctx, ResultEltTy, Op, SubExprValue.getVectorElt(EltNum));
+    if (!Elt)
+      return false;
+    ResultElements.push_back(*Elt);
+  }
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
 //===----------------------------------------------------------------------===//
 // Array Evaluation
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2b69c37278526..82e881476d35c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12261,27 +12261,32 @@ QualType Sema::GetSignedVectorType(QualType V) {
   if (isa<ExtVectorType>(VTy)) {
     if (TypeSize == Context.getTypeSize(Context.CharTy))
       return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
-    else if (TypeSize == Context.getTypeSize(Context.ShortTy))
+    if (TypeSize == Context.getTypeSize(Context.ShortTy))
       return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
-    else if (TypeSize == Context.getTypeSize(Context.IntTy))
+    if (TypeSize == Context.getTypeSize(Context.IntTy))
       return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
-    else if (TypeSize == Context.getTypeSize(Context.LongTy))
+    if (TypeSize == Context.getTypeSize(Context.Int128Ty))
+      return Context.getExtVectorType(Context.Int128Ty, VTy->getNumElements());
+    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());
   }
 
+  if (TypeSize == Context.getTypeSize(Context.Int128Ty))
+    return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(),
+                                 VectorType::GenericVector);
   if (TypeSize == Context.getTypeSize(Context.LongLongTy))
     return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
                                  VectorType::GenericVector);
-  else if (TypeSize == Context.getTypeSize(Context.LongTy))
+  if (TypeSize == Context.getTypeSize(Context.LongTy))
     return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
                                  VectorType::GenericVector);
-  else if (TypeSize == Context.getTypeSize(Context.IntTy))
+  if (TypeSize == Context.getTypeSize(Context.IntTy))
     return Context.getVectorType(Context.IntTy, VTy->getNumElements(),
                                  VectorType::GenericVector);
-  else if (TypeSize == Context.getTypeSize(Context.ShortTy))
+  if (TypeSize == Context.getTypeSize(Context.ShortTy))
     return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
                                  VectorType::GenericVector);
   assert(TypeSize == Context.getTypeSize(Context.CharTy) &&

diff  --git a/clang/test/SemaCXX/constexpr-vectors.cpp b/clang/test/SemaCXX/constexpr-vectors.cpp
index 1ba0e33253321..609d1970dde87 100644
--- a/clang/test/SemaCXX/constexpr-vectors.cpp
+++ b/clang/test/SemaCXX/constexpr-vectors.cpp
@@ -11,12 +11,15 @@ using FourIntsVecSize __attribute__((vector_size(16))) = int;
 using FourLongLongsVecSize __attribute__((vector_size(32))) = long long;
 using FourFloatsVecSize __attribute__((vector_size(16))) = float;
 using FourDoublesVecSize __attribute__((vector_size(32))) = double;
+using FourI128VecSize __attribute__((vector_size(64))) = __int128;
 
 using FourCharsExtVec __attribute__((ext_vector_type(4))) = char;
 using FourIntsExtVec __attribute__((ext_vector_type(4))) = int;
 using FourLongLongsExtVec __attribute__((ext_vector_type(4))) = long long;
 using FourFloatsExtVec __attribute__((ext_vector_type(4))) = float;
 using FourDoublesExtVec __attribute__((ext_vector_type(4))) = double;
+using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128;
+
 
 // Next a series of tests to make sure these operations are usable in
 // constexpr functions. Template instantiations don't emit Winvalid-constexpr,
@@ -204,35 +207,35 @@ void CharUsage() {
 
   constexpr auto w = FourCharsVecSize{1, 2, 3, 4} <
                      FourCharsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0>
   constexpr auto x = FourCharsVecSize{1, 2, 3, 4} >
                      FourCharsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <=
                      FourCharsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0>
   constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >=
                      FourCharsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto A = FourCharsVecSize{1, 2, 3, 4} ==
                      FourCharsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0>
   constexpr auto B = FourCharsVecSize{1, 2, 3, 4} !=
                      FourCharsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1>
 
   constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0>
   constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 -1>
   constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0>
   constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0>
   constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1>
 
   constexpr auto I = FourCharsVecSize{1, 2, 3, 4} &
                      FourCharsVecSize{4, 3, 2, 1};
@@ -277,10 +280,12 @@ void CharUsage() {
   constexpr auto Y = CmpSub(a, b);
   // CHECK: store <4 x i8> <i8 12, i8 17, i8 -1, i8 -1>
 
-  constexpr auto Z = CmpLSH(a, H);
+  constexpr auto InvH = -H;
+  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  constexpr auto Z = CmpLSH(a, InvH);
   // CHECK: store <4 x i8> <i8 36, i8 36, i8 7, i8 16>
 
-  constexpr auto aa = CmpRSH(a, H);
+  constexpr auto aa = CmpRSH(a, InvH);
   // CHECK: store <4 x i8> <i8 9, i8 9, i8 7, i8 4>
 
   constexpr auto ab = CmpBinAnd(a, b);
@@ -291,6 +296,12 @@ void CharUsage() {
 
   constexpr auto ad = CmpBinOr(a, b);
   // CHECK: store <4 x i8> <i8 22, i8 19, i8 15, i8 9>
+
+  constexpr auto ae = ~FourCharsVecSize{1, 2, 10, 20};
+  // CHECK: store <4 x i8> <i8 -2, i8 -3, i8 -11, i8 -21>
+
+  constexpr auto af = !FourCharsVecSize{0, 1, 8, -1};
+  // CHECK: store <4 x i8> <i8 -1, i8 0, i8 0, i8 0>
 }
 
 void CharExtVecUsage() {
@@ -348,35 +359,35 @@ void CharExtVecUsage() {
 
   constexpr auto w = FourCharsExtVec{1, 2, 3, 4} <
                      FourCharsExtVec{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0>
   constexpr auto x = FourCharsExtVec{1, 2, 3, 4} >
                      FourCharsExtVec{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto y = FourCharsExtVec{1, 2, 3, 4} <=
                      FourCharsExtVec{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0>
   constexpr auto z = FourCharsExtVec{1, 2, 3, 4} >=
                      FourCharsExtVec{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto A = FourCharsExtVec{1, 2, 3, 4} ==
                      FourCharsExtVec{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0>
   constexpr auto B = FourCharsExtVec{1, 2, 3, 4} !=
                      FourCharsExtVec{4, 3, 3, 1};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1>
 
   constexpr auto C = FourCharsExtVec{1, 2, 3, 4} < 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0>
   constexpr auto D = FourCharsExtVec{1, 2, 3, 4} > 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 -1>
   constexpr auto E = FourCharsExtVec{1, 2, 3, 4} <= 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0>
   constexpr auto F = FourCharsExtVec{1, 2, 3, 4} >= 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
   constexpr auto G = FourCharsExtVec{1, 2, 3, 4} == 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0>
+  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0>
   constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1>
 
   constexpr auto I = FourCharsExtVec{1, 2, 3, 4} &
                      FourCharsExtVec{4, 3, 2, 1};
@@ -421,10 +432,13 @@ void CharExtVecUsage() {
   constexpr auto Y = CmpSub(a, b);
   // CHECK: store <4 x i8> <i8 12, i8 17, i8 -1, i8 -1>
 
-  constexpr auto Z = CmpLSH(a, H);
+  constexpr auto InvH = -H;
+  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+
+  constexpr auto Z = CmpLSH(a, InvH);
   // CHECK: store <4 x i8> <i8 36, i8 36, i8 7, i8 16>
 
-  constexpr auto aa = CmpRSH(a, H);
+  constexpr auto aa = CmpRSH(a, InvH);
   // CHECK: store <4 x i8> <i8 9, i8 9, i8 7, i8 4>
 
   constexpr auto ab = CmpBinAnd(a, b);
@@ -435,6 +449,12 @@ void CharExtVecUsage() {
 
   constexpr auto ad = CmpBinOr(a, b);
   // CHECK: store <4 x i8> <i8 22, i8 19, i8 15, i8 9>
+
+  constexpr auto ae = ~FourCharsExtVec{1, 2, 10, 20};
+  // CHECK: store <4 x i8> <i8 -2, i8 -3, i8 -11, i8 -21>
+
+  constexpr auto af = !FourCharsExtVec{0, 1, 8, -1};
+  // CHECK: store <4 x i8> <i8 -1, i8 0, i8 0, i8 0>
 }
 
 void FloatUsage() {
@@ -471,35 +491,35 @@ void FloatUsage() {
 
   constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} <
                      FourFloatsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0>
   constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} >
                      FourFloatsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0>
   constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} ==
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0>
   constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} !=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1>
 
   constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0>
   constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 -1>
   constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0>
   constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0>
   constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1>
 
   constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} &&
                      FourFloatsVecSize{5, 5, 0, 0};
@@ -524,6 +544,13 @@ void FloatUsage() {
 
   constexpr auto Y = CmpSub(a, b);
   // CHECK: store <4 x float> <float 1.200000e+01, float 1.700000e+01, float -1.000000e+00, float -1.000000e+00>
+
+  constexpr auto Z = -Y;
+  // CHECK: store <4 x float> <float -1.200000e+01, float -1.700000e+01, float 1.000000e+00, float 1.000000e+00>
+
+  // Operator ~ is illegal on floats, so no test for that.
+  constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1};
+  // CHECK: store <4 x i32> <i32 -1, i32 0, i32 0, i32 0>
 }
 
 void FloatVecUsage() {
@@ -560,35 +587,35 @@ void FloatVecUsage() {
 
   constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} <
                      FourFloatsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0>
   constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} >
                      FourFloatsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0>
   constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} ==
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0>
   constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} !=
                      FourFloatsVecSize{4, 3, 3, 1};
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1>
 
   constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0>
   constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 -1>
   constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0>
   constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1>
   constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3;
-  // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0>
+  // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0>
   constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
-  // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1>
+  // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1>
 
   constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} &&
                      FourFloatsVecSize{5, 5, 0, 0};
@@ -613,4 +640,40 @@ void FloatVecUsage() {
 
   constexpr auto Y = CmpSub(a, b);
   // CHECK: store <4 x float> <float 1.200000e+01, float 1.700000e+01, float -1.000000e+00, float -1.000000e+00>
+
+  constexpr auto Z = -Y;
+  // CHECK: store <4 x float> <float -1.200000e+01, float -1.700000e+01, float 1.000000e+00, float 1.000000e+00>
+
+  // Operator ~ is illegal on floats, so no test for that.
+  constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1};
+  // CHECK: store <4 x i32> <i32 -1, i32 0, i32 0, i32 0>
+}
+
+void I128Usage() {
+  constexpr auto a = FourI128VecSize{1, 2, 3, 4};
+  // CHECK: store <4 x i128> <i128 1, i128 2, i128 3, i128 4>
+  constexpr auto b = a < 3;
+  // CHECK: store <4 x i128> <i128 -1, i128 -1, i128 0, i128 0>
+
+  // Operator ~ is illegal on floats, so no test for that.
+  constexpr auto c = ~FourI128VecSize{1, 2, 10, 20};
+  // CHECK: store <4 x i128> <i128 -2, i128 -3, i128 -11, i128 -21>
+
+  constexpr auto d = !FourI128VecSize{0, 1, 8, -1};
+  // CHECK: store <4 x i128> <i128 -1, i128 0, i128 0, i128 0>
+}
+
+void I128VecUsage() {
+  constexpr auto a = FourI128ExtVec{1, 2, 3, 4};
+  // CHECK: store <4 x i128> <i128 1, i128 2, i128 3, i128 4>
+  constexpr auto b = a < 3;
+  // CHECK: store <4 x i128> <i128 -1, i128 -1, i128 0, i128 0>
+
+  // Operator ~ is illegal on floats, so no test for that.
+  constexpr auto c = ~FourI128ExtVec{1, 2, 10, 20};
+  // CHECK: store <4 x i128>  <i128 -2, i128 -3, i128 -11, i128 -21>
+
+  constexpr auto d = !FourI128ExtVec{0, 1, 8, -1};
+  // CHECK: store <4 x i128>  <i128 -1, i128 0, i128 0, i128 0>
 }
+


        


More information about the cfe-commits mailing list