Skip to content

[cir] Implement __builtin_astype for vec4 to vec3#199374

Open
AmrDeveloper wants to merge 1 commit into
llvm:mainfrom
AmrDeveloper:cir_as_type_vec4_vec3
Open

[cir] Implement __builtin_astype for vec4 to vec3#199374
AmrDeveloper wants to merge 1 commit into
llvm:mainfrom
AmrDeveloper:cir_as_type_vec4_vec3

Conversation

@AmrDeveloper
Copy link
Copy Markdown
Member

Implement __builtin_astype for vec4 to vec3

Issue #192311

@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels May 23, 2026
@llvmorg-github-actions
Copy link
Copy Markdown

llvmorg-github-actions Bot commented May 23, 2026

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Amr Hesham (AmrDeveloper)

Changes

Implement __builtin_astype for vec4 to vec3

Issue #192311


Full diff: https://github.com/llvm/llvm-project/pull/199374.diff

2 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+15-5)
  • (modified) clang/test/CIR/CodeGenOpenCL/as_type.cl (+20-12)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 5609bd848f230..911ff14e5ef84 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1430,6 +1430,13 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
     return {};
   }
 
+  mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
+                                 mlir::Value src, unsigned numElementsDst) {
+    static constexpr int64_t mask[] = {0, 1, 2, -1};
+    return builder.createVecShuffle(
+        loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
+  }
+
   // Create cast instructions for converting MLIR value \p Src to MLIR 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
@@ -1516,10 +1523,12 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
     // to vec4 if the original type is not vec4, then a shuffle vector to
     // get a vec3.
     if (numElementsSrc != 3 && numElementsDst == 3) {
-      cgf.cgm.errorNYI(e->getSourceRange(),
-                       "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc != 3, "
-                       "numElemsDst = 3");
-      return {};
+      mlir::Location loc = cgf.getLoc(e->getExprLoc());
+      auto dstElemTy = cast<cir::VectorType>(dstTy).getElementType();
+      auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
+      src = createCastsForTypeOfSameSize(src, dstVec4Ty);
+      src = convertVec3AndVec4(builder, loc, src, 3);
+      return src;
     }
 
     return createCastsForTypeOfSameSize(src, dstTy);
@@ -1987,7 +1996,8 @@ mlir::Value ScalarExprEmitter::emitRem(const BinOpInfo &ops) {
 mlir::Value ScalarExprEmitter::emitAdd(const BinOpInfo &ops) {
   if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
       mlir::isa<cir::PointerType>(ops.rhs.getType()))
-    return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/false);
+    return emitPointerArithmetic(cgf, ops, /*isSubtraction=*/
+                                 false);
 
   const mlir::Location loc = cgf.getLoc(ops.loc);
   if (ops.compType->isSignedIntegerOrEnumerationType()) {
diff --git a/clang/test/CIR/CodeGenOpenCL/as_type.cl b/clang/test/CIR/CodeGenOpenCL/as_type.cl
index 05afd65665e7c..fc5c3bd5a04b6 100644
--- a/clang/test/CIR/CodeGenOpenCL/as_type.cl
+++ b/clang/test/CIR/CodeGenOpenCL/as_type.cl
@@ -5,8 +5,9 @@
 // RUN: FileCheck %s --input-file=%t.ll --check-prefix=LLVM
 
 // RUN: %clang_cc1 %s -emit-llvm -triple spir-unknown-unknown -o %t.ll
-// RUN: FileCheck %s --input-file=%t.ll --check-prefix=OGCG
+// RUN: FileCheck %s --input-file=%t.ll --check-prefix=LLVM
 
+typedef __attribute__(( ext_vector_type(3) )) char char3;
 typedef __attribute__(( ext_vector_type(4) )) char char4;
 
 char4 f4(int x) {
@@ -27,10 +28,6 @@ char4 f4(int x) {
 // LLVM:  %[[RET:.*]] = bitcast i32 %{{.*}} to <4 x i8>
 // LLVM:  ret <4 x i8> %[[RET]]
 
-// OGCG: define {{.*}} <4 x i8> @f4
-// OGCG:  %[[RET:.*]] = bitcast i32 %{{.*}} to <4 x i8>
-// OGCG:  ret <4 x i8> %[[RET]]
-
 int f6(char4 x) {
   return __builtin_astype(x, int);
 }
@@ -49,10 +46,6 @@ int f6(char4 x) {
 // LLVM:  %[[RET:.*]] = bitcast <4 x i8> %{{.*}} to i32
 // LLVM:  ret i32 %[[RET]]
 
-// OGCG: define {{.*}} i32 @f6
-// OGCG:  %[[RET:.*]] = bitcast <4 x i8> %{{.*}} to i32
-// OGCG:  ret i32 %[[RET]]
-
 int* int_to_ptr(int x) {
   return __builtin_astype(x, int*);
 }
@@ -71,6 +64,21 @@ int* int_to_ptr(int x) {
 // LLVM:   %[[INT_TO_PTR:.*]] = inttoptr i32 %{{.*}} to ptr
 // LLVM:   ret ptr %[[INT_TO_PTR]]
 
-// OGCG: define {{.*}} ptr @int_to_ptr
-// OGCG:   %[[INT_TO_PTR:.*]] = inttoptr i32 %{{.*}} to ptr
-// OGCG:   ret ptr %[[INT_TO_PTR]]
+char3 vec4_to_vec_3(char4 x) {
+  return __builtin_astype(x, char3);
+}
+
+// CIR: cir.func {{.*}} @vec4_to_vec_3
+// CIR:   %[[X_ADDR:.*]] = cir.alloca !cir.vector<4 x !s8i>, !cir.ptr<!cir.vector<4 x !s8i>>, ["x", init]
+// CIR:   %[[RET_ADDR:.*]] = cir.alloca !cir.vector<3 x !s8i>, !cir.ptr<!cir.vector<3 x !s8i>>, ["__retval"]
+// CIR:   cir.store %{{.*}}, %[[X_ADDR]] : !cir.vector<4 x !s8i>, !cir.ptr<!cir.vector<4 x !s8i>>
+// CIR:   %[[TMP_X:.*]] = cir.load {{.*}} %[[X_ADDR]] : !cir.ptr<!cir.vector<4 x !s8i>>, !cir.vector<4 x !s8i>
+// CIR:   %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s8i>
+// CIR:   %[[RESULT:.*]] = cir.vec.shuffle(%[[TMP_X]], %[[POISON]] : !cir.vector<4 x !s8i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i] : !cir.vector<3 x !s8i>
+// CIR:   cir.store %[[RESULT]], %[[RET_ADDR]] : !cir.vector<3 x !s8i>, !cir.ptr<!cir.vector<3 x !s8i>>
+// CIR:   %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!cir.vector<3 x !s8i>>, !cir.vector<3 x !s8i>
+// CIR:   cir.return %[[TMP_RET]] : !cir.vector<3 x !s8i>
+
+// LLVM: define {{.*}} <3 x i8> @vec4_to_vec_3
+// LLVM:  %[[RESULT:.*]] = shufflevector <4 x i8> %{{.*}}, <4 x i8> poison, <3 x i32> <i32 0, i32 1, i32 2>
+// LLVM:  ret <3 x i8> %[[RESULT]]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant