Index: cfe/trunk/lib/CodeGen/CGExprScalar.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp @@ -3407,6 +3407,52 @@ 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 @@ // 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 @@ // 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) { Index: cfe/trunk/test/CodeGenOpenCL/as_type.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/as_type.cl +++ cfe/trunk/test/CodeGenOpenCL/as_type.cl @@ -66,3 +66,42 @@ 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> +//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> +//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*); +}