[clang] df5a905 - [OpenCL] Add ExtVectorElementExpr constant evaluation (PR42387)

Sven van Haastregt via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 17 03:10:50 PST 2019


Author: Sven van Haastregt
Date: 2019-12-17T11:10:06Z
New Revision: df5a905aa8a868bdb700d88e427491ee56243e30

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

LOG: [OpenCL] Add ExtVectorElementExpr constant evaluation (PR42387)

Add constexpr evaluation for ExtVectorElementExpr nodes by evaluating
the underlying vector expression.  Add basic folding for the case that
Evaluate does not return an LValue.

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

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/CodeGenOpenCLCXX/constexpr.cl

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 0b658cbb712f..7e33b9d354b0 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7080,6 +7080,31 @@ class ExprEvaluatorBase
            DerivedSuccess(Result, E);
   }
 
+  bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E) {
+    APValue Val;
+    if (!Evaluate(Val, Info, E->getBase()))
+      return false;
+
+    if (Val.isVector()) {
+      SmallVector<uint32_t, 4> Indices;
+      E->getEncodedElementAccess(Indices);
+      if (Indices.size() == 1) {
+        // Return scalar.
+        return DerivedSuccess(Val.getVectorElt(Indices[0]), E);
+      } else {
+        // Construct new APValue vector.
+        SmallVector<APValue, 4> Elts;
+        for (unsigned I = 0; I < Indices.size(); ++I) {
+          Elts.push_back(Val.getVectorElt(Indices[I]));
+        }
+        APValue VecResult(Elts.data(), Indices.size());
+        return DerivedSuccess(VecResult, E);
+      }
+    }
+
+    return false;
+  }
+
   bool VisitCastExpr(const CastExpr *E) {
     switch (E->getCastKind()) {
     default:

diff  --git a/clang/test/CodeGenOpenCLCXX/constexpr.cl b/clang/test/CodeGenOpenCLCXX/constexpr.cl
index b7175020b814..8c3fad08ea76 100644
--- a/clang/test/CodeGenOpenCLCXX/constexpr.cl
+++ b/clang/test/CodeGenOpenCLCXX/constexpr.cl
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -O0 -emit-llvm -o - | FileCheck %s
 
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
 struct Storage final {
   constexpr const float& operator[](const int index) const noexcept {
     return InternalStorage[index];
@@ -24,3 +27,28 @@ constexpr float FloatConstant = compute();
 kernel void foo(global float *x) {
   *x = FloatConstant;
 }
+
+// Test evaluation of constant vectors.
+// CHECK-LABEL: define spir_kernel void @vecEval
+// CHECK: store i32 3
+// CHECK: store <2 x i32> <i32 22, i32 33>, <2 x i32>
+
+const int oneElt = int4(3).x;
+const int2 twoElts = (int4)(11, 22, 33, 44).yz;
+
+kernel void vecEval(global int *x, global int2 *y) {
+  *x = oneElt;
+  *y = twoElts;
+}
+
+// Test evaluation of vectors initialized through a constexpr function.
+// CHECK-LABEL: define spir_kernel void @vecEval2
+// CHECK: store <2 x i32>
+constexpr int2 addOne(int2 x) {
+  return (int2)(x.x + 1, x.y + 1);
+}
+const int2 fromConstexprFunc = addOne(int2(2));
+
+kernel void vecEval2(global int2 *x) {
+  *x = fromConstexprFunc;
+}


        


More information about the cfe-commits mailing list