https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/212146

>From 49aa8c6c0ca098570cd3df463af75fe30460bf87 Mon Sep 17 00:00:00 2001
From: Amr Hesham <[email protected]>
Date: Thu, 6 Aug 2026 11:02:11 +0200
Subject: [PATCH 1/2] [CIR] Support load/store for Vector of bools

---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          | 26 +---------
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 32 +++++++++++--
 clang/test/CIR/CodeGen/vector-bool.cpp        | 47 +++++++++++++++++++
 3 files changed, 78 insertions(+), 27 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/vector-bool.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index eef1cda1c90f9..34c7efc208ca2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -469,18 +469,10 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
                                        bool isNontemporal) {
 
   if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
-    // Boolean vectors use `iN` as storage type.
-    if (clangVecTy->isExtVectorBoolType())
-      cgm.errorNYI(addr.getPointer().getLoc(),
-                   "emitStoreOfScalar ExtVectorBoolType");
-
     // Handle vectors of size 3 like size 4 for better performance.
-    const mlir::Type elementType = addr.getElementType();
-    const auto vecTy = cast<cir::VectorType>(elementType);
-
     // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed
     assert(!cir::MissingFeatures::cirgenABIInfo());
-    if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)
+    if (clangVecTy->getNumElements() == 3 && !getLangOpts().PreserveVec3Type)
       cgm.errorNYI(addr.getPointer().getLoc(),
                    "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
   }
@@ -707,14 +699,8 @@ LValue CIRGenFunction::emitLValueForFieldInitialization(
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   if (auto *atomicTy = ty->getAs<AtomicType>())
     ty = atomicTy->getValueType();
-
-  if (ty->isExtVectorBoolType()) {
-    cgm.errorNYI("emitToMemory: extVectorBoolType");
-  }
-
   // Unlike in classic codegen CIR, bools are kept as `cir.bool` and BitInts 
are
   // kept as `cir.int<N>` until further lowering
-
   return value;
 }
 
@@ -748,18 +734,10 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address 
addr, bool isVolatile,
   // Traditional LLVM codegen handles thread local separately, CIR handles
   // as part of getAddrOfGlobalVar (GetGlobalOp).
   mlir::Type eltTy = addr.getElementType();
-
   if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
-    if (clangVecTy->isExtVectorBoolType()) {
-      cgm.errorNYI(loc, "emitLoadOfScalar: ExtVectorBoolType");
-      return nullptr;
-    }
-
-    const auto vecTy = cast<cir::VectorType>(eltTy);
-
     // Handle vectors of size 3 like size 4 for better performance.
     assert(!cir::MissingFeatures::cirgenABIInfo());
-    if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)
+    if (clangVecTy->getNumElements() == 3 && !getLangOpts().PreserveVec3Type)
       cgm.errorNYI(addr.getPointer().getLoc(),
                    "emitLoadOfScalar Vec3 & PreserveVec3Type disabled");
   }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 08c2405547dae..8e0ada62a5cb0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -115,6 +115,13 @@ static mlir::Type convertTypeForMemory(const 
mlir::TypeConverter &converter,
                                   dataLayout.getTypeSizeInBits(type));
   }
 
+  if (auto vecTy = mlir::dyn_cast<cir::VectorType>(type)) {
+    if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
+      uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
+      return mlir::IntegerType::get(type.getContext(), bytePadded);
+    }
+  }
+
   // _BitInt(N) keeps its literal width as a value but is stored in a padded
   // integer iM in memory, the same way bool is i1 as a value and i8 in memory.
   // The byte-array storage form for wide split widths is not implemented; a
@@ -194,9 +201,9 @@ lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind 
visibilityKind) {
 /// the memory represetnation of a CIR type is not equal to its scalar
 /// representation.
 static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter,
+                                  const mlir::TypeConverter &converter,
                                   mlir::DataLayout const &dataLayout,
                                   cir::LoadOp op, mlir::Value value) {
-
   // TODO(cir): Handle other types similarly to clang's codegen EmitFromMemory
   if (auto boolTy = mlir::dyn_cast<cir::BoolType>(op.getType())) {
     // Create a cast value from specified size in datalayout to i1
@@ -204,6 +211,15 @@ static mlir::Value 
emitFromMemory(mlir::ConversionPatternRewriter &rewriter,
     return createIntCast(rewriter, value, rewriter.getI1Type());
   }
 
+  // Convert the `iN` back to boolean vectors
+  if (auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
+    if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
+      mlir::Type mlirVecTy = converter.convertType(vecTy);
+      return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), mlirVecTy,
+                                           value);
+    }
+  }
+
   // Truncate the padded storage integer back to the _BitInt's literal width.
   if (auto intTy = mlir::dyn_cast<cir::IntType>(op.getType());
       intTy && intTy.isBitInt())
@@ -228,6 +244,16 @@ static mlir::Value 
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
     return createIntCast(rewriter, value, memType);
   }
 
+  // Boolean vectors use `iN` as storage type
+  if (auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
+    if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
+      uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
+      auto resultTy = mlir::IntegerType::get(origType.getContext(), 
bytePadded);
+      return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
+                                           value);
+    }
+  }
+
   // Sign/zero-extend the _BitInt value to its padded storage integer.
   if (auto intTy = mlir::dyn_cast<cir::IntType>(origType);
       intTy && intTy.isBitInt())
@@ -2244,8 +2270,8 @@ mlir::LogicalResult 
CIRToLLVMLoadOpLowering::matchAndRewrite(
     newLoad->setAttr("cir.riscv_nontemporal_domain", domain);
 
   // Convert adapted result to its original type if needed.
-  mlir::Value result =
-      emitFromMemory(rewriter, dataLayout, op, newLoad.getResult());
+  mlir::Value result = emitFromMemory(rewriter, *getTypeConverter(), 
dataLayout,
+                                      op, newLoad.getResult());
   rewriter.replaceOp(op, result);
   assert(!cir::MissingFeatures::opLoadStoreTbaa());
   return mlir::LogicalResult::success();
diff --git a/clang/test/CIR/CodeGen/vector-bool.cpp 
b/clang/test/CIR/CodeGen/vector-bool.cpp
new file mode 100644
index 0000000000000..b5e8b9b3a2c88
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vector-bool.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+typedef bool v8b __attribute__((ext_vector_type(8)));
+
+void vec_bool_without_padding_needed() {
+  v8b a;
+  v8b b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.vector<8 x 
!cir.bool>>
+// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!cir.vector<8 x 
!cir.bool>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 1
+// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 1
+
+// OGCG: %[[A_ADDR:.*]] = alloca i8, align 1
+// OGCG: %[[B_ADDR:.*]] = alloca i8, align 1
+
+void vec_bool_load_store_without_padding_needed() {
+  v8b a;
+  v8b b;
+  a = b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.vector<8 x 
!cir.bool>>
+// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!cir.vector<8 x 
!cir.bool>>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<8 x 
!cir.bool>>, !cir.vector<8 x !cir.bool>
+// CIR: cir.store {{.*}} %[[TMP_B]], %[[A_ADDR]] : !cir.vector<8 x !cir.bool>, 
!cir.ptr<!cir.vector<8 x !cir.bool>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i8, i64 1, align 1
+// LLVM: %[[B_ADDR:.*]] = alloca i8, i64 1, align 1
+// LLVM: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// LLVM: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// LLVM: %[[TMP_B_I8:.*]] = bitcast <8 x i1> %[[TMP_B_VEC]] to i8
+// LLVM: store i8 %[[TMP_B_I8]], ptr %[[A_ADDR]], align 1
+
+// OGCG: %[[A_ADDR:.*]] = alloca i8, align 1
+// OGCG: %[[B_ADDR:.*]] = alloca i8, align 1
+// OGCG: %[[TMP_B:.*]] = load i8, ptr %b, align 1
+// OGCG: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// OGCG: %[[TMP_B_I8:.*]] = bitcast <8 x i1> %[[TMP_B_VEC]] to i8
+// OGCG: store i8 %[[TMP_B_I8]], ptr %[[A_ADDR]], align 1

>From fbf3ae56ca1856b8016bb2389d5ca231cbdf13eb Mon Sep 17 00:00:00 2001
From: Amr Hesham <[email protected]>
Date: Thu, 6 Aug 2026 18:36:20 +0200
Subject: [PATCH 2/2] Add NYI for constant matrix type

---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 34c7efc208ca2..562ee0b94da95 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -699,6 +699,12 @@ LValue CIRGenFunction::emitLValueForFieldInitialization(
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   if (auto *atomicTy = ty->getAs<AtomicType>())
     ty = atomicTy->getValueType();
+
+  if (ty->isConstantMatrixBoolType()) {
+    cgm.errorNYI("emitToMemory: ConstantMatrixBoolType");
+    return {};
+  }
+
   // Unlike in classic codegen CIR, bools are kept as `cir.bool` and BitInts 
are
   // kept as `cir.int<N>` until further lowering
   return value;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to