summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven van Haastregt <sven.vanhaastregt@arm.com>2019-12-17 11:10:06 +0000
committerSven van Haastregt <sven.vanhaastregt@arm.com>2019-12-17 11:10:06 +0000
commitdf5a905aa8a868bdb700d88e427491ee56243e30 (patch)
treec31a271a8edde0fa3b85043081d091568758e9ca
parent870f39d310d6a575fb5d303f4027e988bec9e78e (diff)
downloadbcm5719-llvm-df5a905aa8a868bdb700d88e427491ee56243e30.tar.gz
bcm5719-llvm-df5a905aa8a868bdb700d88e427491ee56243e30.zip
[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
-rw-r--r--clang/lib/AST/ExprConstant.cpp25
-rw-r--r--clang/test/CodeGenOpenCLCXX/constexpr.cl28
2 files changed, 53 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 0b658cbb712..7e33b9d354b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7080,6 +7080,31 @@ public:
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 b7175020b81..8c3fad08ea7 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;
+}
OpenPOWER on IntegriCloud