[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
This commit is contained in:
Sven van Haastregt 2019-12-17 11:10:06 +00:00
parent 870f39d310
commit df5a905aa8
2 changed files with 53 additions and 0 deletions

View File

@ -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:

View File

@ -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;
}