diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -7080,6 +7080,31 @@ DerivedSuccess(Result, E); } + bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E) { + APValue Val; + if (!Evaluate(Val, Info, E->getBase())) + return false; + + if (Val.isVector()) { + SmallVector Indices; + E->getEncodedElementAccess(Indices); + if (Indices.size() == 1) { + // Return scalar. + return DerivedSuccess(Val.getVectorElt(Indices[0]), E); + } else { + // Construct new APValue vector. + SmallVector 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 --- 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 @@ 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> , <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; +}