Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11717,6 +11717,7 @@ bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); + bool areVectorTypesSameSize(QualType srcType, QualType destType); bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); bool isLaxVectorConversion(QualType srcType, QualType destType); Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2328,6 +2328,16 @@ return TC_Success; } + if (Self.LangOpts.OpenCL && !CStyle) { + if (DestType->isExtVectorType() || SrcType->isExtVectorType()) { + // FIXME: Allow for reinterpret cast between 3 and 4 element vectors + if (Self.areVectorTypesSameSize(SrcType, DestType)) { + Kind = CK_BitCast; + return TC_Success; + } + } + } + // Otherwise, pick a reasonable diagnostic. if (!destIsVector) msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7344,6 +7344,25 @@ matSrcType->getNumColumns() == matDestType->getNumColumns(); } +bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) { + assert(DestTy->isVectorType() || SrcTy->isVectorType()); + + uint64_t SrcLen, DestLen; + QualType SrcEltTy, DestEltTy; + if (!breakDownVectorType(SrcTy, SrcLen, SrcEltTy)) + return false; + if (!breakDownVectorType(DestTy, DestLen, DestEltTy)) + return false; + + // ASTContext::getTypeSize will return the size rounded up to a + // power of 2, so instead of using that, we need to use the raw + // element size multiplied by the element count. + uint64_t SrcEltSize = Context.getTypeSize(SrcEltTy); + uint64_t DestEltSize = Context.getTypeSize(DestEltTy); + + return (SrcLen * SrcEltSize == DestLen * DestEltSize); +} + /// Are the two types lax-compatible vector types? That is, given /// that one of them is a vector, do they have equal storage sizes, /// where the storage size is the number of elements times the element @@ -7362,18 +7381,7 @@ if (srcTy->isScalarType() && destTy->isExtVectorType()) return false; if (destTy->isScalarType() && srcTy->isExtVectorType()) return false; - uint64_t srcLen, destLen; - QualType srcEltTy, destEltTy; - if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false; - if (!breakDownVectorType(destTy, destLen, destEltTy)) return false; - - // ASTContext::getTypeSize will return the size rounded up to a - // power of 2, so instead of using that, we need to use the raw - // element size multiplied by the element count. - uint64_t srcEltSize = Context.getTypeSize(srcEltTy); - uint64_t destEltSize = Context.getTypeSize(destEltTy); - - return (srcLen * srcEltSize == destLen * destEltSize); + return areVectorTypesSameSize(srcTy, destTy); } /// Is this a legal conversion between two types, one of which is Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp =================================================================== --- /dev/null +++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp @@ -0,0 +1,17 @@ +//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s + +typedef int int2 __attribute__((ext_vector_type(2))); +typedef int int4 __attribute__((ext_vector_type(4))); +typedef long long2 __attribute__((ext_vector_type(2))); + +//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i +void bar(global int2 *in) { + //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64 + auto l = reinterpret_cast(in[0]); + //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32> + auto i2 = reinterpret_cast(l); + + int4 i4; + //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64> + auto l2 = reinterpret_cast(i4); +} Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp =================================================================== --- /dev/null +++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only + +typedef int int2 __attribute__((ext_vector_type(2))); +typedef int int3 __attribute__((ext_vector_type(3))); +typedef int int4 __attribute__((ext_vector_type(4))); + +kernel void foo() { + // Testing conversions between vectors and vectors/scalars + long l1; + auto l_to_i2 = reinterpret_cast(l1); + int2 i2; + auto i2_to_l = reinterpret_cast(i2); + auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}} + auto i2_to_i2 = reinterpret_cast(i2); + + // Only integral types (and pointer/references) can be reinterpret casted to themselves. + // Currently this does not include any opencl types. + reserve_id_t r_id1; + auto r_id2 = reinterpret_cast(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}} +}