r283114 - [OpenCL] Fix bug in __builtin_astype causing invalid LLVM cast instructions

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 3 07:41:50 PDT 2016


Author: yaxunl
Date: Mon Oct  3 09:41:50 2016
New Revision: 283114

URL: http://llvm.org/viewvc/llvm-project?rev=283114&view=rev
Log:
[OpenCL] Fix bug in __builtin_astype causing invalid LLVM cast instructions

__builtin_astype is used to cast OpenCL opaque types to other types, as such, it needs to be able to handle casting from and to pointer types correctly.

Current it cannot handle 1) casting between pointers of different addr spaces 2) casting between pointer type and non-pointer types.

This patch fixes that.

Differential Revision: https://reviews.llvm.org/D25123

Modified:
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/test/CodeGenOpenCL/as_type.cl

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=283114&r1=283113&r2=283114&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Oct  3 09:41:50 2016
@@ -3407,6 +3407,52 @@ static Value *ConvertVec3AndVec4(CGBuild
   return Builder.CreateShuffleVector(Src, UnV, Mask);
 }
 
+// Create cast instructions for converting LLVM value \p Src to LLVM type \p
+// DstTy. \p Src has the same size as \p DstTy. Both are single value types
+// but could be scalar or vectors of different lengths, and either can be
+// pointer.
+// There are 4 cases:
+// 1. non-pointer -> non-pointer  : needs 1 bitcast
+// 2. pointer -> pointer          : needs 1 bitcast or addrspacecast
+// 3. pointer -> non-pointer
+//   a) pointer -> intptr_t       : needs 1 ptrtoint
+//   b) pointer -> non-intptr_t   : needs 1 ptrtoint then 1 bitcast
+// 4. non-pointer -> pointer
+//   a) intptr_t -> pointer       : needs 1 inttoptr
+//   b) non-intptr_t -> pointer   : needs 1 bitcast then 1 inttoptr
+// Note: for cases 3b and 4b two casts are required since LLVM casts do not
+// allow casting directly between pointer types and non-integer non-pointer
+// types.
+static Value *createCastsForTypeOfSameSize(CGBuilderTy &Builder,
+                                           const llvm::DataLayout &DL,
+                                           Value *Src, llvm::Type *DstTy,
+                                           StringRef Name = "") {
+  auto SrcTy = Src->getType();
+
+  // Case 1.
+  if (!SrcTy->isPointerTy() && !DstTy->isPointerTy())
+    return Builder.CreateBitCast(Src, DstTy, Name);
+
+  // Case 2.
+  if (SrcTy->isPointerTy() && DstTy->isPointerTy())
+    return Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DstTy, Name);
+
+  // Case 3.
+  if (SrcTy->isPointerTy() && !DstTy->isPointerTy()) {
+    // Case 3b.
+    if (!DstTy->isIntegerTy())
+      Src = Builder.CreatePtrToInt(Src, DL.getIntPtrType(SrcTy));
+    // Cases 3a and 3b.
+    return Builder.CreateBitOrPointerCast(Src, DstTy, Name);
+  }
+
+  // Case 4b.
+  if (!SrcTy->isIntegerTy())
+    Src = Builder.CreateBitCast(Src, DL.getIntPtrType(DstTy));
+  // Cases 4a and 4b.
+  return Builder.CreateIntToPtr(Src, DstTy, Name);
+}
+
 Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
   Value *Src  = CGF.EmitScalarExpr(E->getSrcExpr());
   llvm::Type *DstTy = ConvertType(E->getType());
@@ -3421,7 +3467,8 @@ Value *ScalarExprEmitter::VisitAsTypeExp
   // vector to get a vec4, then a bitcast if the target type is different.
   if (NumElementsSrc == 3 && NumElementsDst != 3) {
     Src = ConvertVec3AndVec4(Builder, CGF, Src, 4);
-    Src = Builder.CreateBitCast(Src, DstTy);
+    Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src,
+                                       DstTy);
     Src->setName("astype");
     return Src;
   }
@@ -3431,13 +3478,15 @@ Value *ScalarExprEmitter::VisitAsTypeExp
   // get a vec3.
   if (NumElementsSrc != 3 && NumElementsDst == 3) {
     auto Vec4Ty = llvm::VectorType::get(DstTy->getVectorElementType(), 4);
-    Src = Builder.CreateBitCast(Src, Vec4Ty);
+    Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src,
+                                       Vec4Ty);
     Src = ConvertVec3AndVec4(Builder, CGF, Src, 3);
     Src->setName("astype");
     return Src;
   }
 
-  return Builder.CreateBitCast(Src, DstTy, "astype");
+  return Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(),
+                                            Src, DstTy, "astype");
 }
 
 Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) {

Modified: cfe/trunk/test/CodeGenOpenCL/as_type.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/as_type.cl?rev=283114&r1=283113&r2=283114&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenOpenCL/as_type.cl (original)
+++ cfe/trunk/test/CodeGenOpenCL/as_type.cl Mon Oct  3 09:41:50 2016
@@ -66,3 +66,42 @@ char3 f7(char3 x) {
 int3 f8(char16 x) {
   return __builtin_astype(x, int3);
 }
+
+//CHECK: define spir_func i32 addrspace(1)* @addr_cast(i32* readnone %[[x:.*]])
+//CHECK: %[[cast:.*]] = addrspacecast i32* %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* addr_cast(int *x) {
+  return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 addrspace(1)* @int_to_ptr(i32 %[[x:.*]])
+//CHECK: %[[cast:.*]] = inttoptr i32 %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* int_to_ptr(int x) {
+  return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 @ptr_to_int(i32* %[[x:.*]])
+//CHECK: %[[cast:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: ret i32 %[[cast]]
+int ptr_to_int(int *x) {
+  return __builtin_astype(x, int);
+}
+
+//CHECK: define spir_func <3 x i8> @ptr_to_char3(i32* %[[x:.*]])
+//CHECK: %[[cast1:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: %[[cast2:.*]] = bitcast i32 %[[cast1]] to <4 x i8>
+//CHECK: %[[astype:.*]] = shufflevector <4 x i8> %[[cast2]], <4 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+//CHECK: ret <3 x i8> %[[astype]]
+char3 ptr_to_char3(int *x) {
+  return  __builtin_astype(x, char3);
+}
+
+//CHECK: define spir_func i32* @char3_to_ptr(<3 x i8> %[[x:.*]])
+//CHECK: %[[astype:.*]] = shufflevector <3 x i8> %[[x]], <3 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+//CHECK: %[[cast1:.*]] = bitcast <4 x i8> %[[astype]] to i32
+//CHECK: %[[cast2:.*]] = inttoptr i32 %[[cast1]] to i32*
+//CHECK: ret i32* %[[cast2]]
+int* char3_to_ptr(char3 x) {
+  return __builtin_astype(x, int*);
+}




More information about the cfe-commits mailing list