diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index b6b114f0e4b9..cea2cf306d5b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -820,7 +820,48 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { llvm_unreachable("NYI"); } - mlir::Value VisitAsTypeExpr(AsTypeExpr *E) { llvm_unreachable("NYI"); } + + mlir::Value VisitAsTypeExpr(AsTypeExpr *E) { + mlir::Value src = CGF.emitScalarExpr(E->getSrcExpr()); + QualType qualSrcTy = E->getSrcExpr()->getType(); + QualType qualDstTy = E->getType(); + + mlir::Type srcTy = CGF.convertType(qualSrcTy); + mlir::Type dstTy = CGF.convertType(qualDstTy); + auto loc = CGF.getLoc(E->getExprLoc()); + + unsigned numSrcElems = 0, numDstElems = 0; + if (auto v = dyn_cast(srcTy)) + numSrcElems = v.getSize(); + if (auto v = dyn_cast(dstTy)) + numDstElems = v.getSize(); + + // Use bit vector expansion for ext_vector_type boolean vectors. + if (qualDstTy->isExtVectorBoolType()) { + llvm_unreachable("NYI"); + } + + // Going from vec3 to non-vec3 is a special case and requires a shuffle + // vector to get a vec4, then a bitcast if the target type is different. + if (numSrcElems == 3 && numDstElems != 3) { + llvm_unreachable("NYI"); + } + + // Going from non-vec3 to vec3 is a special case and requires a bitcast + // to vec4 if the original type is not vec4, then a shuffle vector to + // get a vec3. + if (numSrcElems != 3 && numDstElems == 3) { + llvm_unreachable("NYI"); + } + + // If types are identical, return the source + if (srcTy == dstTy) + return src; + + // Otherwise, fallback to CIR bitcast + return cir::CastOp::create(Builder, loc, dstTy, cir::CastKind::bitcast, src); + } + mlir::Value VisitAtomicExpr(AtomicExpr *E) { return CGF.emitAtomicExpr(E).getScalarVal(); } diff --git a/clang/test/CIR/CodeGen/OpenCL/as_type.cl b/clang/test/CIR/CodeGen/OpenCL/as_type.cl new file mode 100644 index 000000000000..5a8043b5cf94 --- /dev/null +++ b/clang/test/CIR/CodeGen/OpenCL/as_type.cl @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -cl-std=CL2.0 -fclangir -emit-cir -triple spirv64-unknown-unknown -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll --check-prefix=CIR + +// RUN: %clang_cc1 %s -cl-std=CL2.0 -fclangir -emit-llvm -triple spirv64-unknown-unknown -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll --check-prefix=LLVM + +// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -triple spirv64-unknown-unknown -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll --check-prefix=OG-LLVM + +typedef __attribute__(( ext_vector_type(3) )) char char3; +typedef __attribute__(( ext_vector_type(4) )) char char4; +typedef __attribute__(( ext_vector_type(16) )) char char16; +typedef __attribute__(( ext_vector_type(3) )) int int3; + +//CIR: cir.func @f4(%{{.*}}: !s32i loc({{.*}})) -> !cir.vector +//CIR: %[[x:.*]] = cir.load align(4) %{{.*}} : !cir.ptr +//CIR: cir.cast bitcast %[[x]] : !s32i -> !cir.vector +//LLVM: define spir_func <4 x i8> @f4(i32 %[[x:.*]]) +//LLVM: %[[astype:.*]] = bitcast i32 %[[x]] to <4 x i8> +//LLVM-NOT: shufflevector +//LLVM: ret <4 x i8> %[[astype]] +//OG-LLVM: define spir_func noundef <4 x i8> @f4(i32 noundef %[[x:.*]]) +//OG-LLVM: %[[astype:.*]] = bitcast i32 %[[x]] to <4 x i8> +//OG-LLVM-NOT: shufflevector +//OG-LLVM: ret <4 x i8> %[[astype]] +char4 f4(int x) { + return __builtin_astype(x, char4); +} + +//CIR: cir.func @f6(%{{.*}}: !cir.vector loc({{.*}})) -> !s32i +//CIR: %[[x:.*]] = cir.load align(4) %{{.*}} : !cir.ptr, addrspace(offload_private)>, !cir.vector +//CIR: cir.cast bitcast %[[x]] : !cir.vector -> !s32i +//LLVM: define{{.*}} spir_func i32 @f6(<4 x i8> %[[x:.*]]) +//LLVM: %[[astype:.*]] = bitcast <4 x i8> %[[x]] to i32 +//LLVM-NOT: shufflevector +//LLVM: ret i32 %[[astype]] +//OG-LLVM: define{{.*}} spir_func noundef i32 @f6(<4 x i8> noundef %[[x:.*]]) +//OG-LLVM: %[[astype:.*]] = bitcast <4 x i8> %[[x]] to i32 +//OG-LLVM-NOT: shufflevector +//OG-LLVM: ret i32 %[[astype]] +int f6(char4 x) { + return __builtin_astype(x, int); +} \ No newline at end of file