[clang] 66b112d - [OpenCL] Fix reinterpret_cast of vectors
Ole Strohm via cfe-commits
cfe-commits at lists.llvm.org
Mon May 17 04:44:19 PDT 2021
Author: Ole Strohm
Date: 2021-05-17T12:42:21+01:00
New Revision: 66b112d624a549489fa0af131cf7b632c6181424
URL: https://github.com/llvm/llvm-project/commit/66b112d624a549489fa0af131cf7b632c6181424
DIFF: https://github.com/llvm/llvm-project/commit/66b112d624a549489fa0af131cf7b632c6181424.diff
LOG: [OpenCL] Fix reinterpret_cast of vectors
Fixes issues with vectors in reinterpret_cast in C++ for OpenCL
and adds tests to make sure they both pass without errors and
generate the correct code.
Fixes: PR47977
Reviewed By: Anastasia
Differential Revision: https://reviews.llvm.org/D101519
Added:
clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaExpr.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3a8f41196cc4a..b6143d1d31789 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11640,6 +11640,7 @@ class Sema final {
bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
+ bool areVectorTypesSameSize(QualType srcType, QualType destType);
bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
bool isLaxVectorConversion(QualType srcType, QualType destType);
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 7ed62cc8990eb..439b128e90ea4 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -2335,6 +2335,16 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
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_
diff erent_size;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 948d5eddb43b3..51df757071457 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7341,6 +7341,25 @@ bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) {
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
@@ -7359,18 +7378,7 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
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
diff --git a/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp b/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
new file mode 100644
index 0000000000000..430223f337b77
--- /dev/null
+++ b/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<long>(in[0]);
+ //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+ auto i2 = reinterpret_cast<int2>(l);
+
+ int4 i4;
+ //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
+ auto l2 = reinterpret_cast<long2>(i4);
+}
diff --git a/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp b/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
new file mode 100644
index 0000000000000..0e3d74e5bc2d2
--- /dev/null
+++ b/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<int2>(l1);
+ int2 i2;
+ auto i2_to_l = reinterpret_cast<long>(i2);
+ auto i2_to_i = reinterpret_cast<int>(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of
diff erent size}}
+ auto i2_to_i2 = reinterpret_cast<int2>(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<reserve_id_t>(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
More information about the cfe-commits
mailing list