erichkeane created this revision.
erichkeane added reviewers: RKSimon, aaron.ballman, void, efriedma.
erichkeane requested review of this revision.

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.
Additionally, in order to simplify changing of the tests, this ALSo
implements operator-, which simply negates all values of the vector
type.


https://reviews.llvm.org/D115670

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/constexpr-vectors.cpp

Index: clang/test/SemaCXX/constexpr-vectors.cpp
===================================================================
--- clang/test/SemaCXX/constexpr-vectors.cpp
+++ clang/test/SemaCXX/constexpr-vectors.cpp
@@ -204,35 +204,35 @@
 
   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 +277,12 @@
   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);
@@ -348,35 +350,35 @@
 
   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 +423,13 @@
   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);
@@ -471,35 +476,35 @@
 
   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 +529,9 @@
 
   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>
 }
 
 void FloatVecUsage() {
@@ -560,35 +568,35 @@
 
   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 +621,7 @@
 
   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>
 }
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -2912,22 +2912,22 @@
   default:
     llvm_unreachable("unsupported binary operator");
   case BO_EQ:
-    Result = (LHSValue == RHSValue);
+    Result = -(LHSValue == RHSValue);
     break;
   case BO_NE:
-    Result = (LHSValue != RHSValue);
+    Result = -(LHSValue != RHSValue);
     break;
   case BO_LT:
-    Result = (LHSValue < RHSValue);
+    Result = -(LHSValue < RHSValue);
     break;
   case BO_GT:
-    Result = (LHSValue > RHSValue);
+    Result = -(LHSValue > RHSValue);
     break;
   case BO_LE:
-    Result = (LHSValue <= RHSValue);
+    Result = -(LHSValue <= RHSValue);
     break;
   case BO_GE:
-    Result = (LHSValue >= RHSValue);
+    Result = -(LHSValue >= RHSValue);
     break;
   }
 
@@ -10179,7 +10179,8 @@
     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: unary ~, conditional operator (for GNU
     //                 conditional select), shufflevector, ExtVectorElementExpr
   };
 } // end anonymous namespace
@@ -10364,6 +10365,43 @@
   return Success(LHSValue, E);
 }
 
+bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+  Expr *SubExpr = E->getSubExpr();
+  const auto *VD = SubExpr->getType()->castAs<VectorType>();
+  UnaryOperatorKind Op = E->getOpcode();
+
+  APValue SubExprValue;
+  if (!Evaluate(SubExprValue, Info, SubExpr))
+    return false;
+
+  assert(SubExprValue.getVectorLength() == VD->getNumElements() &&
+         "Vector length doesn't match type?");
+
+  switch (Op) {
+  default:
+    // FIXME: Implement the rest of the unary operators.
+    return false;
+  case UO_Minus: {
+    for (unsigned EltNum = 0; EltNum < VD->getNumElements(); ++EltNum) {
+      APValue &Elt = SubExprValue.getVectorElt(EltNum);
+      if (Elt.getKind() == APValue::Int) {
+        Elt.setInt(-Elt.getInt());
+      } else {
+        assert(Elt.getKind() == APValue::Float &&
+               "Vector can only be int or float type");
+        Elt.setFloat(-Elt.getFloat());
+      }
+    }
+    break;
+  }
+  case UO_Plus:
+    // Do nothing, Unary plus is a no-op.
+    break;
+  }
+
+  return Success(SubExprValue, E);
+}
+
 //===----------------------------------------------------------------------===//
 // Array Evaluation
 //===----------------------------------------------------------------------===//
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to