[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