[clang] [Clang] support vector subscript expressions in constant evaluator (WIP) (PR #76379)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 25 20:50:36 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Vikram Hegde (vikramRH)

<details>
<summary>Changes</summary>

Feel free to add additional reviewers as relevant,

I'm yet to update float test cases as I'm not sure whether it would be safe to directly compare float results in static assert. Would it okay to integer cast the results and compare them ?

---

Patch is 42.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76379.diff


3 Files Affected:

- (modified) clang/lib/AST/ExprConstant.cpp (+57-4) 
- (modified) clang/test/CodeGenCXX/temporaries.cpp (+4-8) 
- (modified) clang/test/SemaCXX/constexpr-vectors.cpp (+607-139) 


``````````diff
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..0074b8aa00fc75 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -226,6 +226,12 @@ namespace {
         ArraySize = 0;
         MostDerivedLength = I + 1;
         IsArray = false;
+      } else if (Type->isVectorType()) {
+        const VectorType *CT = Type->castAs<VectorType>();
+        Type = CT->getElementType();
+        ArraySize = CT->getNumElements();
+        MostDerivedLength = I + 1;
+        IsArray = true;
       } else {
         // Path[I] describes a base class.
         ArraySize = 0;
@@ -437,6 +443,15 @@ namespace {
       MostDerivedArraySize = 2;
       MostDerivedPathLength = Entries.size();
     }
+    /// Update this designator to refer to the given vector component.
+    void addVectorUnchecked(const VectorType *VecTy) {
+      Entries.push_back(PathEntry::ArrayIndex(0));
+
+      MostDerivedType = VecTy->getElementType();
+      MostDerivedIsArrayElement = true;
+      MostDerivedArraySize = VecTy->getNumElements();
+      MostDerivedPathLength = Entries.size();
+    }
     void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
     void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
                                    const APSInt &N);
@@ -1732,6 +1747,10 @@ namespace {
       if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
         Designator.addComplexUnchecked(EltTy, Imag);
     }
+    void addVector(EvalInfo &Info, const Expr *E, const VectorType *VecTy) {
+      if (checkSubobject(Info, E, CSK_ArrayIndex))
+        Designator.addVectorUnchecked(VecTy);
+    }
     void clearIsNullPointer() {
       IsNullPtr = false;
     }
@@ -1890,6 +1909,8 @@ static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result,
 static bool EvaluateFixedPoint(const Expr *E, APFixedPoint &Result,
                                EvalInfo &Info);
 
+static bool EvaluateVector(const Expr *E, APValue &Result, EvalInfo &Info);
+
 //===----------------------------------------------------------------------===//
 // Misc utilities
 //===----------------------------------------------------------------------===//
@@ -3278,6 +3299,19 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E,
   return true;
 }
 
+static bool HandeLValueVectorComponent(EvalInfo &Info, const Expr *E,
+                                       LValue &LVal, const VectorType *VecTy,
+                                       APSInt &Adjustment) {
+  LVal.addVector(Info, E, VecTy);
+
+  CharUnits SizeOfComponent;
+  if (!HandleSizeof(Info, E->getExprLoc(), VecTy->getElementType(),
+                    SizeOfComponent))
+    return false;
+  LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfComponent);
+  return true;
+}
+
 /// Try to evaluate the initializer for a variable declaration.
 ///
 /// \param Info   Information about the ongoing evaluation.
@@ -3718,7 +3752,8 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
     }
 
     // If this is our last pass, check that the final object type is OK.
-    if (I == N || (I == N - 1 && ObjType->isAnyComplexType())) {
+    if (I == N || (I == N - 1 &&
+                   (ObjType->isAnyComplexType() || ObjType->isVectorType()))) {
       // Accesses to volatile objects are prohibited.
       if (ObjType.isVolatileQualified() && isFormalAccess(handler.AccessKind)) {
         if (Info.getLangOpts().CPlusPlus) {
@@ -3823,6 +3858,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
         return handler.found(Index ? O->getComplexFloatImag()
                                    : O->getComplexFloatReal(), ObjType);
       }
+    } else if (ObjType->isVectorType()) {
+      // Next Subobject is a vector element
+      uint64_t Index = Sub.Entries[I].getAsArrayIndex();
+      O = &O->getVectorElt(Index);
     } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
       if (Field->isMutable() &&
           !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) {
@@ -8756,14 +8795,28 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
 }
 
 bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
-  // FIXME: Deal with vectors as array subscript bases.
-  if (E->getBase()->getType()->isVectorType() ||
-      E->getBase()->getType()->isSveVLSBuiltinType())
+
+  if (E->getBase()->getType()->isSveVLSBuiltinType())
     return Error(E);
 
   APSInt Index;
   bool Success = true;
 
+  if (E->getBase()->getType()->isVectorType()) {
+    for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) {
+      Success = (SubExpr == E->getBase())
+                    ? EvaluateLValue(SubExpr, Result, Info, true)
+                    : EvaluateInteger(SubExpr, Index, Info);
+    }
+    if (Success) {
+      Success = HandeLValueVectorComponent(
+          Info, E, Result, E->getBase()->getType()->castAs<VectorType>(),
+          Index);
+      return Success;
+    }
+    return false;
+  }
+
   // C++17's rules require us to evaluate the LHS first, regardless of which
   // side is the base.
   for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) {
diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp
index c5adb42a6f1737..aa00cff3aa9014 100644
--- a/clang/test/CodeGenCXX/temporaries.cpp
+++ b/clang/test/CodeGenCXX/temporaries.cpp
@@ -673,16 +673,12 @@ namespace Vector {
     vi4a v;
     vi4b w;
   };
-  // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1rE_
-  // CHECK: store ptr @_ZGRN6Vector1rE_, ptr @_ZN6Vector1rE,
+  // @_ZGRN6Vector1rE_ = internal global i32 0, align 4
+  // @_ZN6Vector1rE = constant ptr @_ZGRN6Vector1rE_, align 8
   int &&r = S().v[1];
 
-  // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1sE_
-  // CHECK: store ptr @_ZGRN6Vector1sE_, ptr @_ZN6Vector1sE,
+  // @_ZGRN6Vector1sE_ = internal global i32 0, align 4
+  // @_ZN6Vector1sE = constant ptr @_ZGRN6Vector1sE_, align 8
   int &&s = S().w[1];
   // FIXME PR16204: The following code leads to an assertion in Sema.
   //int &&s = S().w.y;
diff --git a/clang/test/SemaCXX/constexpr-vectors.cpp b/clang/test/SemaCXX/constexpr-vectors.cpp
index 99b045f888d87c..b00ccb75c86a51 100644
--- a/clang/test/SemaCXX/constexpr-vectors.cpp
+++ b/clang/test/SemaCXX/constexpr-vectors.cpp
@@ -1,10 +1,4 @@
-// RUN: %clang_cc1 -std=c++14 -Wno-unused-value %s -disable-llvm-passes -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s
-
-// FIXME: Unfortunately there is no good way to validate that our values are
-// correct since Vector types don't have operator [] implemented for constexpr.
-// Instead, we need to use filecheck to ensure the emitted IR is correct. Once
-// someone implements array subscript operator for these types as constexpr,
-// this test should modified to jsut use static asserts.
+// RUN: %clang_cc1 -std=c++14 -Wno-unused-value %s -triple x86_64-linux-gnu -emit-llvm -o /dev/null
 
 using FourCharsVecSize __attribute__((vector_size(4))) = char;
 using FourIntsVecSize __attribute__((vector_size(16))) = int;
@@ -155,306 +149,711 @@ constexpr auto CmpBinOr(T t, U u) {
 void CharUsage() {
   constexpr auto a = FourCharsVecSize{6, 3, 2, 1} +
                      FourCharsVecSize{12, 15, 5, 7};
-  // CHECK: store <4 x i8> <i8 18, i8 18, i8 7, i8 8>
+  static_assert(a[0] == 18 , "");
+  static_assert(a[1] == 18 , "");
+  static_assert(a[2] == 7 , "");
+  static_assert(a[3] == 8 , "");
+
   constexpr auto b = FourCharsVecSize{19, 15, 13, 12} -
                      FourCharsVecSize{13, 14, 5, 3};
-  // CHECK: store <4 x i8> <i8 6, i8 1, i8 8, i8 9>
+  static_assert(b[0] == 6 , "");
+  static_assert(b[1] == 1 , "");
+  static_assert(b[2] == 8 , "");
+  static_assert(b[3] == 9 , "");
+
   constexpr auto c = FourCharsVecSize{8, 4, 2, 1} *
                      FourCharsVecSize{3, 4, 5, 6};
-  // CHECK: store <4 x i8> <i8 24, i8 16, i8 10, i8 6>
+  static_assert(c[0] == 24 , "");
+  static_assert(c[1] == 16 , "");
+  static_assert(c[2] == 10 , "");
+  static_assert(c[3] == 6 , "");
+
   constexpr auto d = FourCharsVecSize{12, 12, 10, 10} /
                      FourCharsVecSize{6, 4, 5, 2};
-  // CHECK: store <4 x i8> <i8 2, i8 3, i8 2, i8 5>
+  static_assert(d[0] == 2 , "");
+  static_assert(d[1] == 3 , "");
+  static_assert(d[2] == 2 , "");
+  static_assert(d[3] == 5 , "");
+  
   constexpr auto e = FourCharsVecSize{12, 12, 10, 10} %
                      FourCharsVecSize{6, 4, 4, 3};
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 2, i8 1>
+  static_assert(e[0] == 0 , "");
+  static_assert(e[1] == 0 , "");
+  static_assert(e[2] == 2 , "");
+  static_assert(e[3] == 1 , "");
 
   constexpr auto f = FourCharsVecSize{6, 3, 2, 1} + 3;
-  // CHECK: store <4 x i8> <i8 9, i8 6, i8 5, i8 4>
+  static_assert(f[0] == 9 , "");
+  static_assert(f[1] == 6 , "");
+  static_assert(f[2] == 5 , "");
+  static_assert(f[3] == 4 , "");
+
   constexpr auto g = FourCharsVecSize{19, 15, 12, 10} - 3;
-  // CHECK: store <4 x i8> <i8 16, i8 12, i8 9, i8 7>
+  static_assert(g[0] == 16 , "");
+  static_assert(g[1] == 12 , "");
+  static_assert(g[2] == 9 , "");
+  static_assert(g[3] == 7 , "");
+
   constexpr auto h = FourCharsVecSize{8, 4, 2, 1} * 3;
-  // CHECK: store <4 x i8> <i8 24, i8 12, i8 6, i8 3>
+  static_assert(h[0] == 24 , "");
+  static_assert(h[1] == 12 , "");
+  static_assert(h[2] == 6 , "");
+  static_assert(h[3] == 3 , "");
+
   constexpr auto j = FourCharsVecSize{12, 15, 18, 21} / 3;
-  // CHECK: store <4 x i8> <i8 4, i8 5, i8 6, i8 7>
+  static_assert(j[0] == 4 , "");
+  static_assert(j[1] == 5 , "");
+  static_assert(j[2] == 6 , "");
+  static_assert(j[3] == 7 , "");
+  
   constexpr auto k = FourCharsVecSize{12, 17, 19, 22} % 3;
-  // CHECK: store <4 x i8> <i8 0, i8 2, i8 1, i8 1>
+  static_assert(k[0] == 0 , "");
+  static_assert(k[1] == 2 , "");
+  static_assert(k[2] == 1 , "");
+  static_assert(k[3] == 1 , "");
 
   constexpr auto l = 3 + FourCharsVecSize{6, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 9, i8 6, i8 5, i8 4>
+  static_assert(f[0] == 9 , "");
+  static_assert(f[1] == 6 , "");
+  static_assert(f[2] == 5 , "");
+  static_assert(f[3] == 4 , "");
+
   constexpr auto m = 20 - FourCharsVecSize{19, 15, 12, 10};
-  // CHECK: store <4 x i8> <i8 1, i8 5, i8 8, i8 10>
+  static_assert(m[0] == 1 , "");
+  static_assert(m[1] == 5 , "");
+  static_assert(m[2] == 8 , "");
+  static_assert(m[3] == 10 , "");
+
   constexpr auto n = 3 * FourCharsVecSize{8, 4, 2, 1};
-  // CHECK: store <4 x i8> <i8 24, i8 12, i8 6, i8 3>
+  static_assert(n[0] == 24 , "");
+  static_assert(n[1] == 12 , "");
+  static_assert(n[2] == 6 , "");
+  static_assert(n[3] == 3 , "");
+
   constexpr auto o = 100 / FourCharsVecSize{12, 15, 18, 21};
-  // CHECK: store <4 x i8> <i8 8, i8 6, i8 5, i8 4>
+  static_assert(o[0] == 8 , "");
+  static_assert(o[1] == 6 , "");
+  static_assert(o[2] == 5 , "");
+  static_assert(o[3] == 4 , "");
+
   constexpr auto p = 100 % FourCharsVecSize{12, 15, 18, 21};
-  // CHECK: store <4 x i8> <i8 4, i8 10, i8 10, i8 16>
+  static_assert(p[0] == 4 , "");
+  static_assert(p[1] == 10 , "");
+  static_assert(p[2] == 10 , "");
+  static_assert(p[3] == 16 , "");
 
   constexpr auto q = FourCharsVecSize{6, 3, 2, 1} << FourCharsVecSize{1, 1, 2, 2};
-  // CHECK: store <4 x i8> <i8 12, i8 6, i8 8, i8 4>
+  static_assert(q[0] == 12 , "");
+  static_assert(q[1] == 6 , "");
+  static_assert(q[2] == 8 , "");
+  static_assert(q[3] == 4 , "");
+
   constexpr auto r = FourCharsVecSize{19, 15, 12, 10} >>
                      FourCharsVecSize{1, 1, 2, 2};
-  // CHECK: store <4 x i8> <i8 9, i8 7, i8 3, i8 2>
+  static_assert(r[0] == 9 , "");
+  static_assert(r[1] == 7 , "");
+  static_assert(r[2] == 3 , "");
+  static_assert(r[3] == 2 , "");
+
   constexpr auto s = FourCharsVecSize{6, 3, 5, 10} << 1;
-  // CHECK: store <4 x i8> <i8 12, i8 6, i8 10, i8 20>
+  static_assert(s[0] == 12 , "");
+  static_assert(s[1] == 6 , "");
+  static_assert(s[2] == 10 , "");
+  static_assert(s[3] == 20 , "");
+
   constexpr auto t = FourCharsVecSize{19, 15, 10, 20} >> 1;
-  // CHECK: store <4 x i8> <i8 9, i8 7, i8 5, i8 10>
+  static_assert(t[0] == 9 , "");
+  static_assert(t[1] == 7 , "");
+  static_assert(t[2] == 5 , "");
+  static_assert(t[3] == 10 , "");
+
   constexpr auto u = 12 << FourCharsVecSize{1, 2, 3, 3};
-  // CHECK: store <4 x i8> <i8 24, i8 48, i8 96, i8 96>
+  static_assert(u[0] == 24 , "");
+  static_assert(u[1] == 48 , "");
+  static_assert(u[2] == 96 , "");
+  static_assert(u[3] == 96 , "");
+
   constexpr auto v = 12 >> FourCharsVecSize{1, 2, 2, 1};
-  // CHECK: store <4 x i8> <i8 6, i8 3, i8 3, i8 6>
+  static_assert(v[0] == 6 , "");
+  static_assert(v[1] == 3 , "");
+  static_assert(v[2] == 3 , "");
+  static_assert(v[3] == 6 , "");
 
   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>
+  static_assert(w[0] == -1 , "");
+  static_assert(w[1] == -1 , "");
+  static_assert(w[2] == 0 , "");
+  static_assert(w[3] == 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>
+  static_assert(x[0] == 0 , "");
+  static_assert(x[1] == 0 , "");
+  static_assert(x[2] == -1 , "");
+  static_assert(x[3] == -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>
+  static_assert(y[0] == -1 , "");
+  static_assert(y[1] == -1 , "");
+  static_assert(y[2] == -1 , "");
+  static_assert(y[3] == 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>
+  static_assert(z[0] == 0 , "");
+  static_assert(z[1] == 0 , "");
+  static_assert(z[2] == -1 , "");
+  static_assert(z[3] == -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>
+  static_assert(A[0] == 0 , "");
+  static_assert(A[1] == 0 , "");
+  static_assert(A[2] == -1 , "");
+  static_assert(A[3] == 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>
+  static_assert(B[0] == -1 , "");
+  static_assert(B[1] == -1 , "");
+  static_assert(B[2] == 0 , "");
+  static_assert(B[3] == -1 , "");
 
   constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3;
-  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0>
+  static_assert(C[0] == -1 , "");
+  static_assert(C[1] == -1 , "");
+  static_assert(C[2] == 0 , "");
+  static_assert(C[3] == 0 , "");
+
   constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 -1>
+  static_assert(D[0] == 0 , "");
+  static_assert(D[1] == 0 , "");
+  static_assert(D[2] == 0 , "");
+  static_assert(D[3] == -1 , "");
+
   constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3;
-  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0>
+  static_assert(E[0] == -1 , "");
+  static_assert(E[1] == -1 , "");
+  static_assert(E[2] == -1 , "");
+  static_assert(E[3] == 0 , "");
+
   constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1>
+  static_assert(F[0] == 0 , "");
+  static_assert(F[1] == 0 , "");
+  static_assert(F[2] == -1 , "");
+  static_assert(F[3] == -1 , "");
+
   constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3;
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0>
+  static_assert(G[0] == 0 , "");
+  static_assert(G[1] == 0 , "");
+  static_assert(G[2] == -1 , "");
+  static_assert(G[3] == 0 , "");
+
   constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3;
-  // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1>
+  static_assert(H[0] == -1 , "");
+  static_assert(H[1] == -1 , "");
+  static_assert(H[2] == 0 , "");
+  static_assert(H[3] == -1 , "");
 
   constexpr auto I = FourCharsVecSize{1, 2, 3, 4} &
                      FourCharsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 0, i8 2, i8 2, i8 0>
+  static_assert(I[0] == 0 , "");
+  static_assert(I[1] == 2 , "");
+  static_assert(I[2] == 2 , "");
+  static_assert(I[3] == 0 , "");
+
   constexpr auto J = FourCharsVecSize{1, 2, 3, 4} ^
                      FourCharsVecSize { 4, 3, 2, 1 };
-  // CHECK: store <4 x i8> <i8 5, i8 1, i8 1, i8 5>
+  static_assert(J[0] == 5 , "");
+  static_assert(J[1] == 1 , "");
+  static_assert(J[2] == 1 , "");
+  static_assert(J[3] == 5 , "");
+
   constexpr auto K = FourCharsVecSize{1, 2, 3, 4} |
                      FourCharsVecSize{4, 3, 2, 1};
-  // CHECK: store <4 x i8> <i8 5, i8 3, i8 3, i8 5>
+  static_assert(K[0] == 5 , "");
+  static_assert(K[1] == 3 , "");
+  static_assert(K[2] == 3 , "");
+  static_assert(K[3] == 5 , "");
+
   constexpr auto L = FourCharsVecSize{1, 2, 3, 4} & 3;
-  // CHECK: store <4 x i8> <i8 1, i8 2, i8 3, i8 0>
+  static_assert(L[0] == 1 , "");
+  static_assert(L[1] == 2 , "");
+  static_assert(L[2] == 3 , "");
+  static_assert(L[3] == 0 , "");
+
   constexpr auto M = FourCharsVecSize{1, 2, 3, 4} ^ 3;
-  // CHECK: store <4 x i8> <i8 2, i8 1, i8 0, i8 7>
+  static_assert(M[0] == 2 , "");
+  static_assert(M[1] == 1 , "");
+  static_assert(M[2] == 0 , "");
+  static_assert(M[3] == 7 , "");
+
   constexpr auto N = FourCharsVecSize{1, 2, 3, 4} | 3;
-  // CHECK: store <4 x i8> <i8 3, i8 3, i8 3, i8 7>
+  static_assert(N[0] == 3 , "");
+  static_assert(N[1] == 3 , "");
+  static_assert(N[2] == 3 , "");
+  static_assert(N[3] == 7 , "");
 
   constexpr auto O = FourCharsVecSize{5, 0, 6, 0} &&
                      FourCharsVecSize{5, 5, 0, 0};
-  // CHECK: store <4 x i8> <i8 1, i8 0, i8 0, i8 0>
+  static_assert(O[0] == 1 , "");
+  static_assert(O[1] == 0 , "");
+  static_assert(O[2] == 0 , "");
+  static_assert(O[3] == 0 , "");
+
   constexpr auto P = FourCharsVecSize{5, 0, 6, 0} ||
                      FourCharsVecSize{5, 5, 0, 0};
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0>
+  static_assert(P[0] == 1 , "");
+  static_assert(P[1] == 1 , "");
+  static_assert(P[2] == 1 , "");
+  static_assert(P[3] == 0 , "");
 
   constexpr auto Q = FourCharsVecSize{5, 0, 6, 0} && 3;
-  // CHECK: store <4 x i8> <i8 1, i8 0, i8 1, i8 0>
+  static_assert(Q[0] == 1 , "");
+  static_assert(Q[1] == 0 , "");
+  static_assert(Q[2] == 1 , "");
+  static_assert(Q[3] == 0 , "");
+
   constexpr auto R = FourCharsVecSize{5, 0, 6, 0} || 3;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 1>
+  static_assert(R[0] == 1 , "");
+  static_assert(R[1] == 1 , "");
+  static_assert(R[2] == 1 , "");
+  static_assert(R[3] == 1 , "");
 
   constexpr auto T = CmpMul(a, b);
-  // CHECK: store <4 x i8> <i8 108, i8 18, i8 56, i8 72>
+  static_assert(T[0] == 108 , "");
+  static_assert(T[1] == 18 , "");
+  static_assert(T[2] == 56 , "");
+  static_assert(T[3] == 72 , "");
 
   constexpr auto U = CmpDiv(a, b);
-  // CHECK: store <4 x i8> <i8 3, i8 18, i8 0, i8 0>
+  static_assert(U[0] == 3 , "");
+  static_assert(U[1] == 18 , "");
+  static_assert(U[2] == 0 , "");
+  static_assert(U[3] == 0 , "");
 
   constexpr auto V = CmpRem(a, b);
-  // CHECK: store <4 x i8> <i8 0, i8 0, i8 7, i8 8>
+  static_assert(V[0] == 0 , "");
+  static_assert(V[1] == 0 , "");
+  static_assert(V[2] == 7 , "");
+  static_assert(V[3] == 8 , "");
 
   constexpr auto X = CmpAdd(a, b);
-  // CHECK: store <4 x i8> <i8 24, i8 19, i8 15, i8 17>
+  static_assert(X[0] == 24 , "");
+  static_assert(X[1] == 19 , "");
+  static_assert(X[2] == 15 , "");
+  static_assert(X[3] == 17 , "");
 
   constexpr auto Y = CmpSub(a, b);
-  // CHECK: store <4 x i8> <i8 12, i8 17, i8 -1, i8 -1>
+  static_assert(Y[0] == 12 , "");
+  static_assert(Y[1] == 17 , "");
+  static_assert(Y[2] == -1 , "");
+  static_assert(Y[3] == -1 , "");
 
   constexpr auto InvH = -H;
-  // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1>
+  static_assert(InvH[0] == 1 , "");
+  static_assert(InvH[1] == 1 , "");
+  static_assert(InvH[2] == 0 , "");
+  static_assert(InvH[3] == 1 , "");
+
   constexpr auto Z = CmpLSH(a, InvH);
-  // CHECK: store <4 x i8> <i8 36, i8 36, i8 7, i8 16>
+  static_asser...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/76379


More information about the cfe-commits mailing list